From ea6fa7338782227a8d6f4a3cdf30714f4a8a8f21 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Tue, 3 Dec 2024 14:38:51 -0500 Subject: [PATCH 01/11] added fix for efficient_su2 --- qiskit/circuit/library/n_local/efficient_su2.py | 5 ++++- test/python/circuit/library/test_nlocal.py | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/qiskit/circuit/library/n_local/efficient_su2.py b/qiskit/circuit/library/n_local/efficient_su2.py index 53698a3e18a6..163bb9910b4f 100644 --- a/qiskit/circuit/library/n_local/efficient_su2.py +++ b/qiskit/circuit/library/n_local/efficient_su2.py @@ -114,10 +114,13 @@ def efficient_su2( if su2_gates is None: su2_gates = ["ry", "rz"] + # Set entanglement_blocks to None when num_qubits == 1 + entanglement_blocks = ['cx'] if num_qubits > 1 else [] + return n_local( num_qubits, su2_gates, - ["cx"], + entanglement_blocks, entanglement, reps, insert_barriers, diff --git a/test/python/circuit/library/test_nlocal.py b/test/python/circuit/library/test_nlocal.py index 22bfa391612d..be9b584fe4d7 100644 --- a/test/python/circuit/library/test_nlocal.py +++ b/test/python/circuit/library/test_nlocal.py @@ -790,6 +790,12 @@ def test_efficient_su2(self): expected = n_local(4, ["ry", "rz"], "cx", "reverse_linear", reps=3) self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) + def test_efficient_su2_numqubits_equal1(self): + """Test the efficient SU(2) circuit.""" + circuit = efficient_su2(1) + expected = n_local(1, ["ry", "rz"], [], "reverse_linear", reps=3) + self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) + @data("fsim", "iswap") def test_excitation_preserving(self, mode): """Test the excitation preserving circuit.""" From eb0c13a8e4f4f984870f6e9cc6e82835619d4ae5 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Wed, 4 Dec 2024 20:40:53 -0500 Subject: [PATCH 02/11] making fix for real_amplitudes and excitation_preserving --- .../circuit/library/n_local/efficient_su2.py | 2 +- .../library/n_local/real_amplitudes.py | 4 ++- test/python/circuit/library/test_nlocal.py | 28 +++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/qiskit/circuit/library/n_local/efficient_su2.py b/qiskit/circuit/library/n_local/efficient_su2.py index 163bb9910b4f..c9589a22c9fa 100644 --- a/qiskit/circuit/library/n_local/efficient_su2.py +++ b/qiskit/circuit/library/n_local/efficient_su2.py @@ -115,7 +115,7 @@ def efficient_su2( su2_gates = ["ry", "rz"] # Set entanglement_blocks to None when num_qubits == 1 - entanglement_blocks = ['cx'] if num_qubits > 1 else [] + entanglement_blocks = ["cx"] if num_qubits > 1 else [] return n_local( num_qubits, diff --git a/qiskit/circuit/library/n_local/real_amplitudes.py b/qiskit/circuit/library/n_local/real_amplitudes.py index f1ba10604e9d..572cc036ad73 100644 --- a/qiskit/circuit/library/n_local/real_amplitudes.py +++ b/qiskit/circuit/library/n_local/real_amplitudes.py @@ -114,11 +114,13 @@ def real_amplitudes( Returns: A real-amplitudes circuit. """ + # Set entanglement_blocks to None when num_qubits == 1 + entanglement_blocks = ["cx"] if num_qubits > 1 else [] return n_local( num_qubits, ["ry"], - ["cx"], + entanglement_blocks, entanglement, reps, insert_barriers, diff --git a/test/python/circuit/library/test_nlocal.py b/test/python/circuit/library/test_nlocal.py index be9b584fe4d7..706c515b5610 100644 --- a/test/python/circuit/library/test_nlocal.py +++ b/test/python/circuit/library/test_nlocal.py @@ -780,6 +780,12 @@ class TestNLocalFamily(QiskitTestCase): def test_real_amplitudes(self): """Test the real amplitudes circuit.""" + circuit = real_amplitudes(1) + expected = n_local(1, ["ry", "rz"], []) + self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) + + def test_real_amplitudes_numqubits_equal1(self): + """Test the real amplitudes circuit for a single qubit.""" circuit = real_amplitudes(4) expected = n_local(4, "ry", "cx", "reverse_linear", reps=3) self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) @@ -791,9 +797,9 @@ def test_efficient_su2(self): self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) def test_efficient_su2_numqubits_equal1(self): - """Test the efficient SU(2) circuit.""" + """Test the efficient SU(2) circuit for a single qubit.""" circuit = efficient_su2(1) - expected = n_local(1, ["ry", "rz"], [], "reverse_linear", reps=3) + expected = n_local(1, ["ry", "rz"], []) self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) @data("fsim", "iswap") @@ -813,6 +819,24 @@ def test_excitation_preserving(self, mode): self.assertEqual( expected.assign_parameters(circuit.parameters).decompose(), circuit.decompose() ) + + @data("fsim", "iswap") + def test_excitation_preserving_numqubits_equal1(self, mode): + """Test the excitation preserving circuit for a single qubit.""" + circuit = excitation_preserving(1, mode=mode) + + x = Parameter("x") + block = QuantumCircuit(2) + block.rxx(x, 0, 1) + block.ryy(x, 0, 1) + if mode == "fsim": + y = Parameter("y") + block.cp(y, 0, 1) + + expected = n_local(4, "rz", block.to_gate(), "full", reps=3) + self.assertEqual( + expected.assign_parameters(circuit.parameters).decompose(), circuit.decompose() + ) def test_excitation_preserving_invalid_mode(self): """Test an error is raised for an invalid mode.""" From 30b48d8857f87f598598774548bfc508f28bcb56 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Wed, 4 Dec 2024 20:41:20 -0500 Subject: [PATCH 03/11] formatted --- test/python/circuit/library/test_nlocal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/circuit/library/test_nlocal.py b/test/python/circuit/library/test_nlocal.py index 706c515b5610..31dc34ab596b 100644 --- a/test/python/circuit/library/test_nlocal.py +++ b/test/python/circuit/library/test_nlocal.py @@ -819,7 +819,7 @@ def test_excitation_preserving(self, mode): self.assertEqual( expected.assign_parameters(circuit.parameters).decompose(), circuit.decompose() ) - + @data("fsim", "iswap") def test_excitation_preserving_numqubits_equal1(self, mode): """Test the excitation preserving circuit for a single qubit.""" From b830e1471aa4f3a313e016084d2e3ce13946729e Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Wed, 4 Dec 2024 22:36:19 -0500 Subject: [PATCH 04/11] passing tests --- .../library/n_local/excitation_preserving.py | 18 +++++++++++------- test/python/circuit/library/test_nlocal.py | 19 +++++-------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/qiskit/circuit/library/n_local/excitation_preserving.py b/qiskit/circuit/library/n_local/excitation_preserving.py index 49bfdb07f017..b2fd3f0cdc43 100644 --- a/qiskit/circuit/library/n_local/excitation_preserving.py +++ b/qiskit/circuit/library/n_local/excitation_preserving.py @@ -112,17 +112,21 @@ def excitation_preserving( raise ValueError(f"Unsupported mode {mode}, choose one of {supported_modes}") theta = Parameter("θ") - swap = QuantumCircuit(2, name="Interaction") - swap.rxx(theta, 0, 1) - swap.ryy(theta, 0, 1) - if mode == "fsim": - phi = Parameter("φ") - swap.cp(phi, 0, 1) + if num_qubits > 1: + swap = QuantumCircuit(2, name="Interaction") + swap.rxx(theta, 0, 1) + swap.ryy(theta, 0, 1) + if mode == "fsim": + phi = Parameter("φ") + swap.cp(phi, 0, 1) + entanglement_blocks = [swap.to_gate()] + else: + entanglement_blocks = [] return n_local( num_qubits, ["rz"], - [swap.to_gate()], + entanglement_blocks, entanglement, reps, insert_barriers, diff --git a/test/python/circuit/library/test_nlocal.py b/test/python/circuit/library/test_nlocal.py index 31dc34ab596b..0ed164b0280d 100644 --- a/test/python/circuit/library/test_nlocal.py +++ b/test/python/circuit/library/test_nlocal.py @@ -780,14 +780,14 @@ class TestNLocalFamily(QiskitTestCase): def test_real_amplitudes(self): """Test the real amplitudes circuit.""" - circuit = real_amplitudes(1) - expected = n_local(1, ["ry", "rz"], []) + circuit = real_amplitudes(4) + expected = n_local(4, "ry", "cx", "reverse_linear", reps=3) self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) def test_real_amplitudes_numqubits_equal1(self): """Test the real amplitudes circuit for a single qubit.""" - circuit = real_amplitudes(4) - expected = n_local(4, "ry", "cx", "reverse_linear", reps=3) + circuit = real_amplitudes(1) + expected = n_local(1, "ry", []) self.assertEqual(expected.assign_parameters(circuit.parameters), circuit) def test_efficient_su2(self): @@ -824,16 +824,7 @@ def test_excitation_preserving(self, mode): def test_excitation_preserving_numqubits_equal1(self, mode): """Test the excitation preserving circuit for a single qubit.""" circuit = excitation_preserving(1, mode=mode) - - x = Parameter("x") - block = QuantumCircuit(2) - block.rxx(x, 0, 1) - block.ryy(x, 0, 1) - if mode == "fsim": - y = Parameter("y") - block.cp(y, 0, 1) - - expected = n_local(4, "rz", block.to_gate(), "full", reps=3) + expected = n_local(1, "rz", []) self.assertEqual( expected.assign_parameters(circuit.parameters).decompose(), circuit.decompose() ) From 095834d68bae82bcb407d9438f921e08bce12159 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Wed, 4 Dec 2024 22:58:57 -0500 Subject: [PATCH 05/11] added release notes --- .../fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml diff --git a/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml b/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml new file mode 100644 index 000000000000..055c00c0241c --- /dev/null +++ b/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml @@ -0,0 +1,5 @@ +fixes: + - | + Fixed a bug that caused library functions that call :meth:`n_local`, such as :meth:`efficient_su2` + to error out when passed a num_qubits argument that equals 1. The default entanglement blocks for these + methods was being set to "cx", but now if num_qubits <= 1, then entanglements_blocks will equal an empty array. \ No newline at end of file From cc6fa1693ca619bd473e202e48487ece556bbc24 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Mon, 9 Dec 2024 21:16:50 -0500 Subject: [PATCH 06/11] fixed pauli_two_design --- qiskit/circuit/library/n_local/pauli_two_design.py | 8 +++++--- ...ix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml | 7 ++++--- test/python/circuit/library/test_nlocal.py | 8 ++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index f0deeb68b287..6eda8efc5087 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -16,7 +16,7 @@ import numpy as np from qiskit.circuit import QuantumCircuit -from qiskit.circuit.library.standard_gates import RXGate, RYGate, RZGate, CZGate +from qiskit.circuit.library.standard_gates import RXGate, RYGate, RZGate, CZGate, IGate from qiskit.utils.deprecation import deprecate_func from qiskit._accelerate.circuit_library import Block, py_n_local from .two_local import TwoLocal @@ -88,19 +88,21 @@ def pauli_two_design( """ rng = np.random.default_rng(seed) random_block = Block.from_callable(1, 1, lambda params: _random_pauli_builder(params, rng)) - cz_block = Block.from_standard_gate(CZGate._standard_gate) + entanglement_block = (Block.from_standard_gate(CZGate._standard_gate) if num_qubits > 1 + else Block.from_standard_gate(IGate._standard_gate)) data = py_n_local( num_qubits=num_qubits, reps=reps, rotation_blocks=[random_block], - entanglement_blocks=[cz_block], + entanglement_blocks=[entanglement_block], entanglement=["pairwise"], insert_barriers=insert_barriers, skip_final_rotation_layer=False, skip_unentangled_qubits=False, parameter_prefix=parameter_prefix, ) + two_design = QuantumCircuit._from_circuit_data(data) circuit = QuantumCircuit(num_qubits, name=name) diff --git a/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml b/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml index 055c00c0241c..530c4438de3d 100644 --- a/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml +++ b/releasenotes/notes/fix-efficient-su2-numqubits-issue-2b2c91c1186f82ac.yaml @@ -1,5 +1,6 @@ fixes: - | - Fixed a bug that caused library functions that call :meth:`n_local`, such as :meth:`efficient_su2` - to error out when passed a num_qubits argument that equals 1. The default entanglement blocks for these - methods was being set to "cx", but now if num_qubits <= 1, then entanglements_blocks will equal an empty array. \ No newline at end of file + Fixed a bug that caused the circuit library functions :func:`.efficient_su2`, + :func:`.real_amplitudes`, :func:`.excitation_preserving` and :func:`.pauli_two_design` + to error out when constructed for ``num_qubits==1``. For a single qubit these + circuits will not contain any 2-qubit gates. \ No newline at end of file diff --git a/test/python/circuit/library/test_nlocal.py b/test/python/circuit/library/test_nlocal.py index 0ed164b0280d..b171a728d4c9 100644 --- a/test/python/circuit/library/test_nlocal.py +++ b/test/python/circuit/library/test_nlocal.py @@ -845,6 +845,14 @@ def test_two_design(self): self.assertTrue(circuit_ops.issubset(expected_ops)) + def test_two_design_numqubits_equal1(self): + """Test the Pauli 2-design circuit for a single qubit.""" + circuit = pauli_two_design(1) + expected_ops = {"rx", "ry", "rz", "id"} + circuit_ops = set(circuit.count_ops().keys()) + + self.assertTrue(circuit_ops.issubset(expected_ops)) + def test_two_design_seed(self): """Test the seed""" seed1 = 123 From 1e12c5ec69d4f14a95915d512a82ddc6eff0a929 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Tue, 10 Dec 2024 19:54:55 -0500 Subject: [PATCH 07/11] fixed format --- qiskit/circuit/library/n_local/pauli_two_design.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index 6eda8efc5087..044cbacafda9 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -88,8 +88,11 @@ def pauli_two_design( """ rng = np.random.default_rng(seed) random_block = Block.from_callable(1, 1, lambda params: _random_pauli_builder(params, rng)) - entanglement_block = (Block.from_standard_gate(CZGate._standard_gate) if num_qubits > 1 - else Block.from_standard_gate(IGate._standard_gate)) + entanglement_block = ( + Block.from_standard_gate(CZGate._standard_gate) + if num_qubits > 1 + else Block.from_standard_gate(IGate._standard_gate) + ) data = py_n_local( num_qubits=num_qubits, From c7aa169641770779048238ba1b5c419bbd2bd0a3 Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Thu, 12 Dec 2024 21:02:20 -0500 Subject: [PATCH 08/11] fixed pauli_two_design issue --- qiskit/circuit/library/n_local/pauli_two_design.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index 044cbacafda9..0ca967e35c2a 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -88,17 +88,13 @@ def pauli_two_design( """ rng = np.random.default_rng(seed) random_block = Block.from_callable(1, 1, lambda params: _random_pauli_builder(params, rng)) - entanglement_block = ( - Block.from_standard_gate(CZGate._standard_gate) - if num_qubits > 1 - else Block.from_standard_gate(IGate._standard_gate) - ) + entanglement_block = Block.from_standard_gate(CZGate._standard_gate) data = py_n_local( num_qubits=num_qubits, reps=reps, rotation_blocks=[random_block], - entanglement_blocks=[entanglement_block], + entanglement_blocks=[entanglement_block] if num_qubits > 1 else [], entanglement=["pairwise"], insert_barriers=insert_barriers, skip_final_rotation_layer=False, From 55beb9020fe4614d67ea5601da943841f6dabd2d Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Thu, 12 Dec 2024 21:36:07 -0500 Subject: [PATCH 09/11] fixed unused gate --- qiskit/circuit/library/n_local/pauli_two_design.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index 0ca967e35c2a..03078a485f74 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -16,7 +16,7 @@ import numpy as np from qiskit.circuit import QuantumCircuit -from qiskit.circuit.library.standard_gates import RXGate, RYGate, RZGate, CZGate, IGate +from qiskit.circuit.library.standard_gates import RXGate, RYGate, RZGate, CZGate from qiskit.utils.deprecation import deprecate_func from qiskit._accelerate.circuit_library import Block, py_n_local from .two_local import TwoLocal From e255d5ac84ae3d6467bec424fcd03e6454db8c30 Mon Sep 17 00:00:00 2001 From: trigpolynom Date: Fri, 13 Dec 2024 12:10:00 -0500 Subject: [PATCH 10/11] Update qiskit/circuit/library/n_local/pauli_two_design.py Co-authored-by: Julien Gacon --- qiskit/circuit/library/n_local/pauli_two_design.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index 03078a485f74..8305ca73c031 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -88,7 +88,7 @@ def pauli_two_design( """ rng = np.random.default_rng(seed) random_block = Block.from_callable(1, 1, lambda params: _random_pauli_builder(params, rng)) - entanglement_block = Block.from_standard_gate(CZGate._standard_gate) + entanglement_block = [Block.from_standard_gate(CZGate._standard_gate)] if num_qubits > 1 else [] data = py_n_local( num_qubits=num_qubits, From 058a7e6aefa78e1f728eb18fe3811c9025ca82f3 Mon Sep 17 00:00:00 2001 From: trigpolynom Date: Fri, 13 Dec 2024 17:14:37 +0000 Subject: [PATCH 11/11] addressing change --- qiskit/circuit/library/n_local/pauli_two_design.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/circuit/library/n_local/pauli_two_design.py b/qiskit/circuit/library/n_local/pauli_two_design.py index 8305ca73c031..fc286c8533be 100644 --- a/qiskit/circuit/library/n_local/pauli_two_design.py +++ b/qiskit/circuit/library/n_local/pauli_two_design.py @@ -94,7 +94,7 @@ def pauli_two_design( num_qubits=num_qubits, reps=reps, rotation_blocks=[random_block], - entanglement_blocks=[entanglement_block] if num_qubits > 1 else [], + entanglement_blocks=entanglement_block, entanglement=["pairwise"], insert_barriers=insert_barriers, skip_final_rotation_layer=False,