From 1c59043837ac08b9beded470ad05210d83001685 Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Thu, 15 Apr 2021 01:58:47 -0400 Subject: [PATCH 1/5] fix global phase in initializer --- .../quantum_initializer/initializer.py | 6 +-- test/python/circuit/test_initializer.py | 40 ++++++++++++++++++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/qiskit/extensions/quantum_initializer/initializer.py b/qiskit/extensions/quantum_initializer/initializer.py index f5962d75b3c1..690051c38dd0 100644 --- a/qiskit/extensions/quantum_initializer/initializer.py +++ b/qiskit/extensions/quantum_initializer/initializer.py @@ -26,7 +26,7 @@ from qiskit.circuit.library.standard_gates.h import HGate from qiskit.circuit.library.standard_gates.s import SGate, SdgGate from qiskit.circuit.library.standard_gates.ry import RYGate -from qiskit.circuit.library.standard_gates.u1 import U1Gate +from qiskit.circuit.library.standard_gates.rz import RZGate from qiskit.circuit.reset import Reset from qiskit.quantum_info import Statevector @@ -198,13 +198,13 @@ def gates_to_uncompute(self): add_last_cnot = False if np.linalg.norm(phis) != 0: - rz_mult = self._multiplex(U1Gate, phis, last_cnot=add_last_cnot) + rz_mult = self._multiplex(RZGate, phis, last_cnot=add_last_cnot) circuit.append(rz_mult.to_instruction(), q[i:self.num_qubits]) if np.linalg.norm(thetas) != 0: ry_mult = self._multiplex(RYGate, thetas, last_cnot=add_last_cnot) circuit.append(ry_mult.to_instruction().reverse_ops(), q[i:self.num_qubits]) - + circuit.global_phase -= np.angle(sum(remaining_param)) return circuit @staticmethod diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py index 9260e8a31c4e..6ea0fc586e51 100644 --- a/test/python/circuit/test_initializer.py +++ b/test/python/circuit/test_initializer.py @@ -23,7 +23,7 @@ from qiskit import ClassicalRegister from qiskit import transpile from qiskit import execute, assemble, BasicAer -from qiskit.quantum_info import state_fidelity, Statevector +from qiskit.quantum_info import state_fidelity, Statevector, Operator from qiskit.exceptions import QiskitError from qiskit.test import QiskitTestCase @@ -367,6 +367,44 @@ def test_from_int(self): actual_sv = Statevector.from_instruction(qc) self.assertTrue(desired_sv == actual_sv) + def _remove_resets(self, circ): + circ.data = [tup for tup in circ.data if tup[0].name != 'reset'] + + def test_global_phase_random(self): + """Test global phase preservation with random state vectors""" + from qiskit.quantum_info.random import random_statevector + repeats = 5 + for n_qubits in [1, 2, 4]: + for irep in range(repeats): + with self.subTest(i=f'{n_qubits}_{irep}'): + dim = 2**n_qubits + qr = QuantumRegister(n_qubits) + initializer = QuantumCircuit(qr) + target = random_statevector(dim) + initializer.initialize(target, qr) + uninit = initializer.data[0][0].definition + self._remove_resets(uninit) + disentangler = Operator(uninit.data[0][0]) + zero = Statevector.from_int(0, dim) + evolve = zero @ disentangler + self.assertEqual(target, evolve) + + def test_global_phase_1q(self): + """Test global phase preservation with some simple 1q statevectors""" + target_list = [Statevector([1j, 0]), Statevector([0, 1j]), + Statevector([1j/np.sqrt(2), 1j/np.sqrt(2)])] + n_qubits = 1 + dim = 2**n_qubits + qr = QuantumRegister(n_qubits) + for target in target_list: + with self.subTest(i=target): + initializer = QuantumCircuit(qr) + initializer.initialize(target, qr) + disentangler = Operator(initializer.data[0][0].definition.data[1][0]) + zero = Statevector.from_int(0, dim) + actual = zero @ disentangler + self.assertEqual(target, actual) + class TestInstructionParam(QiskitTestCase): """Test conversion of numpy type parameters.""" From 2a7bcac4ccade8037653fe6c860a20580a6aeac5 Mon Sep 17 00:00:00 2001 From: ewinston Date: Thu, 15 Apr 2021 09:39:47 -0400 Subject: [PATCH 2/5] Update test/python/circuit/test_initializer.py Co-authored-by: Julien Gacon --- test/python/circuit/test_initializer.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py index 6ea0fc586e51..f1daed9a9985 100644 --- a/test/python/circuit/test_initializer.py +++ b/test/python/circuit/test_initializer.py @@ -384,9 +384,7 @@ def test_global_phase_random(self): initializer.initialize(target, qr) uninit = initializer.data[0][0].definition self._remove_resets(uninit) - disentangler = Operator(uninit.data[0][0]) - zero = Statevector.from_int(0, dim) - evolve = zero @ disentangler + evolve = Statevector(uninit) self.assertEqual(target, evolve) def test_global_phase_1q(self): From c7e9507335517ebc8e3351a3d0c7a73ce933031b Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Wed, 21 Apr 2021 01:05:38 -0400 Subject: [PATCH 3/5] add release note --- .../notes/fix_initializer_global_phase-977eea9d416c9918.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml diff --git a/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml b/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml new file mode 100644 index 000000000000..69f2266bda64 --- /dev/null +++ b/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Fix global phase of :class:`~qiskit.extensions.quantum_initializer.initializer.Initialize` instruction. \ No newline at end of file From 3d305be4e968db97dbe78d67f8b7f69166d0af47 Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Wed, 21 Apr 2021 08:40:47 +0200 Subject: [PATCH 4/5] add comment on data[indicies].data[indices] in test --- test/python/circuit/test_initializer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py index f1daed9a9985..0b8c1e67e0be 100644 --- a/test/python/circuit/test_initializer.py +++ b/test/python/circuit/test_initializer.py @@ -398,6 +398,7 @@ def test_global_phase_1q(self): with self.subTest(i=target): initializer = QuantumCircuit(qr) initializer.initialize(target, qr) + # need to get rid of the resets in order to use the Operator class disentangler = Operator(initializer.data[0][0].definition.data[1][0]) zero = Statevector.from_int(0, dim) actual = zero @ disentangler From 87eff1f4fdb202d3e826af2d46eec52c2ce6c845 Mon Sep 17 00:00:00 2001 From: Erick Winston Date: Wed, 21 Apr 2021 11:16:57 -0400 Subject: [PATCH 5/5] minor doc change --- .../notes/fix_initializer_global_phase-977eea9d416c9918.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml b/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml index 69f2266bda64..3bc45e160f7a 100644 --- a/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml +++ b/releasenotes/notes/fix_initializer_global_phase-977eea9d416c9918.yaml @@ -1,4 +1,4 @@ --- fixes: - | - Fix global phase of :class:`~qiskit.extensions.quantum_initializer.initializer.Initialize` instruction. \ No newline at end of file + Fix global phase of :class:`qiskit.extensions.quantum_initializer.initializer.Initialize` instruction. \ No newline at end of file