Skip to content

Commit

Permalink
Merge branch 'main' into controlflow/commutative_cancellation
Browse files Browse the repository at this point in the history
  • Loading branch information
jlapeyre authored Jun 28, 2023
2 parents b6cdab4 + d976352 commit 6adab11
Show file tree
Hide file tree
Showing 24 changed files with 147 additions and 62 deletions.
5 changes: 5 additions & 0 deletions constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ qiskit-aer==0.12.0
# tests to flake. See https://github.com/Qiskit/qiskit-terra/issues/10305,
# remove pin when resolving that.
numpy<1.25

# Scipy 1.11 seems to have caused an instability in the Weyl coordinates
# eigensystem code for one of the test cases. See
# https://github.com/Qiskit/qiskit-terra/issues/10345 for current details.
scipy<1.11
3 changes: 0 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,12 @@ disable = [
"consider-using-dict-items",
"consider-using-enumerate",
"consider-using-f-string",
"consider-using-from-import",
"modified-iterating-list",
"nested-min-max",
"no-member",
"no-value-for-parameter",
"non-ascii-name",
"not-context-manager",
"pointless-exception-statement",
"superfluous-parens",
"unknown-option-value",
"unexpected-keyword-arg",
Expand All @@ -105,7 +103,6 @@ disable = [
"use-list-literal",
"use-implicit-booleaness-not-comparison",
"use-maxsplit-arg",
"used-before-assignment",
]

enable = [
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/library/n_local/real_amplitudes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class RealAmplitudes(TwoLocal):
The ``RealAmplitudes`` circuit is a heuristic trial wave function used as Ansatz in chemistry
applications or classification circuits in machine learning. The circuit consists of
of alternating layers of :math:`Y` rotations and :math:`CX` entanglements. The entanglement
alternating layers of :math:`Y` rotations and :math:`CX` entanglements. The entanglement
pattern can be user-defined or selected from a predefined set.
It is called ``RealAmplitudes`` since the prepared quantum states will only have
real amplitudes, the complex part is always 0.
Expand Down
4 changes: 2 additions & 2 deletions qiskit/circuit/library/standard_gates/x.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,9 @@ def qasm(self):
# exporter code (low priority), or we would need to modify 'qelib1.inc' which would be
# needlessly disruptive this late in OQ2's lifecycle. The current OQ2 exporter _always_
# outputs the `include 'qelib1.inc' line. ---Jake, 2022-11-21.
old_name = self.name
self.name = "c3sqrtx"
try:
old_name = self.name
self.name = "c3sqrtx"
return super().qasm()
finally:
self.name = old_name
Expand Down
6 changes: 6 additions & 0 deletions qiskit/pulse/instructions/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from qiskit.pulse.channels import Channel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.instructions import instruction
from qiskit.utils.deprecation import deprecate_func


class Call(instruction.Instruction):
Expand All @@ -30,6 +31,11 @@ class Call(instruction.Instruction):
# Prefix to use for auto naming.
prefix = "call"

@deprecate_func(
since="0.25.0",
additional_msg="Instead, use the pulse builder function "
"qiskit.pulse.builder.call(subroutine) within an active building context.",
)
def __init__(
self,
subroutine,
Expand Down
4 changes: 3 additions & 1 deletion qiskit/pulse/transforms/alignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,9 @@ def align(self, schedule: Schedule) -> Schedule:
_t_center = self.duration * self.func(ind + 1)
_t0 = int(_t_center - 0.5 * child.duration)
if _t0 < 0 or _t0 > self.duration:
PulseError("Invalid schedule position t=%d is specified at index=%d" % (_t0, ind))
raise PulseError(
"Invalid schedule position t=%d is specified at index=%d" % (_t0, ind)
)
aligned.insert(_t0, child, inplace=True)

return aligned
Expand Down
2 changes: 1 addition & 1 deletion qiskit/qpy/binary_io/schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ def read_schedule_block(file_obj, version, metadata_deserializer=None):
QiskitError: QPY version is earlier than block support.
"""
if version < 5:
QiskitError(f"QPY version {version} does not support ScheduleBlock.")
raise QiskitError(f"QPY version {version} does not support ScheduleBlock.")

data = formats.SCHEDULE_BLOCK_HEADER._make(
struct.unpack(
Expand Down
2 changes: 1 addition & 1 deletion qiskit/quantum_info/operators/scalar_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self, dims=None, coeff=1):
QiskitError: If the optional coefficient is invalid.
"""
if not isinstance(coeff, Number):
QiskitError(f"coeff {coeff} must be a number.")
raise QiskitError(f"coeff {coeff} must be a number.")
self._coeff = coeff
super().__init__(input_dims=dims, output_dims=dims)

Expand Down
16 changes: 10 additions & 6 deletions qiskit/quantum_info/operators/symplectic/base_pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,20 +227,24 @@ def commutes(self, other, qargs=None):
return a_dot_b == b_dot_a

def evolve(self, other, qargs=None, frame="h"):
r"""Heisenberg picture evolution of a Pauli by a Clifford.
r"""Performs either Heisenberg (default) or Schrödinger picture
evolution of the Pauli by a Clifford and returns the evolved Pauli.
This returns the Pauli :math:`P^\prime = C^\dagger.P.C`.
Schrödinger picture evolution can be chosen by passing parameter ``frame='s'``.
This option yields a faster calculation.
By choosing the parameter frame='s', this function returns the Schrödinger evolution of the Pauli
:math:`P^\prime = C.P.C^\dagger`. This option yields a faster calculation.
Heisenberg picture evolves the Pauli as :math:`P^\prime = C^\dagger.P.C`.
Schrödinger picture evolves the Pauli as :math:`P^\prime = C.P.C^\dagger`.
Args:
other (BasePauli or QuantumCircuit): The Clifford circuit to evolve by.
qargs (list): a list of qubits to apply the Clifford to.
frame (string): 'h' for Heisenberg or 's' for Schrödinger framework.
frame (string): ``'h'`` for Heisenberg or ``'s'`` for Schrödinger framework.
Returns:
BasePauli: the Pauli :math:`C^\dagger.P.C`.
BasePauli: the Pauli :math:`C^\dagger.P.C` (Heisenberg picture)
or the Pauli :math:`C.P.C^\dagger` (Schrödinger picture).
Raises:
QiskitError: if the Clifford number of qubits and ``qargs`` don't match.
Expand Down
17 changes: 11 additions & 6 deletions qiskit/quantum_info/operators/symplectic/pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,20 +567,25 @@ def anticommutes(self, other, qargs=None):
return np.logical_not(self.commutes(other, qargs=qargs))

def evolve(self, other, qargs=None, frame="h"):
r"""Heisenberg picture evolution of a Pauli by a Clifford.
r"""Performs either Heisenberg (default) or Schrödinger picture
evolution of the Pauli by a Clifford and returns the evolved Pauli.
This returns the Pauli :math:`P^\prime = C^\dagger.P.C`.
Schrödinger picture evolution can be chosen by passing parameter ``frame='s'``.
This option yields a faster calculation.
By choosing the parameter frame='s', this function returns the Schrödinger evolution of the Pauli
:math:`P^\prime = C.P.C^\dagger`. This option yields a faster calculation.
Heisenberg picture evolves the Pauli as :math:`P^\prime = C^\dagger.P.C`.
Schrödinger picture evolves the Pauli as :math:`P^\prime = C.P.C^\dagger`.
Args:
other (Pauli or Clifford or QuantumCircuit): The Clifford operator to evolve by.
qargs (list): a list of qubits to apply the Clifford to.
frame (string): 'h' for Heisenberg or 's' for Schrödinger framework.
frame (string): ``'h'`` for Heisenberg (default) or ``'s'`` for
Schrödinger framework.
Returns:
Pauli: the Pauli :math:`C^\dagger.P.C`.
Pauli: the Pauli :math:`C^\dagger.P.C` (Heisenberg picture)
or the Pauli :math:`C.P.C^\dagger` (Schrödinger picture).
Raises:
QiskitError: if the Clifford number of qubits and qargs don't match.
Expand Down
16 changes: 10 additions & 6 deletions qiskit/quantum_info/operators/symplectic/pauli_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,20 +901,24 @@ def _commutes_with_all(self, other, anti=False):
return inds

def evolve(self, other, qargs=None, frame="h"):
r"""Evolve the Pauli by a Clifford.
r"""Performs either Heisenberg (default) or Schrödinger picture
evolution of the Pauli by a Clifford and returns the evolved Pauli.
This returns the Pauli :math:`P^\prime = C.P.C^\dagger`.
Schrödinger picture evolution can be chosen by passing parameter ``frame='s'``.
This option yields a faster calculation.
By choosing the parameter frame='s', this function returns the Schrödinger evolution of the Pauli
:math:`P^\prime = C.P.C^\dagger`. This option yields a faster calculation.
Heisenberg picture evolves the Pauli as :math:`P^\prime = C^\dagger.P.C`.
Schrödinger picture evolves the Pauli as :math:`P^\prime = C.P.C^\dagger`.
Args:
other (Pauli or Clifford or QuantumCircuit): The Clifford operator to evolve by.
qargs (list): a list of qubits to apply the Clifford to.
frame (string): 'h' for Heisenberg or 's' for Schrödinger framework.
frame (string): ``'h'`` for Heisenberg (default) or ``'s'`` for Schrödinger framework.
Returns:
Pauli: the Pauli :math:`C.P.C^\dagger`.
PauliList: the Pauli :math:`C^\dagger.P.C` (Heisenberg picture)
or the Pauli :math:`C.P.C^\dagger` (Schrödinger picture).
Raises:
QiskitError: if the Clifford number of qubits and qargs don't match.
Expand Down
4 changes: 2 additions & 2 deletions qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ def _add(self, other, qargs=None):
return SparsePauliOp(paulis, coeffs, ignore_pauli_phase=True, copy=False)

def _multiply(self, other):
if not isinstance(other, Number):
raise QiskitError("other is not a number")
if not isinstance(other, (Number, ParameterExpression)):
raise QiskitError("other is neither a Number nor a Parameter/ParameterExpression")
if other == 0:
# Check edge case that we deleted all Paulis
# In this case we return an identity Pauli with a zero coefficient
Expand Down
2 changes: 1 addition & 1 deletion qiskit/visualization/pulse_v2/plotters/matplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def draw(self):
)
self.ax.add_patch(box)
else:
VisualizationError(
raise VisualizationError(
"Data {name} is not supported "
"by {plotter}".format(name=data, plotter=self.__class__.__name__)
)
Expand Down
4 changes: 2 additions & 2 deletions qiskit/visualization/timeline/layouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def qreg_creg_ascending(bits: List[types.Bits]) -> List[types.Bits]:
elif isinstance(bit, circuit.Clbit):
cregs.append(bit)
else:
VisualizationError(f"Unknown bit {bit} is provided.")
raise VisualizationError(f"Unknown bit {bit} is provided.")

with warnings.catch_warnings():
warnings.simplefilter("ignore")
Expand Down Expand Up @@ -109,7 +109,7 @@ def qreg_creg_descending(bits: List[types.Bits]) -> List[types.Bits]:
elif isinstance(bit, circuit.Clbit):
cregs.append(bit)
else:
VisualizationError(f"Unknown bit {bit} is provided.")
raise VisualizationError(f"Unknown bit {bit} is provided.")

qregs = sorted(qregs, key=lambda x: x.index, reverse=True)
cregs = sorted(cregs, key=lambda x: x.index, reverse=True)
Expand Down
2 changes: 1 addition & 1 deletion qiskit/visualization/timeline/plotters/matplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def draw(self):
self.ax.plot(xvals.repeat(len(offsets)), offsets, **data.styles)

else:
VisualizationError(
raise VisualizationError(
"Data {name} is not supported by {plotter}"
"".format(name=data, plotter=self.__class__.__name__)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
deprecations:
- |
The :class:`~qiskit.pulse.instructions.Call` has been deprecated and will
be removed in a future release.
Instead, use the `pulse builder
<https://qiskit.org/documentation/tutorials/circuits_advanced/06_building_pulse_schedules.html>`_
function :func:`~qiskit.pulse.builder.call`
within an active building context.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
features:
- |
Adds support for multiplication of :class:`.SparsePauliOp` objects
with :class:`.Parameter` objects by using the * operator, for example::
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
param = Parameter("a")
op = SparsePauliOp("X")
param * op
fixes:
- |
Fixes issue `#10185 <https://github.com/Qiskit/qiskit-terra/issues/10185>`.
3 changes: 2 additions & 1 deletion test/python/pulse/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ def test_nested_parametrized_instructions(self):
test_waveform = pulse.Constant(100, self.amp0)

param_sched = pulse.Schedule(pulse.Play(test_waveform, self.d0))
call_inst = pulse.instructions.Call(param_sched)
with self.assertWarns(DeprecationWarning):
call_inst = pulse.instructions.Call(param_sched)

sub_block = pulse.ScheduleBlock()
sub_block += call_inst
Expand Down
15 changes: 10 additions & 5 deletions test/python/pulse/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ def test_scheduler_settings(self):
inst_map.add("x", (0,), test_x_sched)

ref_sched = pulse.Schedule()
ref_sched += pulse.instructions.Call(test_x_sched)
with self.assertWarns(DeprecationWarning):
ref_sched += pulse.instructions.Call(test_x_sched)

x_qc = circuit.QuantumCircuit(2)
x_qc.x(0)
Expand Down Expand Up @@ -961,7 +962,8 @@ def test_call(self):
reference += instructions.Delay(20, d1)

ref_sched = pulse.Schedule()
ref_sched += pulse.instructions.Call(reference)
with self.assertWarns(DeprecationWarning):
ref_sched += pulse.instructions.Call(reference)

with pulse.build() as schedule:
with pulse.align_right():
Expand All @@ -981,7 +983,8 @@ def test_call_circuit(self):
reference = inst_map.get("u1", (0,), 0.0)

ref_sched = pulse.Schedule()
ref_sched += pulse.instructions.Call(reference)
with self.assertWarns(DeprecationWarning):
ref_sched += pulse.instructions.Call(reference)

u1_qc = circuit.QuantumCircuit(2)
u1_qc.append(circuit.library.U1Gate(0.0), [0])
Expand Down Expand Up @@ -1009,7 +1012,8 @@ def test_call_circuit_with_cregs(self):
reference = compiler.schedule(reference_qc, self.backend)

ref_sched = pulse.Schedule()
ref_sched += pulse.instructions.Call(reference)
with self.assertWarns(DeprecationWarning):
ref_sched += pulse.instructions.Call(reference)

self.assertScheduleEqual(schedule, ref_sched)

Expand Down Expand Up @@ -1041,7 +1045,8 @@ def test_call_gate_and_circuit(self):
)

reference = pulse.Schedule()
reference += pulse.instructions.Call(h_reference)
with self.assertWarns(DeprecationWarning):
reference += pulse.instructions.Call(h_reference)
reference += cx_reference
reference += measure_reference << reference.duration

Expand Down
9 changes: 6 additions & 3 deletions test/python/pulse/test_instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,16 @@ def setUp(self):

def test_call(self):
"""Test basic call instruction."""
call = instructions.Call(subroutine=self.subroutine)
with self.assertWarns(DeprecationWarning):
call = instructions.Call(subroutine=self.subroutine)

self.assertEqual(call.duration, 10)
self.assertEqual(call.subroutine, self.subroutine)

def test_parameterized_call(self):
"""Test call instruction with parameterized subroutine."""
call = instructions.Call(subroutine=self.function)
with self.assertWarns(DeprecationWarning):
call = instructions.Call(subroutine=self.function)

self.assertTrue(call.is_parameterized())
self.assertEqual(len(call.parameters), 2)
Expand All @@ -393,7 +395,8 @@ def test_assign_parameters_to_call(self):
def test_call_initialize_with_parameter(self):
"""Test call instruction with parameterized subroutine with initial dict."""
init_dict = {self.param1: 0.1, self.param2: 0.5}
call = instructions.Call(subroutine=self.function, value_dict=init_dict)
with self.assertWarns(DeprecationWarning):
call = instructions.Call(subroutine=self.function, value_dict=init_dict)

with pulse.build() as ref_sched:
pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0))
Expand Down
Loading

0 comments on commit 6adab11

Please sign in to comment.