From 35550931217b7937a6c0ef9edb21a81b2f340052 Mon Sep 17 00:00:00 2001 From: James Brown Date: Tue, 8 Mar 2022 14:47:03 -0500 Subject: [PATCH 1/6] added givens gate decomposition --- .../ansatz_generator/ansatz_utils.py | 22 +++++++++++++++++++ .../tests/test_ansatz_util.py | 15 ++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py index ce7352771..139a7a06f 100644 --- a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py +++ b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py @@ -394,3 +394,25 @@ def derangement_circuit(qubit_list, control=None, n_qubits=None, decomp=None): control=control)] return Circuit(gate_list, n_qubits=n_qubits) + + +def givens_gate(target, theta): + """Generates the list of gates corresponding to a givens rotation exp(-theta*(XX+YY)) + + Explicitly the two-qubit matrix is + [[0, 0, 0, 0], + [0, cos(theta), -sin(theta), 0], + [0, sin(theta), cos(theta), 0], + [0, 0, 0, 0]] + + Args: + target (list): list of two integers that indicate which qubits are involved in the givens rotation + theta (float): the rotation angle + + Returns: + list of Gate: The list of gates corresponding to the givens rotation""" + if len(target) != 2: + raise ValueError("target must be a list of two integers") + return [Gate("CNOT", target=target[0], control=target[1]), + Gate("CRY", target=target[1], control=target[0], parameter=-theta), + Gate("CNOT", target=target[0], control=target[1])] diff --git a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py index 2dbf204cd..f00574b79 100644 --- a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py +++ b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py @@ -11,7 +11,7 @@ from tangelo.molecule_library import mol_H4_sto3g from tangelo.linq.tests.test_simulator import assert_freq_dict_almost_equal from tangelo.toolboxes.qubit_mappings.statevector_mapping import get_reference_circuit -from tangelo.toolboxes.ansatz_generator.ansatz_utils import trotterize, get_qft_circuit +from tangelo.toolboxes.ansatz_generator.ansatz_utils import givens_gate, trotterize, get_qft_circuit from tangelo.toolboxes.ansatz_generator.ansatz_utils import controlled_swap_to_XX_gates from tangelo.toolboxes.ansatz_generator.ansatz_utils import derangement_circuit, controlled_pauliwords @@ -302,6 +302,19 @@ def test_derangement_circuit_by_estimating_pauli_string(self): measured = sim.get_expectation_value(exp_op, rho3_pa_circuit, initial_statevector=full_start_vec) self.assertAlmostEqual(measured, exact, places=6) + def test_givens_gate(self): + """Test of givens gate decomposition into 2 CNOTs and a CRY gate.""" + theta = 0.3 + mat_rep = np.eye(4) + mat_rep[1, 1] = np.cos(theta/2) + mat_rep[1, 2] = -np.sin(theta/2) + mat_rep[2, 1] = np.sin(theta/2) + mat_rep[2, 2] = np.cos(theta/2) + vec = np.array([np.sqrt(2)/3, 2/3, np.sqrt(2)/3, 1/3]) + gvec = mat_rep@vec + _, gvec2 = sim.simulate(Circuit(givens_gate([0, 1], theta)), return_statevector=True, initial_statevector=vec) + np.testing.assert_array_almost_equal(gvec, gvec2) + if __name__ == "__main__": unittest.main() From 63209843bde5e106dd9a9899278e498c7220e74c Mon Sep 17 00:00:00 2001 From: James Brown Date: Fri, 11 Mar 2022 14:43:24 -0500 Subject: [PATCH 2/6] style improvements --- tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py index f00574b79..3495cfc4e 100644 --- a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py +++ b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py @@ -305,11 +305,15 @@ def test_derangement_circuit_by_estimating_pauli_string(self): def test_givens_gate(self): """Test of givens gate decomposition into 2 CNOTs and a CRY gate.""" theta = 0.3 + + # Explicit definition of givens rotation gate mat_rep = np.eye(4) mat_rep[1, 1] = np.cos(theta/2) mat_rep[1, 2] = -np.sin(theta/2) mat_rep[2, 1] = np.sin(theta/2) mat_rep[2, 2] = np.cos(theta/2) + + # Test that explicit definition and circuit return the same state vector vec = np.array([np.sqrt(2)/3, 2/3, np.sqrt(2)/3, 1/3]) gvec = mat_rep@vec _, gvec2 = sim.simulate(Circuit(givens_gate([0, 1], theta)), return_statevector=True, initial_statevector=vec) From aea5378532a4269d11353bdd5474f36c4b8f6fda Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 21 Mar 2022 09:19:15 -0400 Subject: [PATCH 3/6] added variational flag --- tangelo/toolboxes/ansatz_generator/ansatz_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py index 139a7a06f..73a3ceb2e 100644 --- a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py +++ b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py @@ -396,7 +396,7 @@ def derangement_circuit(qubit_list, control=None, n_qubits=None, decomp=None): return Circuit(gate_list, n_qubits=n_qubits) -def givens_gate(target, theta): +def givens_gate(target, theta, variational=False): """Generates the list of gates corresponding to a givens rotation exp(-theta*(XX+YY)) Explicitly the two-qubit matrix is @@ -408,11 +408,12 @@ def givens_gate(target, theta): Args: target (list): list of two integers that indicate which qubits are involved in the givens rotation theta (float): the rotation angle + variational (bool): Whether the rotation angle is a variational parameter. Returns: list of Gate: The list of gates corresponding to the givens rotation""" if len(target) != 2: - raise ValueError("target must be a list of two integers") + raise ValueError("target must be a list or array of two integers") return [Gate("CNOT", target=target[0], control=target[1]), - Gate("CRY", target=target[1], control=target[0], parameter=-theta), + Gate("CRY", target=target[1], control=target[0], parameter=-theta, variational=variational), Gate("CNOT", target=target[0], control=target[1])] From 6342c076c0e96afa167a42d65bec4caf07917390 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 21 Mar 2022 09:52:49 -0400 Subject: [PATCH 4/6] fixed key error --- tangelo/toolboxes/ansatz_generator/ansatz_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py index 73a3ceb2e..94c1b2565 100644 --- a/tangelo/toolboxes/ansatz_generator/ansatz_utils.py +++ b/tangelo/toolboxes/ansatz_generator/ansatz_utils.py @@ -396,7 +396,7 @@ def derangement_circuit(qubit_list, control=None, n_qubits=None, decomp=None): return Circuit(gate_list, n_qubits=n_qubits) -def givens_gate(target, theta, variational=False): +def givens_gate(target, theta, is_variational=False): """Generates the list of gates corresponding to a givens rotation exp(-theta*(XX+YY)) Explicitly the two-qubit matrix is @@ -408,12 +408,12 @@ def givens_gate(target, theta, variational=False): Args: target (list): list of two integers that indicate which qubits are involved in the givens rotation theta (float): the rotation angle - variational (bool): Whether the rotation angle is a variational parameter. + is_variational (bool): Whether the rotation angle is a variational parameter. Returns: list of Gate: The list of gates corresponding to the givens rotation""" if len(target) != 2: raise ValueError("target must be a list or array of two integers") return [Gate("CNOT", target=target[0], control=target[1]), - Gate("CRY", target=target[1], control=target[0], parameter=-theta, variational=variational), + Gate("CRY", target=target[1], control=target[0], parameter=-theta, is_variational=is_variational), Gate("CNOT", target=target[0], control=target[1])] From ce6d5e5c01b125268250cd70b3376febd2bdfefd Mon Sep 17 00:00:00 2001 From: ValentinS4t1qbit <41597680+ValentinS4t1qbit@users.noreply.github.com> Date: Mon, 21 Mar 2022 12:00:48 -0700 Subject: [PATCH 5/6] remove redundant import --- tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py index 3495cfc4e..0e8d606ff 100644 --- a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py +++ b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py @@ -11,9 +11,8 @@ from tangelo.molecule_library import mol_H4_sto3g from tangelo.linq.tests.test_simulator import assert_freq_dict_almost_equal from tangelo.toolboxes.qubit_mappings.statevector_mapping import get_reference_circuit -from tangelo.toolboxes.ansatz_generator.ansatz_utils import givens_gate, trotterize, get_qft_circuit -from tangelo.toolboxes.ansatz_generator.ansatz_utils import controlled_swap_to_XX_gates -from tangelo.toolboxes.ansatz_generator.ansatz_utils import derangement_circuit, controlled_pauliwords +from tangelo.toolboxes.ansatz_generator.ansatz_utils import givens_gate, trotterize, get_qft_circuit, + controlled_swap_to_XX_gates, derangement_circuit, controlled_pauliwords # Initiate simulators, Use cirq as it has the same ordering for statevectors as openfermion does for Hamiltonians # This is important when converting the openfermion QubitOperator toarray(), propagating exactly and comparing From 7f25f4e454a8bd819bd4fceea100b24b5a092ef2 Mon Sep 17 00:00:00 2001 From: James Brown Date: Mon, 21 Mar 2022 16:09:27 -0400 Subject: [PATCH 6/6] fixed import error --- tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py index 0e8d606ff..139b841b8 100644 --- a/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py +++ b/tangelo/toolboxes/ansatz_generator/tests/test_ansatz_util.py @@ -11,8 +11,8 @@ from tangelo.molecule_library import mol_H4_sto3g from tangelo.linq.tests.test_simulator import assert_freq_dict_almost_equal from tangelo.toolboxes.qubit_mappings.statevector_mapping import get_reference_circuit -from tangelo.toolboxes.ansatz_generator.ansatz_utils import givens_gate, trotterize, get_qft_circuit, - controlled_swap_to_XX_gates, derangement_circuit, controlled_pauliwords +from tangelo.toolboxes.ansatz_generator.ansatz_utils import (givens_gate, trotterize, get_qft_circuit, controlled_swap_to_XX_gates, + derangement_circuit, controlled_pauliwords) # Initiate simulators, Use cirq as it has the same ordering for statevectors as openfermion does for Hamiltonians # This is important when converting the openfermion QubitOperator toarray(), propagating exactly and comparing