Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 2 additions & 39 deletions qiskit/pulse/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@
assembler.
"""
from abc import ABCMeta
from typing import Any, Set, Union
from typing import Any, Union

import numpy as np

from qiskit.circuit import Parameter
from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.circuit.parameterexpression import ParameterExpression
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.utils import deprecated_functionality


class Channel(metaclass=ABCMeta):
Expand Down Expand Up @@ -71,10 +69,6 @@ def __init__(self, index: int):
self._index = index
self._hash = hash((self.__class__.__name__, self._index))

self._parameters = set()
if isinstance(index, ParameterExpression):
self._parameters = index.parameters

@property
def index(self) -> Union[int, ParameterExpression]:
"""Return the index of this channel. The index is a label for a control signal line
Expand All @@ -101,41 +95,10 @@ def _validate_index(self, index: Any) -> None:
if not isinstance(index, (int, np.integer)) and index < 0:
raise PulseError('Channel index must be a nonnegative integer')

@property
@deprecated_functionality
def parameters(self) -> Set:
"""Parameters which determine the channel index."""
return self._parameters

def is_parameterized(self) -> bool:
"""Return True iff the channel is parameterized."""
return isinstance(self.index, ParameterExpression)

@deprecated_functionality
def assign(self, parameter: Parameter, value: ParameterValueType) -> 'Channel':
"""Return a new channel with the input Parameter assigned to value.

Args:
parameter: A parameter in this expression whose value will be updated.
value: The new value to bind to.

Returns:
A new channel with updated parameters.

Raises:
PulseError: If the parameter is not present in the channel.
"""
if parameter not in self.parameters:
raise PulseError('Cannot bind parameters ({}) not present in the channel.'
''.format(parameter))

new_index = self.index.assign(parameter, value)
if not new_index.parameters:
self._validate_index(new_index)
new_index = int(new_index)

return type(self)(new_index)

@property
def name(self) -> str:
"""Return the shorthand alias for this channel, which is based on its type and index."""
Expand Down
65 changes: 1 addition & 64 deletions qiskit/pulse/instructions/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@

"""Call instruction that represents calling a schedule as a subroutine."""

from typing import Optional, Union, Dict, Tuple, Any, Set
from typing import Optional, Union, Dict, Tuple

from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.pulse.channels import Channel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.instructions import instruction
from qiskit.pulse.utils import format_parameter_value, deprecated_functionality


class Call(instruction.Instruction):
Expand Down Expand Up @@ -54,7 +53,6 @@ def __init__(self, subroutine,
value_dict = value_dict or dict()

# initialize parameter template
# TODO remove self._parameter_table
self._arguments = dict()
if subroutine.is_parameterized():
for param in subroutine.parameters:
Expand Down Expand Up @@ -113,71 +111,10 @@ def assigned_subroutine(self):

return subroutine

def _initialize_parameter_table(self,
operands: Tuple[Any]):
"""A helper method to initialize parameter table.

The behavior of the parameter table of the ``Call`` instruction is slightly different from
other instructions. The actual parameter mapper object is defined only in the
subroutine, thus the call instruction doesn't have operand of ``ParameterExpression`` type.
The parameter table is defined as a mapping of parameter objects to assigned values,
whereas the standard instruction stores the mapping to the operand tuple index.

Note that this instruction doesn't immediately bind parameter values when the
:meth:`assign_parameters` method is called with the parameter dictionary.
Instead, this instruction separately keeps the parameter values from the subroutine.
This logic enables the compiler to reuse the subroutine with different parameters.

Args:
operands: List of operands associated with this instruction.
"""
if operands[0].is_parameterized():
for value in operands[0].parameters:
self._parameter_table[value] = value

@deprecated_functionality
def assign_parameters(self,
value_dict: Dict[ParameterExpression, ParameterValueType]
) -> 'Call':
"""Store parameters which will be later assigned to the subroutine.

Parameter values are not immediately assigned. The subroutine with parameters
assigned according to the populated parameter table will be generated only when
:func:`~qiskit.pulse.transforms.inline_subroutines` function is applied to this
instruction. Note that parameter assignment logic creates a copy of subroutine
to avoid the mutation problem. This function is usually applied by the Qiskit
compiler when the program is submitted to the backend.

Args:
value_dict: A mapping from Parameters to either numeric values or another
Parameter expression.

Returns:
Self with updated parameters.
"""
for param_obj, assigned_value in value_dict.items():
for key_obj, value in self._parameter_table.items():
# assign value to parameter expression (it can consist of multiple parameters)
if isinstance(value, ParameterExpression) and param_obj in value.parameters:
new_value = format_parameter_value(value.assign(param_obj, assigned_value))
self._parameter_table[key_obj] = new_value

return self

def is_parameterized(self) -> bool:
"""Return True iff the instruction is parameterized."""
return any(isinstance(value, ParameterExpression) for value in self.arguments.values())

@property
def parameters(self) -> Set:
"""Unassigned parameters which determine the instruction behavior."""
params = set()
for value in self._arguments.values():
if isinstance(value, ParameterExpression):
for param in value.parameters:
params.add(param)
return params

@property
def arguments(self) -> Dict[ParameterExpression, ParameterValueType]:
"""Parameters dictionary to be assigned to subroutine."""
Expand Down
68 changes: 1 addition & 67 deletions qiskit/pulse/instructions/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,10 @@
"""
import warnings
from abc import ABC, abstractproperty
from collections import defaultdict
from typing import Callable, Dict, Iterable, List, Optional, Set, Tuple, Any
from typing import Callable, Iterable, List, Optional, Tuple

from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.pulse.channels import Channel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.utils import format_parameter_value, deprecated_functionality


# pylint: disable=missing-return-doc
Expand Down Expand Up @@ -74,9 +71,6 @@ def __init__(self,
self._name = name
self._hash = None

self._parameter_table = defaultdict(list)
self._initialize_parameter_table(operands)

for channel in self.channels:
if not isinstance(channel, Channel):
raise PulseError("Expected a channel, got {} instead.".format(channel))
Expand Down Expand Up @@ -229,70 +223,10 @@ def append(self, schedule,
time = self.ch_stop_time(*common_channels)
return self.insert(time, schedule, name=name)

@property
@deprecated_functionality
def parameters(self) -> Set:
"""Parameters which determine the instruction behavior."""
return set(self._parameter_table.keys())

def is_parameterized(self) -> bool:
"""Return True iff the instruction is parameterized."""
return any(chan.is_parameterized() for chan in self.channels)

def _initialize_parameter_table(self,
operands: Tuple[Any]):
"""A helper method to initialize parameter table.

Args:
operands: List of operands associated with this instruction.
"""
for idx, op in enumerate(operands):
if isinstance(op, ParameterExpression):
for param in op.parameters:
self._parameter_table[param].append(idx)
elif isinstance(op, Channel) and isinstance(op.index, ParameterExpression):
for param in op.index.parameters:
self._parameter_table[param].append(idx)

@deprecated_functionality
def assign_parameters(self,
value_dict: Dict[ParameterExpression, ParameterValueType]
) -> 'Instruction':
"""Modify and return self with parameters assigned according to the input.

Args:
value_dict: A mapping from Parameters to either numeric values or another
Parameter expression.

Returns:
Self with updated parameters.
"""
new_operands = list(self.operands)

for parameter in self.parameters:
if parameter not in value_dict:
continue

value = value_dict[parameter]
op_indices = self._parameter_table[parameter]
for op_idx in op_indices:
param_expr = new_operands[op_idx]
new_operands[op_idx] = format_parameter_value(param_expr.assign(parameter, value))

# Update parameter table
entry = self._parameter_table.pop(parameter)
if isinstance(value, ParameterExpression):
for new_parameter in value.parameters:
if new_parameter in self._parameter_table:
new_entry = set(entry + self._parameter_table[new_parameter])
self._parameter_table[new_parameter] = list(new_entry)
else:
self._parameter_table[new_parameter] = entry

self._operands = tuple(new_operands)

return self

def draw(self, dt: float = 1, style=None,
filename: Optional[str] = None, interp_method: Optional[Callable] = None,
scale: float = 1, plot_all: bool = False,
Expand Down
32 changes: 3 additions & 29 deletions qiskit/pulse/instructions/play.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
"""An instruction to transmit a given pulse on a ``PulseChannel`` (i.e., those which support
transmitted pulses, such as ``DriveChannel``).
"""
from typing import Dict, Optional, Union, Tuple, Any
from typing import Optional, Union, Tuple

from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.circuit.parameterexpression import ParameterExpression
from qiskit.pulse.channels import PulseChannel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.library.pulse import Pulse
from qiskit.pulse.instructions.instruction import Instruction
from qiskit.pulse.utils import deprecated_functionality
from qiskit.pulse.library.pulse import Pulse


class Play(Instruction):
Expand Down Expand Up @@ -77,31 +76,6 @@ def duration(self) -> Union[int, ParameterExpression]:
"""Duration of this instruction."""
return self.pulse.duration

def _initialize_parameter_table(self,
operands: Tuple[Any]):
"""A helper method to initialize parameter table.

Args:
operands: List of operands associated with this instruction.
"""
super()._initialize_parameter_table(operands)

if any(isinstance(val, ParameterExpression) for val in self.pulse.parameters.values()):
for value in self.pulse.parameters.values():
if isinstance(value, ParameterExpression):
for param in value.parameters:
# Table maps parameter to operand index, 0 for ``pulse``
self._parameter_table[param].append(0)

@deprecated_functionality
def assign_parameters(self,
value_dict: Dict[ParameterExpression, ParameterValueType]
) -> 'Play':
super().assign_parameters(value_dict)
pulse = self.pulse.assign_parameters(value_dict)
self._operands = (pulse, self.channel)
return self

def is_parameterized(self) -> bool:
"""Return True iff the instruction is parameterized."""
return self.pulse.is_parameterized() or super().is_parameterized()
35 changes: 1 addition & 34 deletions qiskit/pulse/library/parametric_pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ class ParametricPulseShapes(Enum):
import math
import numpy as np

from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.circuit.parameterexpression import ParameterExpression
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.library import continuous
from qiskit.pulse.library.discrete import gaussian, gaussian_square, drag, constant
from qiskit.pulse.library.pulse import Pulse
from qiskit.pulse.library.waveform import Waveform
from qiskit.pulse.utils import format_parameter_value, deprecated_functionality


class ParametricPulse(Pulse):
Expand Down Expand Up @@ -88,38 +87,6 @@ def is_parameterized(self) -> bool:
"""Return True iff the instruction is parameterized."""
return any(_is_parameterized(val) for val in self.parameters.values())

@deprecated_functionality
def assign(self, parameter: ParameterExpression,
value: ParameterValueType) -> 'ParametricPulse':
"""Assign one parameter to a value, which can either be numeric or another parameter
expression.
"""
return self.assign_parameters({parameter: value})

@deprecated_functionality
def assign_parameters(self,
value_dict: Dict[ParameterExpression, ParameterValueType]
) -> 'ParametricPulse':
"""Return a new ParametricPulse with parameters assigned.

Args:
value_dict: A mapping from Parameters to either numeric values or another
Parameter expression.

Returns:
New pulse with updated parameters.
"""
if not self.is_parameterized():
return self

new_parameters = {}
for op, op_value in self.parameters.items():
for parameter, value in value_dict.items():
if _is_parameterized(op_value) and parameter in op_value.parameters:
op_value = format_parameter_value(op_value.assign(parameter, value))
new_parameters[op] = op_value
return type(self)(**new_parameters, name=self.name)

def __eq__(self, other: Pulse) -> bool:
return super().__eq__(other) and self.parameters == other.parameters

Expand Down
19 changes: 1 addition & 18 deletions qiskit/pulse/library/pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
from abc import ABC, abstractmethod
from typing import Dict, Optional, Any, Tuple, Union

from qiskit.circuit.parameterexpression import ParameterExpression, ParameterValueType
from qiskit.pulse.utils import deprecated_functionality
from qiskit.circuit.parameterexpression import ParameterExpression


class Pulse(ABC):
Expand Down Expand Up @@ -48,22 +47,6 @@ def is_parameterized(self) -> bool:
"""Return True iff the instruction is parameterized."""
raise NotImplementedError

@deprecated_functionality
@abstractmethod
def assign_parameters(self,
value_dict: Dict[ParameterExpression, ParameterValueType]
) -> 'Pulse':
"""Return a new pulse with parameters assigned.

Args:
value_dict: A mapping from Parameters to either numeric values or another
Parameter expression.

Returns:
New pulse with updated parameters.
"""
raise NotImplementedError

def draw(self,
dt: Any = None, # deprecated
style: Optional[Dict[str, Any]] = None,
Expand Down
Loading