From 62cb99fbdab4c650018c04726cb1e901905ec625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 14:16:34 +0200 Subject: [PATCH 01/10] Deprecate bind parameters --- qiskit/circuit/quantumcircuit.py | 372 ++---------------- qiskit/compiler/assembler.py | 2 +- qiskit/primitives/backend_estimator.py | 2 +- qiskit/primitives/backend_sampler.py | 2 +- qiskit/primitives/estimator.py | 2 +- qiskit/primitives/sampler.py | 2 +- .../passes/synthesis/unitary_synthesis.py | 2 +- .../passes/utils/unroll_forloops.py | 4 +- ...cate-bind-parameters-283c94069e8a9142.yaml | 6 + test/benchmarks/circuit_construction.py | 2 +- .../circuit/test_circuit_load_from_qpy.py | 4 +- .../python/circuit/test_circuit_operations.py | 4 +- test/python/circuit/test_hamiltonian_gate.py | 10 +- test/python/circuit/test_parameters.py | 191 ++++----- test/python/compiler/test_assembler.py | 2 +- .../primitives/test_backend_estimator.py | 2 +- test/python/primitives/test_estimator.py | 4 +- test/python/qasm2/test_circuit_methods.py | 6 +- test/python/qasm2/test_legacy_importer.py | 6 +- test/python/qasm3/test_export.py | 8 +- .../test_optimize_1q_decomposition.py | 12 +- .../transpiler/test_template_matching.py | 8 +- .../visualization/test_circuit_latex.py | 2 +- .../visualization/test_circuit_text_drawer.py | 6 +- test/qpy_compat/test_qpy.py | 4 +- .../circuit/test_circuit_matplotlib_drawer.py | 2 +- 26 files changed, 171 insertions(+), 496 deletions(-) create mode 100644 releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index f0ed85208435..77660a55889a 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -15,12 +15,8 @@ """Quantum circuit object.""" from __future__ import annotations -import collections.abc import copy -import itertools import multiprocessing as mp -import string -import re import warnings import typing from collections import OrderedDict, defaultdict, namedtuple @@ -47,6 +43,7 @@ from qiskit.circuit.parameter import Parameter from qiskit.circuit.exceptions import CircuitError from qiskit.utils import optionals as _optionals +from qiskit.utils.deprecation import deprecate_func from . import _classical_resource_map from ._utils import sort_parameters from .classical import expr @@ -63,7 +60,6 @@ from .delay import Delay from .measure import Measure from .reset import Reset -from .tools import pi_check if typing.TYPE_CHECKING: import qiskit # pylint: disable=cyclic-import @@ -101,23 +97,6 @@ # which operate on either type of bit, but not both at the same time. BitType = TypeVar("BitType", Qubit, Clbit) -# Regex pattern to match valid OpenQASM identifiers -VALID_QASM2_IDENTIFIER = re.compile("[a-z][a-zA-Z_0-9]*") -QASM2_RESERVED = { - "OPENQASM", - "qreg", - "creg", - "include", - "gate", - "opaque", - "U", - "CX", - "measure", - "reset", - "if", - "barrier", -} - class QuantumCircuit: """Create a new circuit. @@ -213,10 +192,6 @@ class QuantumCircuit: instances = 0 prefix = "circuit" - # Class variable OPENQASM header - header = "OPENQASM 2.0;" - extension_lib = 'include "qelib1.inc";' - def __init__( self, *regs: Register | int | Sequence[Bit], @@ -367,6 +342,24 @@ def layout(self) -> Optional[TranspileLayout]: """ return self._layout + @classmethod + @property + @deprecate_func( + since="0.45.0", additional_msg="No alternative will be provided.", is_property=True + ) + def header(cls) -> str: + """The OpenQASM 2.0 header statement.""" + return "OPENQASM 2.0;" + + @classmethod + @property + @deprecate_func( + since="0.45.0", additional_msg="No alternative will be provided.", is_property=True + ) + def extension_lib(cls) -> str: + """The standard OpenQASM 2 import statement.""" + return 'include "qelib1.inc";' + @property def data(self) -> QuantumCircuitData: """Return the circuit data (instructions and context). @@ -1604,7 +1597,13 @@ def qasm( filename: str | None = None, encoding: str | None = None, ) -> str | None: - """Return OpenQASM string. + """Return OpenQASM 2.0 string. + + .. seealso:: + + :func:`.qasm2.dump` and :func:`.qasm2.dumps` + The preferred entry points to the OpenQASM 2 export capabilities. These match the + interface for other serialisers in Qiskit. Args: formatted (bool): Return formatted Qasm string. @@ -1625,126 +1624,12 @@ def qasm( QASM2ExportError: If circuit has free parameters. QASM2ExportError: If an operation that has no OpenQASM 2 representation is encountered. """ - from qiskit.qasm2 import QASM2ExportError # pylint: disable=cyclic-import + from qiskit import qasm2 # pylint: disable=cyclic-import - if self.num_parameters > 0: - raise QASM2ExportError( - "Cannot represent circuits with unbound parameters in OpenQASM 2." - ) - - existing_gate_names = { - "barrier", - "measure", - "reset", - "u3", - "u2", - "u1", - "cx", - "id", - "u0", - "u", - "p", - "x", - "y", - "z", - "h", - "s", - "sdg", - "t", - "tdg", - "rx", - "ry", - "rz", - "sx", - "sxdg", - "cz", - "cy", - "swap", - "ch", - "ccx", - "cswap", - "crx", - "cry", - "crz", - "cu1", - "cp", - "cu3", - "csx", - "cu", - "rxx", - "rzz", - "rccx", - "rc3x", - "c3x", - "c3sx", # This is the Qiskit gate name, but the qelib1.inc name is 'c3sqrtx'. - "c4x", - } - - # Mapping of instruction name to a pair of the source for a definition, and an OQ2 string - # that includes the `gate` or `opaque` statement that defines the gate. - gates_to_define: OrderedDict[str, tuple[Instruction, str]] = OrderedDict() - - regless_qubits = [bit for bit in self.qubits if not self.find_bit(bit).registers] - regless_clbits = [bit for bit in self.clbits if not self.find_bit(bit).registers] - dummy_registers: list[QuantumRegister | ClassicalRegister] = [] - if regless_qubits: - dummy_registers.append(QuantumRegister(name="qregless", bits=regless_qubits)) - if regless_clbits: - dummy_registers.append(ClassicalRegister(name="cregless", bits=regless_clbits)) - register_escaped_names: dict[str, QuantumRegister | ClassicalRegister] = {} - for regs in (self.qregs, self.cregs, dummy_registers): - for reg in regs: - register_escaped_names[ - _make_unique(_qasm_escape_name(reg.name, "reg_"), register_escaped_names) - ] = reg - bit_labels: dict[Qubit | Clbit, str] = { - bit: "%s[%d]" % (name, idx) - for name, register in register_escaped_names.items() - for (idx, bit) in enumerate(register) - } - register_definitions_qasm = "".join( - f"{'qreg' if isinstance(reg, QuantumRegister) else 'creg'} {name}[{reg.size}];\n" - for name, reg in register_escaped_names.items() - ) - instruction_calls = [] - for instruction in self._data: - operation = instruction.operation - if operation.name == "measure": - qubit = instruction.qubits[0] - clbit = instruction.clbits[0] - instruction_qasm = f"measure {bit_labels[qubit]} -> {bit_labels[clbit]};" - elif operation.name == "reset": - instruction_qasm = f"reset {bit_labels[instruction.qubits[0]]};" - elif operation.name == "barrier": - if not instruction.qubits: - # Barriers with no operands are invalid in (strict) OQ2, and the statement - # would have no meaning anyway. - continue - qargs = ",".join(bit_labels[q] for q in instruction.qubits) - instruction_qasm = "barrier;" if not qargs else f"barrier {qargs};" - else: - instruction_qasm = _qasm2_custom_operation_statement( - instruction, existing_gate_names, gates_to_define, bit_labels - ) - instruction_calls.append(instruction_qasm) - instructions_qasm = "".join(f"{call}\n" for call in instruction_calls) - gate_definitions_qasm = "".join(f"{qasm}\n" for _, qasm in gates_to_define.values()) - - out = "".join( - ( - self.header, - "\n", - self.extension_lib, - "\n", - gate_definitions_qasm, - register_definitions_qasm, - instructions_qasm, - ) - ) - - if filename: + out = qasm2.dumps(self) + if filename is not None: with open(filename, "w+", encoding=encoding) as file: - file.write(out) + print(out, file=file) if formatted: _optionals.HAS_PYGMENTS.require_now("formatted OpenQASM 2 output") @@ -1761,7 +1646,9 @@ def qasm( ) print(code) return None - return out + # The old `QuantumCircuit.qasm()` method included a terminating new line that `qasm2.dumps` + # doesn't, so for full compatibility we add it back here. + return out + "\n" def draw( self, @@ -2893,6 +2780,10 @@ def _unroll_param_dict( out[parameter] = value return out + @deprecate_func( + additional_msg=("Use assign_parameters() instead"), + since="0.45.0", + ) def bind_parameters( self, values: Union[Mapping[Parameter, float], Sequence[float]] ) -> "QuantumCircuit": @@ -5012,195 +4903,6 @@ def mapping(self): return self.mapping_cache -# Used by the OQ2 exporter. Just needs to have enough parameters to support the largest standard -# (non-controlled) gate in our standard library. We have to use the same `Parameter` instances each -# time so the equality comparisons will work. -_QASM2_FIXED_PARAMETERS = [Parameter("param0"), Parameter("param1"), Parameter("param2")] - - -def _qasm2_custom_operation_statement( - instruction, existing_gate_names, gates_to_define, bit_labels -): - operation = _qasm2_define_custom_operation( - instruction.operation, existing_gate_names, gates_to_define - ) - # Insert qasm representation of the original instruction - if instruction.clbits: - bits = itertools.chain(instruction.qubits, instruction.clbits) - else: - bits = instruction.qubits - bits_qasm = ",".join(bit_labels[j] for j in bits) - instruction_qasm = f"{_instruction_qasm2(operation)} {bits_qasm};" - return instruction_qasm - - -def _qasm2_define_custom_operation(operation, existing_gate_names, gates_to_define): - """Extract a custom definition from the given operation, and append any necessary additional - subcomponents' definitions to the ``gates_to_define`` ordered dictionary. - - Returns a potentially new :class:`.Instruction`, which should be used for the - :meth:`~.Instruction.qasm` call (it may have been renamed).""" - # pylint: disable=cyclic-import - from qiskit.circuit import library as lib - from qiskit.qasm2 import QASM2ExportError - - if operation.name in existing_gate_names: - return operation - - # Check instructions names or label are valid - escaped = _qasm_escape_name(operation.name, "gate_") - if escaped != operation.name: - operation = operation.copy(name=escaped) - - # These are built-in gates that are known to be safe to construct by passing the correct number - # of `Parameter` instances positionally, and have no other information. We can't guarantee that - # if they've been subclassed, though. This is a total hack; ideally we'd be able to inspect the - # "calling" signatures of Qiskit `Gate` objects to know whether they're safe to re-parameterise. - known_good_parameterized = { - lib.PhaseGate, - lib.RGate, - lib.RXGate, - lib.RXXGate, - lib.RYGate, - lib.RYYGate, - lib.RZGate, - lib.RZXGate, - lib.RZZGate, - lib.XXMinusYYGate, - lib.XXPlusYYGate, - lib.UGate, - lib.U1Gate, - lib.U2Gate, - lib.U3Gate, - } - - # In known-good situations we want to use a manually parametrised object as the source of the - # definition, but still continue to return the given object as the call-site object. - if type(operation) in known_good_parameterized: - parameterized_operation = type(operation)(*_QASM2_FIXED_PARAMETERS[: len(operation.params)]) - elif hasattr(operation, "_qasm2_decomposition"): - new_op = operation._qasm2_decomposition() - parameterized_operation = operation = new_op.copy( - name=_qasm_escape_name(new_op.name, "gate_") - ) - else: - parameterized_operation = operation - - # If there's an _equal_ operation in the existing circuits to be defined, then our job is done. - previous_definition_source, _ = gates_to_define.get(operation.name, (None, None)) - if parameterized_operation == previous_definition_source: - return operation - - # Otherwise, if there's a naming clash, we need a unique name. - if operation.name in gates_to_define: - operation = _rename_operation(operation) - - new_name = operation.name - - if parameterized_operation.params: - parameters_qasm = ( - "(" + ",".join(f"param{i}" for i in range(len(parameterized_operation.params))) + ")" - ) - else: - parameters_qasm = "" - - if operation.num_qubits == 0: - raise QASM2ExportError( - f"OpenQASM 2 cannot represent '{operation.name}, which acts on zero qubits." - ) - if operation.num_clbits != 0: - raise QASM2ExportError( - f"OpenQASM 2 cannot represent '{operation.name}', which acts on {operation.num_clbits}" - " classical bits." - ) - - qubits_qasm = ",".join(f"q{i}" for i in range(parameterized_operation.num_qubits)) - parameterized_definition = getattr(parameterized_operation, "definition", None) - if parameterized_definition is None: - gates_to_define[new_name] = ( - parameterized_operation, - f"opaque {new_name}{parameters_qasm} {qubits_qasm};", - ) - else: - qubit_labels = {bit: f"q{i}" for i, bit in enumerate(parameterized_definition.qubits)} - body_qasm = " ".join( - _qasm2_custom_operation_statement( - instruction, existing_gate_names, gates_to_define, qubit_labels - ) - for instruction in parameterized_definition.data - ) - - # if an inner operation has the same name as the actual operation, it needs to be renamed - if operation.name in gates_to_define: - operation = _rename_operation(operation) - new_name = operation.name - - definition_qasm = f"gate {new_name}{parameters_qasm} {qubits_qasm} {{ {body_qasm} }}" - gates_to_define[new_name] = (parameterized_operation, definition_qasm) - return operation - - -def _rename_operation(operation): - """Returns the operation with a new name following this pattern: {operation name}_{operation id}""" - new_name = f"{operation.name}_{id(operation)}" - updated_operation = operation.copy(name=new_name) - return updated_operation - - -def _qasm_escape_name(name: str, prefix: str) -> str: - """Returns a valid OpenQASM identifier, using `prefix` as a prefix if necessary. `prefix` must - itself be a valid identifier.""" - # Replace all non-ASCII-word characters (letters, digits, underscore) with the underscore. - escaped_name = re.sub(r"\W", "_", name, flags=re.ASCII) - if ( - not escaped_name - or escaped_name[0] not in string.ascii_lowercase - or escaped_name in QASM2_RESERVED - ): - escaped_name = prefix + escaped_name - return escaped_name - - -def _instruction_qasm2(operation): - """Return an OpenQASM 2 string for the instruction.""" - from qiskit.qasm2 import QASM2ExportError # pylint: disable=cyclic-import - - if operation.name == "c3sx": - qasm2_call = "c3sqrtx" - else: - qasm2_call = operation.name - if operation.params: - qasm2_call = "{}({})".format( - qasm2_call, - ",".join([pi_check(i, output="qasm", eps=1e-12) for i in operation.params]), - ) - if operation.condition is not None: - if not isinstance(operation.condition[0], ClassicalRegister): - raise QASM2ExportError( - "OpenQASM 2 can only condition on registers, but got '{operation.condition[0]}'" - ) - qasm2_call = ( - "if(%s==%d) " % (operation.condition[0].name, operation.condition[1]) + qasm2_call - ) - return qasm2_call - - -def _make_unique(name: str, already_defined: collections.abc.Set[str]) -> str: - """Generate a name by suffixing the given stem that is unique within the defined set.""" - if name not in already_defined: - return name - used = {in_use[len(name) :] for in_use in already_defined if in_use.startswith(name)} - characters = (string.digits + string.ascii_letters) if name else string.ascii_letters - for parts in itertools.chain.from_iterable( - itertools.product(characters, repeat=n) for n in itertools.count(1) - ): - suffix = "".join(parts) - if suffix not in used: - return name + suffix - # This isn't actually reachable because the above loop is infinite. - return name - - def _bit_argument_conversion(specifier, bit_sequence, bit_set, type_) -> list[Bit]: """Get the list of bits referred to by the specifier ``specifier``. diff --git a/qiskit/compiler/assembler.py b/qiskit/compiler/assembler.py index 5a9e15c33f0e..9ebcb0783526 100644 --- a/qiskit/compiler/assembler.py +++ b/qiskit/compiler/assembler.py @@ -587,7 +587,7 @@ def _expand_parameters(circuits, run_config): ) circuits = [ - circuit.bind_parameters(binds) for circuit in circuits for binds in parameter_binds + circuit.assign_parameters(binds) for circuit in circuits for binds in parameter_binds ] # All parameters have been expanded and bound, so remove from run_config diff --git a/qiskit/primitives/backend_estimator.py b/qiskit/primitives/backend_estimator.py index d4c733b5133d..740a870e0d65 100644 --- a/qiskit/primitives/backend_estimator.py +++ b/qiskit/primitives/backend_estimator.py @@ -245,7 +245,7 @@ def _call( bound_circuits = [ transpiled_circuits[circuit_index] if len(p) == 0 - else transpiled_circuits[circuit_index].bind_parameters(p) + else transpiled_circuits[circuit_index].assign_parameters(p) for i, (p, n) in enumerate(zip(parameter_dicts, num_observables)) for circuit_index in range(accum[i], accum[i] + n) ] diff --git a/qiskit/primitives/backend_sampler.py b/qiskit/primitives/backend_sampler.py index 6d7f16173980..6510b981b68a 100644 --- a/qiskit/primitives/backend_sampler.py +++ b/qiskit/primitives/backend_sampler.py @@ -140,7 +140,7 @@ def _call( bound_circuits = [ transpiled_circuits[i] if len(value) == 0 - else transpiled_circuits[i].bind_parameters((dict(zip(self._parameters[i], value)))) + else transpiled_circuits[i].assign_parameters((dict(zip(self._parameters[i], value)))) for i, value in zip(circuits, parameter_values) ] bound_circuits = self._bound_pass_manager_run(bound_circuits) diff --git a/qiskit/primitives/estimator.py b/qiskit/primitives/estimator.py index 8afa7783ee40..a63949542d06 100644 --- a/qiskit/primitives/estimator.py +++ b/qiskit/primitives/estimator.py @@ -96,7 +96,7 @@ def _call( bound_circuits.append( self._circuits[i] if len(value) == 0 - else self._circuits[i].bind_parameters(dict(zip(self._parameters[i], value))) + else self._circuits[i].assign_parameters(dict(zip(self._parameters[i], value))) ) sorted_observables = [self._observables[i] for i in observables] expectation_values = [] diff --git a/qiskit/primitives/sampler.py b/qiskit/primitives/sampler.py index 82c637b5d2ba..c96f7b886c1c 100644 --- a/qiskit/primitives/sampler.py +++ b/qiskit/primitives/sampler.py @@ -93,7 +93,7 @@ def _call( bound_circuits.append( self._circuits[i] if len(value) == 0 - else self._circuits[i].bind_parameters(dict(zip(self._parameters[i], value))) + else self._circuits[i].assign_parameters(dict(zip(self._parameters[i], value))) ) qargs_list.append(self._qargs_list[i]) probabilities = [ diff --git a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py index 3e1c4d0a3331..398915f0d5a2 100644 --- a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py +++ b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py @@ -784,7 +784,7 @@ def is_controlled(gate): # rewrite XX of the same strength in terms of it embodiment = XXEmbodiments[type(v)] if len(embodiment.parameters) == 1: - embodiments[strength] = embodiment.bind_parameters([strength]) + embodiments[strength] = embodiment.assign_parameters([strength]) else: embodiments[strength] = embodiment # basis equivalent to CX are well optimized so use for the pi/2 angle if available diff --git a/qiskit/transpiler/passes/utils/unroll_forloops.py b/qiskit/transpiler/passes/utils/unroll_forloops.py index c83a47f72eec..8cde3874adcb 100644 --- a/qiskit/transpiler/passes/utils/unroll_forloops.py +++ b/qiskit/transpiler/passes/utils/unroll_forloops.py @@ -59,7 +59,9 @@ def run(self, dag): unrolled_dag = circuit_to_dag(body).copy_empty_like() for index_value in indexset: - bound_body = body.bind_parameters({loop_param: index_value}) if loop_param else body + bound_body = ( + body.assign_parameters({loop_param: index_value}) if loop_param else body + ) unrolled_dag.compose(circuit_to_dag(bound_body), inplace=True) dag.substitute_node_with_dag(forloop_op, unrolled_dag) diff --git a/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml new file mode 100644 index 000000000000..181ab70d7b1f --- /dev/null +++ b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + The method :meth:`~qiskit.QuantumCircuit.bind_parameters` is now deprecated. Its functionality + overlapped highly with :meth:`~qiskit.QuantumCircuit.assign_parameters`, and can be totally + replaced by it. Please use :meth:`~qiskit.QuantumCircuit.assign_parameters` instead. diff --git a/test/benchmarks/circuit_construction.py b/test/benchmarks/circuit_construction.py index 6e984823dff0..1a7f58b8e934 100644 --- a/test/benchmarks/circuit_construction.py +++ b/test/benchmarks/circuit_construction.py @@ -93,4 +93,4 @@ def setup(self, width, gates, params): self.circuit, self.params = build_parameterized_circuit(width, gates, params) def time_bind_params(self, _, __, ___): - self.circuit.bind_parameters({x: 3.14 for x in self.params}) + self.circuit.assign_parameters({x: 3.14 for x in self.params}) diff --git a/test/python/circuit/test_circuit_load_from_qpy.py b/test/python/circuit/test_circuit_load_from_qpy.py index 2e07157b8898..2e429cbcee12 100644 --- a/test/python/circuit/test_circuit_load_from_qpy.py +++ b/test/python/circuit/test_circuit_load_from_qpy.py @@ -250,7 +250,9 @@ def test_parameter(self): qpy_file.seek(0) new_circ = load(qpy_file)[0] self.assertEqual(qc, new_circ) - self.assertEqual(qc.bind_parameters({theta: 3.14}), new_circ.bind_parameters({theta: 3.14})) + self.assertEqual( + qc.assign_parameters({theta: 3.14}), new_circ.assign_parameters({theta: 3.14}) + ) self.assertDeprecatedBitProperties(qc, new_circ) def test_bound_parameter(self): diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py index 81e9e0f214fd..43c60ae4c767 100644 --- a/test/python/circuit/test_circuit_operations.py +++ b/test/python/circuit/test_circuit_operations.py @@ -760,7 +760,7 @@ def test_bind_global_phase(self): circuit = QuantumCircuit(1, global_phase=x) self.assertEqual(circuit.parameters, {x}) - bound = circuit.bind_parameters({x: 2}) + bound = circuit.assign_parameters({x: 2}) self.assertEqual(bound.global_phase, 2) self.assertEqual(bound.parameters, set()) @@ -774,7 +774,7 @@ def test_bind_parameter_in_phase_and_gate(self): ref = QuantumCircuit(1, global_phase=2) ref.rx(2, 0) - bound = circuit.bind_parameters({x: 2}) + bound = circuit.assign_parameters({x: 2}) self.assertEqual(bound, ref) self.assertEqual(bound.parameters, set()) diff --git a/test/python/circuit/test_hamiltonian_gate.py b/test/python/circuit/test_hamiltonian_gate.py index 2ae7ec1c43f4..a27818489447 100644 --- a/test/python/circuit/test_hamiltonian_gate.py +++ b/test/python/circuit/test_hamiltonian_gate.py @@ -77,7 +77,7 @@ def test_1q_hamiltonian(self): qc.x(qr[0]) theta = Parameter("theta") qc.append(HamiltonianGate(matrix, theta), [qr[0]]) - qc = qc.bind_parameters({theta: 1}) + qc = qc.assign_parameters({theta: 1}) # test of text drawer self.log.info(qc) @@ -107,7 +107,7 @@ def test_2q_hamiltonian(self): theta = Parameter("theta") uni2q = HamiltonianGate(matrix, theta) qc.append(uni2q, [qr[0], qr[1]]) - qc2 = qc.bind_parameters({theta: -np.pi / 2}) + qc2 = qc.assign_parameters({theta: -np.pi / 2}) dag = circuit_to_dag(qc2) nodes = dag.two_qubit_ops() self.assertEqual(len(nodes), 1) @@ -131,7 +131,7 @@ def test_3q_hamiltonian(self): qc.cx(qr[3], qr[2]) # test of text drawer self.log.info(qc) - qc = qc.bind_parameters({theta: -np.pi / 2}) + qc = qc.assign_parameters({theta: -np.pi / 2}) dag = circuit_to_dag(qc) nodes = dag.multi_qubit_ops() self.assertEqual(len(nodes), 1) @@ -150,7 +150,7 @@ def test_qobj_with_hamiltonian(self): uni = HamiltonianGate(matrix, theta, label="XIZ") qc.append(uni, [qr[0], qr[1], qr[3]]) qc.cx(qr[3], qr[2]) - qc = qc.bind_parameters({theta: np.pi / 2}) + qc = qc.assign_parameters({theta: np.pi / 2}) qobj = qiskit.compiler.assemble(qc) instr = qobj.experiments[0].instructions[1] self.assertEqual(instr.name, "hamiltonian") @@ -167,6 +167,6 @@ def test_decomposes_into_correct_unitary(self): theta = Parameter("theta") uni2q = HamiltonianGate(matrix, theta) qc.append(uni2q, [0, 1]) - qc = qc.bind_parameters({theta: -np.pi / 2}).decompose() + qc = qc.assign_parameters({theta: -np.pi / 2}).decompose() decomposed_ham = qc.data[0].operation self.assertEqual(decomposed_ham, UnitaryGate(Operator.from_label("XY"))) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 31b73c55afca..a68869953ac2 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -180,11 +180,10 @@ def test_bind_parameters_anonymously(self): order = [phase] + v[:] + [x, y, z] param_dict = dict(zip(order, params)) - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - bqc_anonymous = getattr(qc, assign_fun)(params) - bqc_list = getattr(qc, assign_fun)(param_dict) - self.assertEqual(bqc_anonymous, bqc_list) + + bqc_anonymous = qc.assign_parameters(params) + bqc_list = qc.assign_parameters(param_dict) + self.assertEqual(bqc_anonymous, bqc_list) def test_bind_parameters_allow_unknown(self): """Test binding parameters allowing unknown parameters.""" @@ -193,7 +192,7 @@ def test_bind_parameters_allow_unknown(self): c = a.bind({a: 1, b: 1}, allow_unknown_parameters=True) self.assertEqual(c, a.bind({a: 1})) - @data(QuantumCircuit.assign_parameters, QuantumCircuit.bind_parameters) + @data(QuantumCircuit.assign_parameters, QuantumCircuit.assign_parameters) def test_bind_parameters_custom_definition_global_phase(self, assigner): """Test that a custom gate with a parametrised `global_phase` is assigned correctly.""" x = Parameter("x") @@ -327,15 +326,12 @@ def test_fix_variable(self): qc.rx(theta, qr) qc.u(0, theta, 0, qr) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - bqc = getattr(qc, assign_fun)({theta: 0.5}) - self.assertEqual(float(bqc.data[0].operation.params[0]), 0.5) - self.assertEqual(float(bqc.data[1].operation.params[1]), 0.5) - bqc = getattr(qc, assign_fun)({theta: 0.6}) - self.assertEqual(float(bqc.data[0].operation.params[0]), 0.6) - self.assertEqual(float(bqc.data[1].operation.params[1]), 0.6) + bqc = qc.assign_parameters({theta: 0.5}) + self.assertEqual(float(bqc.data[0].operation.params[0]), 0.5) + self.assertEqual(float(bqc.data[1].operation.params[1]), 0.5) + bqc = qc.assign_parameters({theta: 0.6}) + self.assertEqual(float(bqc.data[0].operation.params[0]), 0.6) + self.assertEqual(float(bqc.data[1].operation.params[1]), 0.6) def test_multiple_parameters(self): """Test setting multiple parameters""" @@ -384,15 +380,10 @@ def test_partial_binding(self): qc.rx(theta, qr) qc.u(0, theta, x, qr) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - pqc = getattr(qc, assign_fun)({theta: 2}) - - self.assertEqual(pqc.parameters, {x}) - - self.assertEqual(float(pqc.data[0].operation.params[0]), 2) - self.assertEqual(float(pqc.data[1].operation.params[1]), 2) + pqc = qc.assign_parameters({theta: 2}) + self.assertEqual(pqc.parameters, {x}) + self.assertEqual(float(pqc.data[0].operation.params[0]), 2) + self.assertEqual(float(pqc.data[1].operation.params[1]), 2) @data(True, False) def test_mixed_binding(self, inplace): @@ -420,21 +411,15 @@ def test_expression_partial_binding(self): qc = QuantumCircuit(qr) qc.rx(theta + phi, qr) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - pqc = getattr(qc, assign_fun)({theta: 2}) - - self.assertEqual(pqc.parameters, {phi}) + pqc = qc.assign_parameters({theta: 2}) + self.assertEqual(pqc.parameters, {phi}) + self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) + self.assertEqual(str(pqc.data[0].operation.params[0]), "phi + 2") - self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) - self.assertEqual(str(pqc.data[0].operation.params[0]), "phi + 2") - - fbqc = getattr(pqc, assign_fun)({phi: 1.0}) - - self.assertEqual(fbqc.parameters, set()) - self.assertIsInstance(fbqc.data[0].operation.params[0], float) - self.assertEqual(float(fbqc.data[0].operation.params[0]), 3) + fbqc = pqc.assign_parameters({phi: 1.0}) + self.assertEqual(fbqc.parameters, set()) + self.assertIsInstance(fbqc.data[0].operation.params[0], float) + self.assertEqual(float(fbqc.data[0].operation.params[0]), 3) def test_two_parameter_expression_binding(self): """Verify that for a circuit with parameters theta and phi that @@ -464,21 +449,15 @@ def test_expression_partial_binding_zero(self): qc = QuantumCircuit(1) qc.p(theta * phi, 0) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - pqc = getattr(qc, assign_fun)({theta: 0}) - - self.assertEqual(pqc.parameters, {phi}) + pqc = qc.assign_parameters({theta: 0}) + self.assertEqual(pqc.parameters, {phi}) + self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) + self.assertEqual(str(pqc.data[0].operation.params[0]), "0") - self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) - self.assertEqual(str(pqc.data[0].operation.params[0]), "0") - - fbqc = getattr(pqc, assign_fun)({phi: 1}) - - self.assertEqual(fbqc.parameters, set()) - self.assertIsInstance(fbqc.data[0].operation.params[0], int) - self.assertEqual(float(fbqc.data[0].operation.params[0]), 0) + fbqc = pqc.assign_parameters({phi: 1}) + self.assertEqual(fbqc.parameters, set()) + self.assertIsInstance(fbqc.data[0].operation.params[0], int) + self.assertEqual(float(fbqc.data[0].operation.params[0]), 0) def test_raise_if_assigning_params_not_in_circuit(self): """Verify binding parameters which are not present in the circuit raises an error.""" @@ -488,18 +467,15 @@ def test_raise_if_assigning_params_not_in_circuit(self): qr = QuantumRegister(1) qc = QuantumCircuit(qr) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - qc = QuantumCircuit(qr) - with self.subTest(assign_fun=assign_fun): - qc.p(0.1, qr[0]) - self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1}) - qc.p(x, qr[0]) - self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1, y: 2}) - qc.p(z[1], qr[0]) - self.assertRaises(CircuitError, getattr(qc, assign_fun), {z: [3, 4, 5]}) - self.assertRaises(CircuitError, getattr(qc, assign_fun), {"a_str": 6}) - self.assertRaises(CircuitError, getattr(qc, assign_fun), {None: 7}) + qc = QuantumCircuit(qr) + qc.p(0.1, qr[0]) + self.assertRaises(CircuitError, qc.assign_parameters({x: 1})) + qc.p(x, qr[0]) + self.assertRaises(CircuitError, qc.assign_parameters({x: 1, y: 2})) + qc.p(z[1], qr[0]) + self.assertRaises(CircuitError, qc.assign_parameters({z: [3, 4, 5]})) + self.assertRaises(CircuitError, qc.assign_parameters({"a_str": 6})) + self.assertRaises(CircuitError, qc.assign_parameters({None: 7})) def test_gate_multiplicity_binding(self): """Test binding when circuit contains multiple references to same gate""" @@ -509,13 +485,11 @@ def test_gate_multiplicity_binding(self): gate = RZGate(theta) qc.append(gate, [0], []) qc.append(gate, [0], []) - # test for both `bind_parameters` and `assign_parameters` - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - qc2 = getattr(qc, assign_fun)({theta: 1.0}) - self.assertEqual(len(qc2._parameter_table), 0) - for instruction in qc2.data: - self.assertEqual(float(instruction.operation.params[0]), 1.0) + + qc2 = qc.assign_parameters({theta: 1.0}) + self.assertEqual(len(qc2._parameter_table), 0) + for instruction in qc2.data: + self.assertEqual(float(instruction.operation.params[0]), 1.0) def test_calibration_assignment(self): """That that calibration mapping and the schedules they map are assigned together.""" @@ -661,17 +635,14 @@ def test_circuit_generation(self): backend = BasicAer.get_backend("qasm_simulator") qc_aer = transpile(qc, backend) - # generate list of circuits - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - circs = [] - theta_list = numpy.linspace(0, numpy.pi, 20) - for theta_i in theta_list: - circs.append(getattr(qc_aer, assign_fun)({theta: theta_i})) - qobj = assemble(circs) - for index, theta_i in enumerate(theta_list): - res = float(qobj.experiments[index].instructions[0].params[0]) - self.assertTrue(math.isclose(res, theta_i), f"{res} != {theta_i}") + circs = [] + theta_list = numpy.linspace(0, numpy.pi, 20) + for theta_i in theta_list: + circs.append(qc_aer.assign_parameters({theta: theta_i})) + qobj = assemble(circs) + for index, theta_i in enumerate(theta_list): + res = float(qobj.experiments[index].instructions[0].params[0]) + self.assertTrue(math.isclose(res, theta_i), f"{res} != {theta_i}") def test_circuit_composition(self): """Test preservation of parameters when combining circuits.""" @@ -736,12 +707,11 @@ def test_bind_ryrz_vector(self): qc.barrier() theta_vals = numpy.linspace(0, 1, len(theta)) * numpy.pi self.assertEqual(set(qc.parameters), set(theta.params)) - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - bqc = getattr(qc, assign_fun)({theta: theta_vals}) - for instruction in bqc.data: - if hasattr(instruction.operation, "params") and instruction.operation.params: - self.assertIn(float(instruction.operation.params[0]), theta_vals) + + bqc = qc.assign_parameters({theta: theta_vals}) + for instruction in bqc.data: + if hasattr(instruction.operation, "params") and instruction.operation.params: + self.assertIn(float(instruction.operation.params[0]), theta_vals) def test_compile_vector(self): """Test compiling a circuit with an unbound ParameterVector""" @@ -908,10 +878,8 @@ def test_repeated_gates_to_dag_and_back(self): double_qc = qc.compose(qc) test_qc = dag_to_circuit(circuit_to_dag(double_qc)) - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - bound_test_qc = getattr(test_qc, assign_fun)({theta: 1}) - self.assertEqual(len(bound_test_qc.parameters), 0) + bound_test_qc = test_qc.assign_parameters({theta: 1}) + self.assertEqual(len(bound_test_qc.parameters), 0) def test_rebinding_instruction_copy(self): """Test rebinding a copied instruction does not modify the original.""" @@ -925,19 +893,17 @@ def test_rebinding_instruction_copy(self): qc1 = QuantumCircuit(1) qc1.append(instr, [0]) - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - output1 = getattr(qc1, assign_fun)({theta: 0.1}).decompose() - output2 = getattr(qc1, assign_fun)({theta: 0.2}).decompose() + output1 = qc1.assign_parameters({theta: 0.1}).decompose() + output2 = qc1.assign_parameters({theta: 0.2}).decompose() - expected1 = QuantumCircuit(1) - expected1.rx(0.1, 0) + expected1 = QuantumCircuit(1) + expected1.rx(0.1, 0) - expected2 = QuantumCircuit(1) - expected2.rx(0.2, 0) + expected2 = QuantumCircuit(1) + expected2.rx(0.2, 0) - self.assertEqual(expected1, output1) - self.assertEqual(expected2, output2) + self.assertEqual(expected1, output1) + self.assertEqual(expected2, output2) @combine(target_type=["gate", "instruction"], parameter_type=["numbers", "parameters"]) def test_decompose_propagates_bound_parameters(self, target_type, parameter_type): @@ -1053,13 +1019,10 @@ def test_executing_parameterized_instruction_bound_early(self, target_type): unbound_qc.append(sub_inst, [0, 1], []) unbound_qc.measure(0, 0) - for assign_fun in ["bind_parameters", "assign_parameters"]: - with self.subTest(assign_fun=assign_fun): - bound_qc = getattr(unbound_qc, assign_fun)({theta: numpy.pi / 2}) - - shots = 1024 - job = execute(bound_qc, backend=BasicAer.get_backend("qasm_simulator"), shots=shots) - self.assertDictAlmostEqual(job.result().get_counts(), {"1": shots}, 0.05 * shots) + bound_qc = unbound_qc.assign_parameters({theta: numpy.pi / 2}) + shots = 1024 + job = execute(bound_qc, backend=BasicAer.get_backend("qasm_simulator"), shots=shots) + self.assertDictAlmostEqual(job.result().get_counts(), {"1": shots}, 0.05 * shots) def test_num_parameters(self): """Test the num_parameters property.""" @@ -1199,7 +1162,7 @@ def test_compile_with_ufunc(self): for x in theta: self.assertIn(x, transpiled.parameters) - bound = transpiled.bind_parameters({theta: [-1, pi, pi, pi, 1, 1, 1]}) + bound = transpiled.assign_parameters({theta: [-1, pi, pi, pi, 1, 1, 1]}) expected = QuantumCircuit(7) expected.rx(1.0, 0) @@ -1459,7 +1422,7 @@ def test_complex_parameter_bound_to_real(self): with self.subTest("simple 1j * x"): qc = QuantumCircuit(1) qc.rx(1j * x, 0) - bound = qc.bind_parameters({x: 1j}) + bound = qc.assign_parameters({x: 1j}) ref = QuantumCircuit(1) ref.rx(-1, 0) self.assertEqual(bound, ref) @@ -1467,7 +1430,7 @@ def test_complex_parameter_bound_to_real(self): with self.subTest("more complex expression"): qc = QuantumCircuit(1) qc.rx(0.5j * x - y * y + 2 * y, 0) - bound = qc.bind_parameters({x: -4, y: 1j}) + bound = qc.assign_parameters({x: -4, y: 1j}) ref = QuantumCircuit(1) ref.rx(1, 0) self.assertEqual(bound, ref) @@ -1479,7 +1442,7 @@ def test_complex_angle_raises_when_not_supported(self): qc.r(x, 1j * x, 0) with self.subTest("binding x to 0 yields real parameters"): - bound = qc.bind_parameters({x: 0}) + bound = qc.assign_parameters({x: 0}) ref = QuantumCircuit(1) ref.r(0, 0, 0) self.assertEqual(bound, ref) @@ -1487,7 +1450,7 @@ def test_complex_angle_raises_when_not_supported(self): with self.subTest("binding x to 1 yields complex parameters"): # RGate does not support complex parameters with self.assertRaises(CircuitError): - bound = qc.bind_parameters({x: 1}) + bound = qc.assign_parameters({x: 1}) def test_operating_on_a_parameter_with_a_non_float_will_raise(self): """Verify operations between a Parameter and a non-float will raise.""" diff --git a/test/python/compiler/test_assembler.py b/test/python/compiler/test_assembler.py index debd47e3a48b..2641012857a6 100644 --- a/test/python/compiler/test_assembler.py +++ b/test/python/compiler/test_assembler.py @@ -244,7 +244,7 @@ def test_assemble_unroll_parametervector(self): qc.barrier() qc.measure([0, 1], [0, 1]) - qc.bind_parameters({pv1: [0.1, 0.2, 0.3], pv2: [0.4, 0.5, 0.6]}) + qc.assign_parameters({pv1: [0.1, 0.2, 0.3], pv2: [0.4, 0.5, 0.6]}) qobj = assemble(qc, parameter_binds=[{pv1: [0.1, 0.2, 0.3], pv2: [0.4, 0.5, 0.6]}]) diff --git a/test/python/primitives/test_backend_estimator.py b/test/python/primitives/test_backend_estimator.py index df9387ee070b..44af5791cddc 100644 --- a/test/python/primitives/test_backend_estimator.py +++ b/test/python/primitives/test_backend_estimator.py @@ -107,7 +107,7 @@ def test_estimator_run(self, backend): def test_estimator_run_no_params(self, backend): """test for estimator without parameters""" backend.set_options(seed_simulator=123) - circuit = self.ansatz.bind_parameters([0, 1, 1, 2, 3, 5]) + circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5]) est = BackendEstimator(backend=backend) result = est.run([circuit], [self.observable]).result() self.assertIsInstance(result, EstimatorResult) diff --git a/test/python/primitives/test_estimator.py b/test/python/primitives/test_estimator.py index 4a9209e7fa8a..5b620dc7c0e5 100644 --- a/test/python/primitives/test_estimator.py +++ b/test/python/primitives/test_estimator.py @@ -95,7 +95,7 @@ def test_estimator_run(self): def test_estiamtor_run_no_params(self): """test for estimator without parameters""" - circuit = self.ansatz.bind_parameters([0, 1, 1, 2, 3, 5]) + circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5]) est = Estimator() result = est.run([circuit], [self.observable]).result() self.assertIsInstance(result, EstimatorResult) @@ -259,7 +259,7 @@ def test_run_numpy_params(self): def test_run_with_operator(self): """test for run with Operator as an observable""" - circuit = self.ansatz.bind_parameters([0, 1, 1, 2, 3, 5]) + circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5]) matrix = Operator( [ [-1.06365335, 0.0, 0.0, 0.1809312], diff --git a/test/python/qasm2/test_circuit_methods.py b/test/python/qasm2/test_circuit_methods.py index fdd30211b73f..ff1e5842715c 100644 --- a/test/python/qasm2/test_circuit_methods.py +++ b/test/python/qasm2/test_circuit_methods.py @@ -376,7 +376,7 @@ def test_from_qasm_str_custom_gate4(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll("u", circuit, expected) @@ -400,7 +400,7 @@ def test_from_qasm_str_custom_gate5(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll("u", circuit, expected) @@ -426,7 +426,7 @@ def test_from_qasm_str_custom_gate6(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll(["rx", "ry"], circuit, expected) diff --git a/test/python/qasm2/test_legacy_importer.py b/test/python/qasm2/test_legacy_importer.py index 070646b1d9ea..891c23233d35 100644 --- a/test/python/qasm2/test_legacy_importer.py +++ b/test/python/qasm2/test_legacy_importer.py @@ -389,7 +389,7 @@ def test_from_qasm_str_custom_gate4(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll("u", circuit, expected) @@ -413,7 +413,7 @@ def test_from_qasm_str_custom_gate5(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll("u", circuit, expected) @@ -439,7 +439,7 @@ def test_from_qasm_str_custom_gate6(self): qr = QuantumRegister(1, name="qr") expected = QuantumCircuit(qr, name="circuit") expected.append(my_gate, [qr[0]]) - expected = expected.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + expected = expected.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqualUnroll(["rx", "ry"], circuit, expected) diff --git a/test/python/qasm3/test_export.py b/test/python/qasm3/test_export.py index bcec1699be68..26876667abc7 100644 --- a/test/python/qasm3/test_export.py +++ b/test/python/qasm3/test_export.py @@ -392,7 +392,7 @@ def test_custom_gate_with_bound_parameter(self): custom = QuantumCircuit(1) custom.rx(parameter_a, 0) - custom_gate = custom.bind_parameters({parameter_a: 0.5}).to_gate() + custom_gate = custom.assign_parameters({parameter_a: 0.5}).to_gate() custom_gate.name = "custom" circuit = QuantumCircuit(1) @@ -453,8 +453,8 @@ def test_reused_custom_parameter(self): custom.rx(parameter_a, 0) circuit = QuantumCircuit(1) - circuit.append(custom.bind_parameters({parameter_a: 0.5}).to_gate(), [0]) - circuit.append(custom.bind_parameters({parameter_a: 1}).to_gate(), [0]) + circuit.append(custom.assign_parameters({parameter_a: 0.5}).to_gate(), [0]) + circuit.append(custom.assign_parameters({parameter_a: 1}).to_gate(), [0]) circuit_name_0 = circuit.data[0].operation.definition.name circuit_name_1 = circuit.data[1].operation.definition.name @@ -1390,7 +1390,7 @@ def test_custom_gate_used_in_loop_scope(self): custom = QuantumCircuit(1) custom.rx(parameter_a, 0) - custom_gate = custom.bind_parameters({parameter_a: 0.5}).to_gate() + custom_gate = custom.assign_parameters({parameter_a: 0.5}).to_gate() custom_gate.name = "custom" loop_body = QuantumCircuit(1) diff --git a/test/python/transpiler/test_optimize_1q_decomposition.py b/test/python/transpiler/test_optimize_1q_decomposition.py index 9f3cd3669afa..5d3ebb3d7245 100644 --- a/test/python/transpiler/test_optimize_1q_decomposition.py +++ b/test/python/transpiler/test_optimize_1q_decomposition.py @@ -287,8 +287,8 @@ def test_single_parameterized_circuit(self, basis): result = passmanager.run(qc) self.assertTrue( - Operator(qc.bind_parameters({theta: 3.14})).equiv( - Operator(result.bind_parameters({theta: 3.14})) + Operator(qc.assign_parameters({theta: 3.14})).equiv( + Operator(result.assign_parameters({theta: 3.14})) ) ) @@ -324,8 +324,8 @@ def test_parameterized_circuits(self, basis): result = passmanager.run(qc) self.assertTrue( - Operator(qc.bind_parameters({theta: 3.14})).equiv( - Operator(result.bind_parameters({theta: 3.14})) + Operator(qc.assign_parameters({theta: 3.14})).equiv( + Operator(result.assign_parameters({theta: 3.14})) ) ) @@ -364,8 +364,8 @@ def test_parameterized_expressions_in_circuits(self, basis): result = passmanager.run(qc) self.assertTrue( - Operator(qc.bind_parameters({theta: 3.14, phi: 10})).equiv( - Operator(result.bind_parameters({theta: 3.14, phi: 10})) + Operator(qc.assign_parameters({theta: 3.14, phi: 10})).equiv( + Operator(result.assign_parameters({theta: 3.14, phi: 10})) ) ) diff --git a/test/python/transpiler/test_template_matching.py b/test/python/transpiler/test_template_matching.py index e6d8ed2cff7a..95294c7a2ab1 100644 --- a/test/python/transpiler/test_template_matching.py +++ b/test/python/transpiler/test_template_matching.py @@ -396,8 +396,8 @@ def test_unbound_parameters_in_rzx_template(self): # however these are equivalent if the operators are the same theta_set = 0.42 self.assertTrue( - Operator(circuit_in.bind_parameters({theta: theta_set})).equiv( - circuit_out.bind_parameters({theta: theta_set}) + Operator(circuit_in.assign_parameters({theta: theta_set})).equiv( + circuit_out.assign_parameters({theta: theta_set}) ) ) @@ -483,8 +483,8 @@ def test_two_parameter_template(self): alpha_set = 0.37 beta_set = 0.42 self.assertTrue( - Operator(circuit_in.bind_parameters({alpha: alpha_set, beta: beta_set})).equiv( - circuit_out.bind_parameters({alpha: alpha_set, beta: beta_set}) + Operator(circuit_in.assign_parameters({alpha: alpha_set, beta: beta_set})).equiv( + circuit_out.assign_parameters({alpha: alpha_set, beta: beta_set}) ) ) diff --git a/test/python/visualization/test_circuit_latex.py b/test/python/visualization/test_circuit_latex.py index e61a3b2f0bf3..b5f06529702a 100644 --- a/test/python/visualization/test_circuit_latex.py +++ b/test/python/visualization/test_circuit_latex.py @@ -305,7 +305,7 @@ def test_big_gates(self): matrix = np.zeros((4, 4)) theta = Parameter("theta") circuit.append(HamiltonianGate(matrix, theta), [qr[1], qr[2]]) - circuit = circuit.bind_parameters({theta: 1}) + circuit = circuit.assign_parameters({theta: 1}) circuit.isometry(np.eye(4, 4), list(range(3, 5)), []) circuit_drawer(circuit, filename=filename, output="latex_source") diff --git a/test/python/visualization/test_circuit_text_drawer.py b/test/python/visualization/test_circuit_text_drawer.py index 671756bf0d82..8ff1c1a8b3fe 100644 --- a/test/python/visualization/test_circuit_text_drawer.py +++ b/test/python/visualization/test_circuit_text_drawer.py @@ -1933,7 +1933,7 @@ def test_text_bound_parameters(self): qr = QuantumRegister(1, name="qr") circuit = QuantumCircuit(qr, name="circuit") circuit.append(my_u2, [qr[0]]) - circuit = circuit.bind_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) + circuit = circuit.assign_parameters({phi: 3.141592653589793, lam: 3.141592653589793}) self.assertEqual(str(_text_circuit_drawer(circuit)), expected) @@ -5095,7 +5095,7 @@ def test_draw_hamiltonian_single(self): matrix = numpy.zeros((2, 2)) theta = Parameter("theta") circuit.append(HamiltonianGate(matrix, theta), [qr[0]]) - circuit = circuit.bind_parameters({theta: 1}) + circuit = circuit.assign_parameters({theta: 1}) self.assertEqual(circuit.draw(output="text").single_string(), expected) def test_draw_hamiltonian_multi(self): @@ -5115,7 +5115,7 @@ def test_draw_hamiltonian_multi(self): matrix = numpy.zeros((4, 4)) theta = Parameter("theta") circuit.append(HamiltonianGate(matrix, theta), [qr[0], qr[1]]) - circuit = circuit.bind_parameters({theta: 1}) + circuit = circuit.assign_parameters({theta: 1}) self.assertEqual(circuit.draw(output="text").single_string(), expected) diff --git a/test/qpy_compat/test_qpy.py b/test/qpy_compat/test_qpy.py index 7eb9b1a6dd99..4e9429f248fe 100755 --- a/test/qpy_compat/test_qpy.py +++ b/test/qpy_compat/test_qpy.py @@ -768,8 +768,8 @@ def assert_equal(reference, qpy, count, version_parts, bind=None): ) sys.stderr.write(msg) sys.exit(4) - reference = reference.bind_parameters(bind) - qpy = qpy.bind_parameters(bind) + reference = reference.assign_parameters(bind) + qpy = qpy.assign_parameters(bind) if reference != qpy: msg = ( f"Reference Circuit {count}:\n{reference}\nis not equivalent to " diff --git a/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py b/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py index 9a348a1957be..82a65b33e131 100644 --- a/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py +++ b/test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py @@ -542,7 +542,7 @@ def test_big_gates(self): matrix = np.zeros((4, 4)) theta = Parameter("theta") circuit.append(HamiltonianGate(matrix, theta), [qr[1], qr[2]]) - circuit = circuit.bind_parameters({theta: 1}) + circuit = circuit.assign_parameters({theta: 1}) circuit.isometry(np.eye(4, 4), list(range(3, 5)), []) fname = "big_gates.png" From c232cc979852d099e0ae5b0a05b1d7f52091161e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 14:32:30 +0200 Subject: [PATCH 02/10] Replace bind in docstring --- qiskit/circuit/parameter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/circuit/parameter.py b/qiskit/circuit/parameter.py index fae84a71852b..75d51ed592d1 100644 --- a/qiskit/circuit/parameter.py +++ b/qiskit/circuit/parameter.py @@ -45,7 +45,7 @@ class Parameter(ParameterExpression): qc.draw('mpl') # bind the parameters after circuit to create a bound circuit - bc = qc.bind_parameters({phi: 3.14}) + bc = qc.assign_parameters({phi: 3.14}) bc.measure_all() bc.draw('mpl') """ From 5eb7146cf244d571e7969a8249cbb916544c4a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 15:19:54 +0200 Subject: [PATCH 03/10] Test deprecation warning --- test/python/circuit/test_parameters.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index a68869953ac2..e7afb72a9ae8 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -192,15 +192,22 @@ def test_bind_parameters_allow_unknown(self): c = a.bind({a: 1, b: 1}, allow_unknown_parameters=True) self.assertEqual(c, a.bind({a: 1})) - @data(QuantumCircuit.assign_parameters, QuantumCircuit.assign_parameters) - def test_bind_parameters_custom_definition_global_phase(self, assigner): + def test_circuit_bind_parameters_raises(self): + """Test that the deprecated bind_parameters method raises a deprecation warning.""" + qc = QuantumCircuit(1) + qc.rx(Parameter("x"), 0) + + with self.assertWarns(DeprecationWarning): + _ = qc.bind_parameters([1]) + + def test_bind_parameters_custom_definition_global_phase(self): """Test that a custom gate with a parametrised `global_phase` is assigned correctly.""" x = Parameter("x") custom = QuantumCircuit(1, global_phase=x).to_gate() base = QuantumCircuit(1) base.append(custom, [0], []) - test = Operator(assigner(base, {x: math.pi})) + test = Operator(QuantumCircuit.assign_parameters(base, {x: math.pi})) expected = Operator(numpy.array([[-1, 0], [0, -1]])) self.assertEqual(test, expected) @@ -465,7 +472,6 @@ def test_raise_if_assigning_params_not_in_circuit(self): y = Parameter("y") z = ParameterVector("z", 3) qr = QuantumRegister(1) - qc = QuantumCircuit(qr) qc = QuantumCircuit(qr) qc.p(0.1, qr[0]) From 5cbf14ab6a27b923976a5917ddf726098659bd89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 15:20:14 +0200 Subject: [PATCH 04/10] Remove bind_parameters in algorithms --- qiskit/algorithms/eigen_solvers/vqd.py | 14 +++++++++----- qiskit/algorithms/eigensolvers/vqd.py | 2 +- .../evolvers/trotterization/trotter_qrte.py | 2 +- qiskit/algorithms/gradients/reverse/bind.py | 2 +- qiskit/algorithms/minimum_eigen_solvers/vqe.py | 4 ++-- qiskit/algorithms/optimizers/qnspsa.py | 4 ++-- qiskit/algorithms/optimizers/spsa.py | 2 +- qiskit/algorithms/time_evolvers/pvqd/pvqd.py | 4 ++-- test/python/algorithms/test_aux_ops_evaluator.py | 2 +- .../algorithms/test_observables_evaluator.py | 6 +++--- test/python/algorithms/test_vqe.py | 2 +- .../time_evolvers/variational/test_var_qrte.py | 2 +- 12 files changed, 25 insertions(+), 21 deletions(-) diff --git a/qiskit/algorithms/eigen_solvers/vqd.py b/qiskit/algorithms/eigen_solvers/vqd.py index 72e3dd306647..068cdd08cd14 100644 --- a/qiskit/algorithms/eigen_solvers/vqd.py +++ b/qiskit/algorithms/eigen_solvers/vqd.py @@ -473,7 +473,9 @@ def _eval_aux_ops( list_op = ListOp(aux_operators) aux_op_meas = expectation.convert(StateFn(list_op, is_measurement=True)) - aux_op_expect = aux_op_meas.compose(CircuitStateFn(self.ansatz.bind_parameters(parameters))) + aux_op_expect = aux_op_meas.compose( + CircuitStateFn(self.ansatz.assign_parameters(parameters)) + ) aux_op_expect_sampled = sampler.convert(aux_op_expect) # compute means @@ -611,7 +613,9 @@ def compute_eigenvalues( eigenvalue = ( StateFn(operator, is_measurement=True) - .compose(CircuitStateFn(self.ansatz.bind_parameters(result.optimal_parameters[-1]))) + .compose( + CircuitStateFn(self.ansatz.assign_parameters(result.optimal_parameters[-1])) + ) .reduce() .eval() ) @@ -620,7 +624,7 @@ def compute_eigenvalues( result.eigenstates.append(self._get_eigenstate(result.optimal_parameters[-1])) if aux_operators is not None: - bound_ansatz = self.ansatz.bind_parameters(result.optimal_point[-1]) + bound_ansatz = self.ansatz.assign_parameters(result.optimal_point[-1]) aux_value = eval_observables( self.quantum_instance, bound_ansatz, aux_operators, expectation=expectation ) @@ -715,7 +719,7 @@ def get_energy_evaluation( for state in range(step - 1): - prev_circ = self.ansatz.bind_parameters(prev_states[state]) + prev_circ = self.ansatz.assign_parameters(prev_states[state]) overlap_op.append(~CircuitStateFn(prev_circ) @ CircuitStateFn(self.ansatz)) def energy_evaluation(parameters): @@ -751,7 +755,7 @@ def energy_evaluation(parameters): def _get_eigenstate(self, optimal_parameters) -> list[float] | dict[str, int]: """Get the simulation outcome of the ansatz, provided with parameters.""" - optimal_circuit = self.ansatz.bind_parameters(optimal_parameters) + optimal_circuit = self.ansatz.assign_parameters(optimal_parameters) state_fn = self._circuit_sampler.convert(StateFn(optimal_circuit)).eval() if self.quantum_instance.is_statevector: state = state_fn.primitive.data # VectorStateFn -> Statevector -> np.array diff --git a/qiskit/algorithms/eigensolvers/vqd.py b/qiskit/algorithms/eigensolvers/vqd.py index cbb4d56af313..59f07d8a918b 100644 --- a/qiskit/algorithms/eigensolvers/vqd.py +++ b/qiskit/algorithms/eigensolvers/vqd.py @@ -271,7 +271,7 @@ def compute_eigenvalues( initial_point = validate_initial_point(initial_points[step - 1], self.ansatz) if step > 1: - prev_states.append(self.ansatz.bind_parameters(result.optimal_points[-1])) + prev_states.append(self.ansatz.assign_parameters(result.optimal_points[-1])) self._eval_count = 0 energy_evaluation = self._get_evaluate_energy( diff --git a/qiskit/algorithms/evolvers/trotterization/trotter_qrte.py b/qiskit/algorithms/evolvers/trotterization/trotter_qrte.py index 4c4af495e6ba..538635c67f42 100644 --- a/qiskit/algorithms/evolvers/trotterization/trotter_qrte.py +++ b/qiskit/algorithms/evolvers/trotterization/trotter_qrte.py @@ -204,7 +204,7 @@ def evolve(self, evolution_problem: EvolutionProblem) -> EvolutionResult: f"PauliSumOp | SummedOp, {type(hamiltonian)} provided." ) if isinstance(hamiltonian, OperatorBase): - hamiltonian = hamiltonian.bind_parameters(evolution_problem.param_value_dict) + hamiltonian = hamiltonian.assign_parameters(evolution_problem.param_value_dict) if isinstance(hamiltonian, SummedOp): hamiltonian = self._summed_op_to_pauli_sum_op(hamiltonian) # the evolution gate diff --git a/qiskit/algorithms/gradients/reverse/bind.py b/qiskit/algorithms/gradients/reverse/bind.py index 5380090b7425..7660f7c836d0 100644 --- a/qiskit/algorithms/gradients/reverse/bind.py +++ b/qiskit/algorithms/gradients/reverse/bind.py @@ -26,7 +26,7 @@ def bind( """Bind parameters in a circuit (or list of circuits). This method also allows passing parameter binds to parameters that are not in the circuit, - and thereby differs to :meth:`.QuantumCircuit.bind_parameters`. + and thereby differs to :meth:`.QuantumCircuit.assign_parameters`. Args: circuits: Input circuit(s). diff --git a/qiskit/algorithms/minimum_eigen_solvers/vqe.py b/qiskit/algorithms/minimum_eigen_solvers/vqe.py index bf9304e4d6b7..3ca342f9894d 100644 --- a/qiskit/algorithms/minimum_eigen_solvers/vqe.py +++ b/qiskit/algorithms/minimum_eigen_solvers/vqe.py @@ -569,7 +569,7 @@ def compute_minimum_eigenvalue( self._ret = result if aux_operators is not None: - bound_ansatz = self.ansatz.bind_parameters(result.optimal_point) + bound_ansatz = self.ansatz.assign_parameters(result.optimal_point) aux_values = eval_observables( self.quantum_instance, bound_ansatz, aux_operators, expectation=expectation @@ -648,7 +648,7 @@ def energy_evaluation(parameters): def _get_eigenstate(self, optimal_parameters) -> list[float] | dict[str, int]: """Get the simulation outcome of the ansatz, provided with parameters.""" - optimal_circuit = self.ansatz.bind_parameters(optimal_parameters) + optimal_circuit = self.ansatz.assign_parameters(optimal_parameters) state_fn = self._circuit_sampler.convert(StateFn(optimal_circuit)).eval() if self.quantum_instance.is_statevector: state = state_fn.primitive.data # VectorStateFn -> Statevector -> np.array diff --git a/qiskit/algorithms/optimizers/qnspsa.py b/qiskit/algorithms/optimizers/qnspsa.py index c9c195729a84..be5907afbf17 100644 --- a/qiskit/algorithms/optimizers/qnspsa.py +++ b/qiskit/algorithms/optimizers/qnspsa.py @@ -105,7 +105,7 @@ def loss(x): initial_point = np.random.random(ansatz.num_parameters) def loss(x): - bound = ansatz.bind_parameters(x) + bound = ansatz.assign_parameters(x) return np.real((StateFn(observable, is_measurement=True) @ StateFn(bound)).eval()) fidelity = QNSPSA.get_fidelity(ansatz) @@ -387,7 +387,7 @@ def fidelity(values_x, values_y): value_dict = dict( zip(params_x[:] + params_y[:], values_x.tolist() + values_y.tolist()) ) - return np.abs(expression.bind_parameters(value_dict).eval()) ** 2 + return np.abs(expression.assign_parameters(value_dict).eval()) ** 2 else: sampler = CircuitSampler(backend) diff --git a/qiskit/algorithms/optimizers/spsa.py b/qiskit/algorithms/optimizers/spsa.py index 0226f8a00a1e..fb39ad781f72 100644 --- a/qiskit/algorithms/optimizers/spsa.py +++ b/qiskit/algorithms/optimizers/spsa.py @@ -98,7 +98,7 @@ class SPSA(Optimizer): initial_point = np.random.random(ansatz.num_parameters) def loss(x): - bound = ansatz.bind_parameters(x) + bound = ansatz.assign_parameters(x) return np.real((StateFn(observable, is_measurement=True) @ StateFn(bound)).eval()) spsa = SPSA(maxiter=300) diff --git a/qiskit/algorithms/time_evolvers/pvqd/pvqd.py b/qiskit/algorithms/time_evolvers/pvqd/pvqd.py index ea3d82dc4d74..dd560858cebd 100644 --- a/qiskit/algorithms/time_evolvers/pvqd/pvqd.py +++ b/qiskit/algorithms/time_evolvers/pvqd/pvqd.py @@ -232,7 +232,7 @@ def get_loss( self._validate_setup(skip={"optimizer"}) # use Trotterization to evolve the current state - trotterized = ansatz.bind_parameters(current_parameters) + trotterized = ansatz.assign_parameters(current_parameters) evolution_gate = PauliEvolutionGate(hamiltonian, time=dt, synthesis=self.evolution) @@ -388,7 +388,7 @@ def evolve(self, evolution_problem: TimeEvolutionProblem) -> TimeEvolutionResult if observables is not None: observable_values.append(evaluate_observables(next_parameters)) - evolved_state = self.ansatz.bind_parameters(parameters[-1]) + evolved_state = self.ansatz.assign_parameters(parameters[-1]) result = PVQDResult( evolved_state=evolved_state, diff --git a/test/python/algorithms/test_aux_ops_evaluator.py b/test/python/algorithms/test_aux_ops_evaluator.py index 11e4c8e76fc5..af4e30faaf7f 100644 --- a/test/python/algorithms/test_aux_ops_evaluator.py +++ b/test/python/algorithms/test_aux_ops_evaluator.py @@ -125,7 +125,7 @@ def test_eval_observables(self, observables: ListOrDict[OperatorBase]): dtype=float, ) - bound_ansatz = ansatz.bind_parameters(parameters) + bound_ansatz = ansatz.assign_parameters(parameters) expected_result = self.get_exact_expectation(bound_ansatz, observables) for backend_name in self.backend_names: diff --git a/test/python/algorithms/test_observables_evaluator.py b/test/python/algorithms/test_observables_evaluator.py index f4df4ba4bdf5..045c05c36f2d 100644 --- a/test/python/algorithms/test_observables_evaluator.py +++ b/test/python/algorithms/test_observables_evaluator.py @@ -119,7 +119,7 @@ def test_estimate_observables(self, observables: ListOrDict[BaseOperator | Pauli dtype=float, ) - bound_ansatz = ansatz.bind_parameters(parameters) + bound_ansatz = ansatz.assign_parameters(parameters) states = bound_ansatz expected_result = self.get_exact_expectation(bound_ansatz, observables) estimator = Estimator() @@ -140,7 +140,7 @@ def test_estimate_observables_zero_op(self): dtype=float, ) - bound_ansatz = ansatz.bind_parameters(parameters) + bound_ansatz = ansatz.assign_parameters(parameters) state = bound_ansatz estimator = Estimator() observables = [SparsePauliOp(["XX", "YY"]), 0] @@ -162,7 +162,7 @@ def test_estimate_observables_shots(self): dtype=float, ) - bound_ansatz = ansatz.bind_parameters(parameters) + bound_ansatz = ansatz.assign_parameters(parameters) state = bound_ansatz estimator = Estimator(options={"shots": 2048}) with self.assertWarns(DeprecationWarning): diff --git a/test/python/algorithms/test_vqe.py b/test/python/algorithms/test_vqe.py index c9fee9547d19..4272227fa027 100644 --- a/test/python/algorithms/test_vqe.py +++ b/test/python/algorithms/test_vqe.py @@ -844,7 +844,7 @@ def test_construct_eigenstate_from_optpoint(self): vqe = VQE(optimizer=optimizer, quantum_instance=quantum_instance) result = vqe.compute_minimum_eigenvalue(hamiltonian) - optimal_circuit = vqe.ansatz.bind_parameters(result.optimal_point) + optimal_circuit = vqe.ansatz.assign_parameters(result.optimal_point) self.assertTrue(Statevector(result.eigenstate).equiv(optimal_circuit)) diff --git a/test/python/algorithms/time_evolvers/variational/test_var_qrte.py b/test/python/algorithms/time_evolvers/variational/test_var_qrte.py index b7dfaf59f12b..a2d9665417d8 100644 --- a/test/python/algorithms/time_evolvers/variational/test_var_qrte.py +++ b/test/python/algorithms/time_evolvers/variational/test_var_qrte.py @@ -65,7 +65,7 @@ def expected_state(time): result = varqrte.evolve(evolution_problem) final_parameters = result.parameter_values[-1] - final_state = Statevector(circuit.bind_parameters(final_parameters)).to_dict() + final_state = Statevector(circuit.assign_parameters(final_parameters)).to_dict() final_expected_state = expected_state(final_time) for key, expected_value in final_state.items(): From 5bee2350aeade4496750966be769cdac66837a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= <57907331+ElePT@users.noreply.github.com> Date: Thu, 7 Sep 2023 16:52:55 +0200 Subject: [PATCH 05/10] Update releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml Co-authored-by: Jake Lishman --- .../notes/deprecate-bind-parameters-283c94069e8a9142.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml index 181ab70d7b1f..d37f2a5edf3e 100644 --- a/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml +++ b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml @@ -1,6 +1,6 @@ --- deprecations: - | - The method :meth:`~qiskit.QuantumCircuit.bind_parameters` is now deprecated. Its functionality + The method :meth:`.QuantumCircuit.bind_parameters` is now deprecated. Its functionality overlapped highly with :meth:`~qiskit.QuantumCircuit.assign_parameters`, and can be totally replaced by it. Please use :meth:`~qiskit.QuantumCircuit.assign_parameters` instead. From 5e52b56c6593b1e4e7abd6bb83404b468e654a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 17:29:16 +0200 Subject: [PATCH 06/10] Apply suggestions from code review --- ...cate-bind-parameters-283c94069e8a9142.yaml | 7 +- test/benchmarks/circuit_construction.py | 2 + test/python/circuit/test_parameters.py | 222 +++++++++++------- 3 files changed, 142 insertions(+), 89 deletions(-) diff --git a/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml index 181ab70d7b1f..e06b58a67e88 100644 --- a/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml +++ b/releasenotes/notes/deprecate-bind-parameters-283c94069e8a9142.yaml @@ -1,6 +1,7 @@ --- deprecations: - | - The method :meth:`~qiskit.QuantumCircuit.bind_parameters` is now deprecated. Its functionality - overlapped highly with :meth:`~qiskit.QuantumCircuit.assign_parameters`, and can be totally - replaced by it. Please use :meth:`~qiskit.QuantumCircuit.assign_parameters` instead. + The method :meth:`.QuantumCircuit.bind_parameters` is now deprecated and will be removed + from the codebase in no less than 3 months from the release date. Its functionality + overlapped highly with :meth:`.QuantumCircuit.assign_parameters`, and can be totally + replaced by it. Please use :meth:`.QuantumCircuit.assign_parameters` instead. diff --git a/test/benchmarks/circuit_construction.py b/test/benchmarks/circuit_construction.py index 1a7f58b8e934..d4497ed3a04c 100644 --- a/test/benchmarks/circuit_construction.py +++ b/test/benchmarks/circuit_construction.py @@ -93,4 +93,6 @@ def setup(self, width, gates, params): self.circuit, self.params = build_parameterized_circuit(width, gates, params) def time_bind_params(self, _, __, ___): + # TODO: write more complete benchmarks of assign_parameters + # that test more of the input formats / combinations self.circuit.assign_parameters({x: 3.14 for x in self.params}) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index e7afb72a9ae8..d0d4ae3f2cc4 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -12,6 +12,7 @@ """Test circuits with variable parameters.""" import unittest +import warnings import cmath import math import copy @@ -108,6 +109,12 @@ def raise_if_parameter_table_invalid(circuit): class TestParameters(QiskitTestCase): """Test Parameters.""" + def setUp(self): + super().setUp() + # TODO: delete once bind_parameters is removed from the codebase + # and related tests are also removed. + warnings.filterwarnings("ignore", category=DeprecationWarning) + def test_gate(self): """Test instantiating gate with variable parameters""" theta = Parameter("θ") @@ -180,10 +187,11 @@ def test_bind_parameters_anonymously(self): order = [phase] + v[:] + [x, y, z] param_dict = dict(zip(order, params)) - - bqc_anonymous = qc.assign_parameters(params) - bqc_list = qc.assign_parameters(param_dict) - self.assertEqual(bqc_anonymous, bqc_list) + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + bqc_anonymous = getattr(qc, assign_fun)(params) + bqc_list = getattr(qc, assign_fun)(param_dict) + self.assertEqual(bqc_anonymous, bqc_list) def test_bind_parameters_allow_unknown(self): """Test binding parameters allowing unknown parameters.""" @@ -192,22 +200,15 @@ def test_bind_parameters_allow_unknown(self): c = a.bind({a: 1, b: 1}, allow_unknown_parameters=True) self.assertEqual(c, a.bind({a: 1})) - def test_circuit_bind_parameters_raises(self): - """Test that the deprecated bind_parameters method raises a deprecation warning.""" - qc = QuantumCircuit(1) - qc.rx(Parameter("x"), 0) - - with self.assertWarns(DeprecationWarning): - _ = qc.bind_parameters([1]) - - def test_bind_parameters_custom_definition_global_phase(self): + @data(QuantumCircuit.assign_parameters, QuantumCircuit.bind_parameters) + def test_bind_parameters_custom_definition_global_phase(self, assigner): """Test that a custom gate with a parametrised `global_phase` is assigned correctly.""" x = Parameter("x") custom = QuantumCircuit(1, global_phase=x).to_gate() base = QuantumCircuit(1) base.append(custom, [0], []) - test = Operator(QuantumCircuit.assign_parameters(base, {x: math.pi})) + test = Operator(assigner(base, {x: math.pi})) expected = Operator(numpy.array([[-1, 0], [0, -1]])) self.assertEqual(test, expected) @@ -333,12 +334,15 @@ def test_fix_variable(self): qc.rx(theta, qr) qc.u(0, theta, 0, qr) - bqc = qc.assign_parameters({theta: 0.5}) - self.assertEqual(float(bqc.data[0].operation.params[0]), 0.5) - self.assertEqual(float(bqc.data[1].operation.params[1]), 0.5) - bqc = qc.assign_parameters({theta: 0.6}) - self.assertEqual(float(bqc.data[0].operation.params[0]), 0.6) - self.assertEqual(float(bqc.data[1].operation.params[1]), 0.6) + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + bqc = getattr(qc, assign_fun)({theta: 0.5}) + self.assertEqual(float(bqc.data[0].operation.params[0]), 0.5) + self.assertEqual(float(bqc.data[1].operation.params[1]), 0.5) + bqc = getattr(qc, assign_fun)({theta: 0.6}) + self.assertEqual(float(bqc.data[0].operation.params[0]), 0.6) + self.assertEqual(float(bqc.data[1].operation.params[1]), 0.6) def test_multiple_parameters(self): """Test setting multiple parameters""" @@ -387,10 +391,15 @@ def test_partial_binding(self): qc.rx(theta, qr) qc.u(0, theta, x, qr) - pqc = qc.assign_parameters({theta: 2}) - self.assertEqual(pqc.parameters, {x}) - self.assertEqual(float(pqc.data[0].operation.params[0]), 2) - self.assertEqual(float(pqc.data[1].operation.params[1]), 2) + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + pqc = getattr(qc, assign_fun)({theta: 2}) + + self.assertEqual(pqc.parameters, {x}) + + self.assertEqual(float(pqc.data[0].operation.params[0]), 2) + self.assertEqual(float(pqc.data[1].operation.params[1]), 2) @data(True, False) def test_mixed_binding(self, inplace): @@ -418,15 +427,21 @@ def test_expression_partial_binding(self): qc = QuantumCircuit(qr) qc.rx(theta + phi, qr) - pqc = qc.assign_parameters({theta: 2}) - self.assertEqual(pqc.parameters, {phi}) - self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) - self.assertEqual(str(pqc.data[0].operation.params[0]), "phi + 2") + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + pqc = getattr(qc, assign_fun)({theta: 2}) - fbqc = pqc.assign_parameters({phi: 1.0}) - self.assertEqual(fbqc.parameters, set()) - self.assertIsInstance(fbqc.data[0].operation.params[0], float) - self.assertEqual(float(fbqc.data[0].operation.params[0]), 3) + self.assertEqual(pqc.parameters, {phi}) + + self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) + self.assertEqual(str(pqc.data[0].operation.params[0]), "phi + 2") + + fbqc = getattr(pqc, assign_fun)({phi: 1.0}) + + self.assertEqual(fbqc.parameters, set()) + self.assertIsInstance(fbqc.data[0].operation.params[0], float) + self.assertEqual(float(fbqc.data[0].operation.params[0]), 3) def test_two_parameter_expression_binding(self): """Verify that for a circuit with parameters theta and phi that @@ -456,15 +471,21 @@ def test_expression_partial_binding_zero(self): qc = QuantumCircuit(1) qc.p(theta * phi, 0) - pqc = qc.assign_parameters({theta: 0}) - self.assertEqual(pqc.parameters, {phi}) - self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) - self.assertEqual(str(pqc.data[0].operation.params[0]), "0") + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + pqc = getattr(qc, assign_fun)({theta: 0}) + + self.assertEqual(pqc.parameters, {phi}) - fbqc = pqc.assign_parameters({phi: 1}) - self.assertEqual(fbqc.parameters, set()) - self.assertIsInstance(fbqc.data[0].operation.params[0], int) - self.assertEqual(float(fbqc.data[0].operation.params[0]), 0) + self.assertTrue(isinstance(pqc.data[0].operation.params[0], ParameterExpression)) + self.assertEqual(str(pqc.data[0].operation.params[0]), "0") + + fbqc = getattr(pqc, assign_fun)({phi: 1}) + + self.assertEqual(fbqc.parameters, set()) + self.assertIsInstance(fbqc.data[0].operation.params[0], int) + self.assertEqual(float(fbqc.data[0].operation.params[0]), 0) def test_raise_if_assigning_params_not_in_circuit(self): """Verify binding parameters which are not present in the circuit raises an error.""" @@ -472,16 +493,20 @@ def test_raise_if_assigning_params_not_in_circuit(self): y = Parameter("y") z = ParameterVector("z", 3) qr = QuantumRegister(1) - qc = QuantumCircuit(qr) - qc.p(0.1, qr[0]) - self.assertRaises(CircuitError, qc.assign_parameters({x: 1})) - qc.p(x, qr[0]) - self.assertRaises(CircuitError, qc.assign_parameters({x: 1, y: 2})) - qc.p(z[1], qr[0]) - self.assertRaises(CircuitError, qc.assign_parameters({z: [3, 4, 5]})) - self.assertRaises(CircuitError, qc.assign_parameters({"a_str": 6})) - self.assertRaises(CircuitError, qc.assign_parameters({None: 7})) + + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + qc = QuantumCircuit(qr) + with self.subTest(assign_fun=assign_fun): + qc.p(0.1, qr[0]) + self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1}) + qc.p(x, qr[0]) + self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1, y: 2}) + qc.p(z[1], qr[0]) + self.assertRaises(CircuitError, getattr(qc, assign_fun), {z: [3, 4, 5]}) + self.assertRaises(CircuitError, getattr(qc, assign_fun), {"a_str": 6}) + self.assertRaises(CircuitError, getattr(qc, assign_fun), {None: 7}) def test_gate_multiplicity_binding(self): """Test binding when circuit contains multiple references to same gate""" @@ -491,11 +516,13 @@ def test_gate_multiplicity_binding(self): gate = RZGate(theta) qc.append(gate, [0], []) qc.append(gate, [0], []) - - qc2 = qc.assign_parameters({theta: 1.0}) - self.assertEqual(len(qc2._parameter_table), 0) - for instruction in qc2.data: - self.assertEqual(float(instruction.operation.params[0]), 1.0) + # test for both `bind_parameters` and `assign_parameters` + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + qc2 = getattr(qc, assign_fun)({theta: 1.0}) + self.assertEqual(len(qc2._parameter_table), 0) + for instruction in qc2.data: + self.assertEqual(float(instruction.operation.params[0]), 1.0) def test_calibration_assignment(self): """That that calibration mapping and the schedules they map are assigned together.""" @@ -641,14 +668,17 @@ def test_circuit_generation(self): backend = BasicAer.get_backend("qasm_simulator") qc_aer = transpile(qc, backend) - circs = [] - theta_list = numpy.linspace(0, numpy.pi, 20) - for theta_i in theta_list: - circs.append(qc_aer.assign_parameters({theta: theta_i})) - qobj = assemble(circs) - for index, theta_i in enumerate(theta_list): - res = float(qobj.experiments[index].instructions[0].params[0]) - self.assertTrue(math.isclose(res, theta_i), f"{res} != {theta_i}") + # generate list of circuits + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + circs = [] + theta_list = numpy.linspace(0, numpy.pi, 20) + for theta_i in theta_list: + circs.append(getattr(qc_aer, assign_fun)({theta: theta_i})) + qobj = assemble(circs) + for index, theta_i in enumerate(theta_list): + res = float(qobj.experiments[index].instructions[0].params[0]) + self.assertTrue(math.isclose(res, theta_i), f"{res} != {theta_i}") def test_circuit_composition(self): """Test preservation of parameters when combining circuits.""" @@ -713,11 +743,12 @@ def test_bind_ryrz_vector(self): qc.barrier() theta_vals = numpy.linspace(0, 1, len(theta)) * numpy.pi self.assertEqual(set(qc.parameters), set(theta.params)) - - bqc = qc.assign_parameters({theta: theta_vals}) - for instruction in bqc.data: - if hasattr(instruction.operation, "params") and instruction.operation.params: - self.assertIn(float(instruction.operation.params[0]), theta_vals) + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + bqc = getattr(qc, assign_fun)({theta: theta_vals}) + for instruction in bqc.data: + if hasattr(instruction.operation, "params") and instruction.operation.params: + self.assertIn(float(instruction.operation.params[0]), theta_vals) def test_compile_vector(self): """Test compiling a circuit with an unbound ParameterVector""" @@ -884,8 +915,10 @@ def test_repeated_gates_to_dag_and_back(self): double_qc = qc.compose(qc) test_qc = dag_to_circuit(circuit_to_dag(double_qc)) - bound_test_qc = test_qc.assign_parameters({theta: 1}) - self.assertEqual(len(bound_test_qc.parameters), 0) + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + bound_test_qc = getattr(test_qc, assign_fun)({theta: 1}) + self.assertEqual(len(bound_test_qc.parameters), 0) def test_rebinding_instruction_copy(self): """Test rebinding a copied instruction does not modify the original.""" @@ -899,17 +932,19 @@ def test_rebinding_instruction_copy(self): qc1 = QuantumCircuit(1) qc1.append(instr, [0]) - output1 = qc1.assign_parameters({theta: 0.1}).decompose() - output2 = qc1.assign_parameters({theta: 0.2}).decompose() + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + output1 = getattr(qc1, assign_fun)({theta: 0.1}).decompose() + output2 = getattr(qc1, assign_fun)({theta: 0.2}).decompose() - expected1 = QuantumCircuit(1) - expected1.rx(0.1, 0) + expected1 = QuantumCircuit(1) + expected1.rx(0.1, 0) - expected2 = QuantumCircuit(1) - expected2.rx(0.2, 0) + expected2 = QuantumCircuit(1) + expected2.rx(0.2, 0) - self.assertEqual(expected1, output1) - self.assertEqual(expected2, output2) + self.assertEqual(expected1, output1) + self.assertEqual(expected2, output2) @combine(target_type=["gate", "instruction"], parameter_type=["numbers", "parameters"]) def test_decompose_propagates_bound_parameters(self, target_type, parameter_type): @@ -1025,10 +1060,13 @@ def test_executing_parameterized_instruction_bound_early(self, target_type): unbound_qc.append(sub_inst, [0, 1], []) unbound_qc.measure(0, 0) - bound_qc = unbound_qc.assign_parameters({theta: numpy.pi / 2}) - shots = 1024 - job = execute(bound_qc, backend=BasicAer.get_backend("qasm_simulator"), shots=shots) - self.assertDictAlmostEqual(job.result().get_counts(), {"1": shots}, 0.05 * shots) + for assign_fun in ["bind_parameters", "assign_parameters"]: + with self.subTest(assign_fun=assign_fun): + bound_qc = getattr(unbound_qc, assign_fun)({theta: numpy.pi / 2}) + + shots = 1024 + job = execute(bound_qc, backend=BasicAer.get_backend("qasm_simulator"), shots=shots) + self.assertDictAlmostEqual(job.result().get_counts(), {"1": shots}, 0.05 * shots) def test_num_parameters(self): """Test the num_parameters property.""" @@ -1168,7 +1206,7 @@ def test_compile_with_ufunc(self): for x in theta: self.assertIn(x, transpiled.parameters) - bound = transpiled.assign_parameters({theta: [-1, pi, pi, pi, 1, 1, 1]}) + bound = transpiled.bind_parameters({theta: [-1, pi, pi, pi, 1, 1, 1]}) expected = QuantumCircuit(7) expected.rx(1.0, 0) @@ -1428,7 +1466,7 @@ def test_complex_parameter_bound_to_real(self): with self.subTest("simple 1j * x"): qc = QuantumCircuit(1) qc.rx(1j * x, 0) - bound = qc.assign_parameters({x: 1j}) + bound = qc.bind_parameters({x: 1j}) ref = QuantumCircuit(1) ref.rx(-1, 0) self.assertEqual(bound, ref) @@ -1436,7 +1474,7 @@ def test_complex_parameter_bound_to_real(self): with self.subTest("more complex expression"): qc = QuantumCircuit(1) qc.rx(0.5j * x - y * y + 2 * y, 0) - bound = qc.assign_parameters({x: -4, y: 1j}) + bound = qc.bind_parameters({x: -4, y: 1j}) ref = QuantumCircuit(1) ref.rx(1, 0) self.assertEqual(bound, ref) @@ -1448,7 +1486,7 @@ def test_complex_angle_raises_when_not_supported(self): qc.r(x, 1j * x, 0) with self.subTest("binding x to 0 yields real parameters"): - bound = qc.assign_parameters({x: 0}) + bound = qc.bind_parameters({x: 0}) ref = QuantumCircuit(1) ref.r(0, 0, 0) self.assertEqual(bound, ref) @@ -1456,7 +1494,7 @@ def test_complex_angle_raises_when_not_supported(self): with self.subTest("binding x to 1 yields complex parameters"): # RGate does not support complex parameters with self.assertRaises(CircuitError): - bound = qc.assign_parameters({x: 1}) + bound = qc.bind_parameters({x: 1}) def test_operating_on_a_parameter_with_a_non_float_will_raise(self): """Verify operations between a Parameter and a non-float will raise.""" @@ -2143,5 +2181,17 @@ def test_ne(self): self.assertFalse(self.view3 != self.view3) +class TestBindParametersDeprecation(QiskitTestCase): + """Test deprecation of bind_parameters().""" + + def test_circuit_bind_parameters_raises(self): + """Test that the deprecated bind_parameters method raises a deprecation warning.""" + qc = QuantumCircuit(1) + qc.rx(Parameter("x"), 0) + + with self.assertWarns(DeprecationWarning): + _ = qc.bind_parameters([1]) + + if __name__ == "__main__": unittest.main() From b2cacd675ae30d5b7c0b7db710feaf6ccfffbbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Thu, 7 Sep 2023 18:02:53 +0200 Subject: [PATCH 07/10] suppress warnings in test Parameter Expressions --- test/python/circuit/test_parameters.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index d0d4ae3f2cc4..6b2adb39a0b8 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -1277,6 +1277,12 @@ class TestParameterExpressions(QiskitTestCase): supported_operations = [add, sub, mul, truediv] + def setUp(self): + super().setUp() + # TODO: delete once bind_parameters is removed from the codebase + # and related tests are also removed. + warnings.filterwarnings("ignore", category=DeprecationWarning) + def test_compare_to_value_when_bound(self): """Verify expression can be compared to a fixed value when fully bound.""" From 8d179119c6dae5b1a9a142c1b5b8a01f08fbb8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Fri, 8 Sep 2023 13:43:05 +0200 Subject: [PATCH 08/10] Add module to filter --- test/python/circuit/test_parameters.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 6b2adb39a0b8..6c2bf940f124 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -113,7 +113,9 @@ def setUp(self): super().setUp() # TODO: delete once bind_parameters is removed from the codebase # and related tests are also removed. - warnings.filterwarnings("ignore", category=DeprecationWarning) + warnings.filterwarnings( + "ignore", category=DeprecationWarning, module=r"test\.python\.circuit\.test_parameters" + ) def test_gate(self): """Test instantiating gate with variable parameters""" @@ -1281,7 +1283,9 @@ def setUp(self): super().setUp() # TODO: delete once bind_parameters is removed from the codebase # and related tests are also removed. - warnings.filterwarnings("ignore", category=DeprecationWarning) + warnings.filterwarnings( + "ignore", category=DeprecationWarning, module=r"test\.python\.circuit\.test_parameters" + ) def test_compare_to_value_when_bound(self): """Verify expression can be compared to a fixed value From 61172e82ad8c66622d5a053f40811792674ce6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Mon, 11 Sep 2023 10:27:11 +0200 Subject: [PATCH 09/10] Add filter to context manager --- test/python/circuit/test_parameters.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 6c2bf940f124..8acc21bb0895 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -495,12 +495,14 @@ def test_raise_if_assigning_params_not_in_circuit(self): y = Parameter("y") z = ParameterVector("z", 3) qr = QuantumRegister(1) - qc = QuantumCircuit(qr) # test for both `bind_parameters` and `assign_parameters` for assign_fun in ["bind_parameters", "assign_parameters"]: qc = QuantumCircuit(qr) with self.subTest(assign_fun=assign_fun): + # TODO: delete once bind_parameters is removed from the codebase + warnings.filterwarnings("ignore", category=DeprecationWarning) + qc.p(0.1, qr[0]) self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1}) qc.p(x, qr[0]) From df69283cbbc3f36cba0e312f0bb0eb9b8665abe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= Date: Mon, 11 Sep 2023 11:12:45 +0200 Subject: [PATCH 10/10] Fix black --- test/python/circuit/test_parameters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 8acc21bb0895..caa3a148cd7f 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -502,7 +502,7 @@ def test_raise_if_assigning_params_not_in_circuit(self): with self.subTest(assign_fun=assign_fun): # TODO: delete once bind_parameters is removed from the codebase warnings.filterwarnings("ignore", category=DeprecationWarning) - + qc.p(0.1, qr[0]) self.assertRaises(CircuitError, getattr(qc, assign_fun), {x: 1}) qc.p(x, qr[0])