From 03e82f2e91067090d2b218063d6f5f463601a36d Mon Sep 17 00:00:00 2001 From: dariatols Date: Wed, 16 Aug 2023 16:09:03 +0200 Subject: [PATCH 1/6] Implement iSWAP gate. --- src/tequila/circuit/gates.py | 32 ++++++++++++++++++++++++ src/tequila/simulators/simulator_cirq.py | 1 + tests/test_circuits.py | 23 ++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/tequila/circuit/gates.py b/src/tequila/circuit/gates.py index 2c63f66a0..73f04f90f 100644 --- a/src/tequila/circuit/gates.py +++ b/src/tequila/circuit/gates.py @@ -504,6 +504,38 @@ def SWAP(first: int, second: int, control: typing.Union[int, list] = None, power else: return GeneralizedRotation(angle=power * np.pi, control=control, generator=generator, eigenvalues_magnitude=0.25) + + +def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, power: float = None, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + iSWAP gate + .. math:: + iSWAP = e^{i\\frac{\\pi}{4} (X \otimes X + Y \otimes Y )} + + Parameters + ---------- + first: int + target qubit + second: int + target qubit + control + int or list of ints + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + + Returns + ------- + QCircuit + + """ + + generator = paulis.from_string(f"X({first})X({second}) + Y({first})Y({second})") + + return GeneralizedRotation(angle=power * (-np.pi/2), control=control, generator=generator, + eigenvalues_magnitude=0.25) """ diff --git a/src/tequila/simulators/simulator_cirq.py b/src/tequila/simulators/simulator_cirq.py index 782124f2d..b9088b153 100755 --- a/src/tequila/simulators/simulator_cirq.py +++ b/src/tequila/simulators/simulator_cirq.py @@ -120,6 +120,7 @@ def __init__(self, abstract_circuit: QCircuit, variables, qubit_map=None, noise= 'Ry': (cirq.ops.common_gates.YPowGate, map_2), 'Rz': (cirq.ops.common_gates.ZPowGate, map_2), 'SWAP': (cirq.ops.SwapPowGate, None), + 'iSWAP': (cirq.ops.ISwapPowGate, None), } self.tq_to_sympy = {} diff --git a/tests/test_circuits.py b/tests/test_circuits.py index aab25d220..6c38a02cd 100644 --- a/tests/test_circuits.py +++ b/tests/test_circuits.py @@ -6,7 +6,7 @@ from tequila import assign_variable, paulis, TequilaWarning from tequila.circuit._gates_impl import RotationGateImpl from tequila.circuit.gates import CNOT, ExpPauli, H, Phase, QCircuit, RotationGate, Rx, Ry, Rz, S, \ - SWAP, T, Trotterized, u1, u2, u3, X, Y, Z + SWAP, iSWAP, T, Trotterized, u1, u2, u3, X, Y, Z from tequila.objective.objective import Variable from tequila.simulators.simulator_api import simulate from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction @@ -332,6 +332,27 @@ def test_swap(): wfn = simulate(U) wfnx = simulate(X(2)+X(3)) assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2,1.0) + +def test_iswap(): + U = X(0) + U += iSWAP(0, 2) + wfn = simulate(U) + wfnx = simulate(X(2)) + assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, complex(0.0, 1.0)) + + U = X(2) + U += iSWAP(0, 2) + wfn = simulate(U) + wfnx = simulate(X(0)) + assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, complex(0.0, 1.0)) + + U = X(0) + U += iSWAP(0, 2, power=0.5) + wfn = simulate(U) + wfn0100 = simulate(X(2)) + assert numpy.isclose(numpy.abs(wfn.inner(wfn0100))**2, complex(0, 1)/numpy.sqrt(2)) + wfn0010 = simulate(X(0)) + assert numpy.isclose(numpy.abs(wfn.inner(wfn0100))**2, 1/numpy.sqrt(2)) def test_variable_map(): U = Ry(angle="a", target=0) + Rx(angle="b", target=1) + Rz(angle="c", target=2) + H(angle="d", target=3) + ExpPauli(paulistring="X(0)Y(1)Z(2)", angle="e") From 76da819ebbe467d09c66c4370bf132a293f59f1a Mon Sep 17 00:00:00 2001 From: dariatols Date: Fri, 18 Aug 2023 13:58:55 +0200 Subject: [PATCH 2/6] Implement Givens gate and bugfix tests iSWAP. --- src/tequila/circuit/gates.py | 38 ++++++++-- test.ipynb | 133 +++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 test.ipynb diff --git a/src/tequila/circuit/gates.py b/src/tequila/circuit/gates.py index 73f04f90f..aa3275432 100644 --- a/src/tequila/circuit/gates.py +++ b/src/tequila/circuit/gates.py @@ -506,14 +506,14 @@ def SWAP(first: int, second: int, control: typing.Union[int, list] = None, power eigenvalues_magnitude=0.25) -def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, power: float = None, *args, +def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, power: float = 1.0, *args, **kwargs) -> QCircuit: """ Notes ---------- iSWAP gate .. math:: - iSWAP = e^{i\\frac{\\pi}{4} (X \otimes X + Y \otimes Y )} + iSWAP = e^{i\\frac{\\pi}{4} (X \\otimes X + Y \\otimes Y )} Parameters ---------- @@ -533,9 +533,39 @@ def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, powe """ generator = paulis.from_string(f"X({first})X({second}) + Y({first})Y({second})") + return GeneralizedRotation(angle=power*(-np.pi/2), control=control, generator=generator, + eigenvalues_magnitude=0.25) + + +def Givens(first: int, second: int, control: typing.Union[int, list] = None, angle: float = None, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + Givens gate G + .. math:: + G = e^{-i\\frac{\\theta}{2} (Y \\otimes X - X \\otimes Y )} + + Parameters + ---------- + first: int + target qubit + second: int + target qubit + control + int or list of ints + angle + numeric type (fixed exponent) or hashable type (parametrized exponent), theta in the above formula + + Returns + ------- + QCircuit + + """ + + generator = paulis.from_string(f"1.0*Y({first})X({second}) - 1.0*X({first})Y({second})") - return GeneralizedRotation(angle=power * (-np.pi/2), control=control, generator=generator, - eigenvalues_magnitude=0.25) + return GeneralizedRotation(angle=angle, control=control, generator=generator,) """ diff --git a/test.ipynb b/test.ipynb new file mode 100644 index 000000000..1db098ef8 --- /dev/null +++ b/test.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import cirq\n", + "import numpy as np\n", + "import tequila as tq" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "U = tq.gates.X(0)\n", + "U += tq.gates.Givens(0, 1, angle=-np.pi/4)\n", + "wfn = tq.simulate(U)\n", + "wfnx = tq.simulate(tq.gates.X(0))\n", + "assert np.isclose(np.abs(wfn.inner(wfnx)), 1/np.sqrt(2))\n", + "wfnx = tq.simulate(tq.gates.X(1))\n", + "assert np.isclose(np.abs(wfn.inner(wfnx)), 1/np.sqrt(2))\n", + "\n", + "U = tq.gates.X(0)\n", + "U += tq.gates.Givens(0, 1, angle=np.pi/4)\n", + "wfn = tq.simulate(U)\n", + "#qc = tq.QCircuit(gates=[0, 1])\n", + "#qc = tq.gates.Phase([0, 1], angle=np.pi)\n", + "#qc += tq.gates.X(0)\n", + "wfnx0 = tq.simulate(tq.gates.Phase([0, 1], angle=np.pi) + tq.gates.X(0))\n", + "wfnx1 = tq.simulate(tq.gates.X(1))\n", + "assert np.isclose(wfn.inner(wfnx0), -wfn.inner(wfnx1))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nU =tq.gates.X(0)\\nU += tq.gates.iSWAP(0, 2, power=0.5)\\nwfn =tq.simulate(U)\\nwfn0100 =tq.simulate(tq.gates.X(2))\\nassert np.isclose(np.abs(wfn.inner(wfn0100))**2, complex(0, 1)/np.sqrt(2))\\nwfn0010 =tq.simulate(tq.gates.X(0))\\nassert np.isclose(np.abs(wfn.inner(wfn0010))**2, 1/np.sqrt(2))\\n'" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "U = tq.gates.X(0)\n", + "U += tq.gates.iSWAP(0, 2, power=0.5)\n", + "wfn = tq.simulate(U)\n", + "wfnx = tq.simulate(tq.gates.X(2))\n", + "assert np.isclose(np.abs(wfn.inner(wfnx))**2, 0.5)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.7071067811865476j" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wfn.inner(wfnx)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(+0.7071|100> +0.7071i|001> , +1.0000|1> )" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wfn, wfnx" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "teq_fork", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.17" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From a65e1751da53eed9746655f29e69cfc30b99d6f5 Mon Sep 17 00:00:00 2001 From: dariatols Date: Fri, 18 Aug 2023 14:00:00 +0200 Subject: [PATCH 3/6] Remove test notebook + add tests for iSWAP and Givens gates. --- test.ipynb | 133 ----------------------------------------- tests/test_circuits.py | 28 +++++---- 2 files changed, 16 insertions(+), 145 deletions(-) delete mode 100644 test.ipynb diff --git a/test.ipynb b/test.ipynb deleted file mode 100644 index 1db098ef8..000000000 --- a/test.ipynb +++ /dev/null @@ -1,133 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import cirq\n", - "import numpy as np\n", - "import tequila as tq" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "U = tq.gates.X(0)\n", - "U += tq.gates.Givens(0, 1, angle=-np.pi/4)\n", - "wfn = tq.simulate(U)\n", - "wfnx = tq.simulate(tq.gates.X(0))\n", - "assert np.isclose(np.abs(wfn.inner(wfnx)), 1/np.sqrt(2))\n", - "wfnx = tq.simulate(tq.gates.X(1))\n", - "assert np.isclose(np.abs(wfn.inner(wfnx)), 1/np.sqrt(2))\n", - "\n", - "U = tq.gates.X(0)\n", - "U += tq.gates.Givens(0, 1, angle=np.pi/4)\n", - "wfn = tq.simulate(U)\n", - "#qc = tq.QCircuit(gates=[0, 1])\n", - "#qc = tq.gates.Phase([0, 1], angle=np.pi)\n", - "#qc += tq.gates.X(0)\n", - "wfnx0 = tq.simulate(tq.gates.Phase([0, 1], angle=np.pi) + tq.gates.X(0))\n", - "wfnx1 = tq.simulate(tq.gates.X(1))\n", - "assert np.isclose(wfn.inner(wfnx0), -wfn.inner(wfnx1))" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\\nU =tq.gates.X(0)\\nU += tq.gates.iSWAP(0, 2, power=0.5)\\nwfn =tq.simulate(U)\\nwfn0100 =tq.simulate(tq.gates.X(2))\\nassert np.isclose(np.abs(wfn.inner(wfn0100))**2, complex(0, 1)/np.sqrt(2))\\nwfn0010 =tq.simulate(tq.gates.X(0))\\nassert np.isclose(np.abs(wfn.inner(wfn0010))**2, 1/np.sqrt(2))\\n'" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "U = tq.gates.X(0)\n", - "U += tq.gates.iSWAP(0, 2, power=0.5)\n", - "wfn = tq.simulate(U)\n", - "wfnx = tq.simulate(tq.gates.X(2))\n", - "assert np.isclose(np.abs(wfn.inner(wfnx))**2, 0.5)" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-0.7071067811865476j" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "wfn.inner(wfnx)" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(+0.7071|100> +0.7071i|001> , +1.0000|1> )" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "wfn, wfnx" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "teq_fork", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.17" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_circuits.py b/tests/test_circuits.py index 6c38a02cd..05a9fb868 100644 --- a/tests/test_circuits.py +++ b/tests/test_circuits.py @@ -6,7 +6,7 @@ from tequila import assign_variable, paulis, TequilaWarning from tequila.circuit._gates_impl import RotationGateImpl from tequila.circuit.gates import CNOT, ExpPauli, H, Phase, QCircuit, RotationGate, Rx, Ry, Rz, S, \ - SWAP, iSWAP, T, Trotterized, u1, u2, u3, X, Y, Z + SWAP, iSWAP, Givens, T, Trotterized, u1, u2, u3, X, Y, Z from tequila.objective.objective import Variable from tequila.simulators.simulator_api import simulate from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction @@ -335,24 +335,28 @@ def test_swap(): def test_iswap(): U = X(0) - U += iSWAP(0, 2) + U += iSWAP(0, 2, power=0.5) wfn = simulate(U) wfnx = simulate(X(2)) - assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, complex(0.0, 1.0)) + assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 0.5) + - U = X(2) - U += iSWAP(0, 2) +def test_givens(): + U = X(0) + U += Givens(0, 1, angle=-numpy.pi/4) wfn = simulate(U) wfnx = simulate(X(0)) - assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, complex(0.0, 1.0)) - + assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 0.5) + wfnx = simulate(X(1)) + assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 0.5) + U = X(0) - U += iSWAP(0, 2, power=0.5) + U += Givens(0, 1, angle=numpy.pi/4) wfn = simulate(U) - wfn0100 = simulate(X(2)) - assert numpy.isclose(numpy.abs(wfn.inner(wfn0100))**2, complex(0, 1)/numpy.sqrt(2)) - wfn0010 = simulate(X(0)) - assert numpy.isclose(numpy.abs(wfn.inner(wfn0100))**2, 1/numpy.sqrt(2)) + wfnx0 = simulate(Phase([0, 1], angle=numpy.pi) + X(0)) + wfnx1 = simulate(X(1)) + assert numpy.isclose(wfn.inner(wfnx0), -wfn.inner(wfnx1)) + def test_variable_map(): U = Ry(angle="a", target=0) + Rx(angle="b", target=1) + Rz(angle="c", target=2) + H(angle="d", target=3) + ExpPauli(paulistring="X(0)Y(1)Z(2)", angle="e") From 85759a59df87f86129510eadc1132a25fab04e20 Mon Sep 17 00:00:00 2001 From: dariatols Date: Fri, 18 Aug 2023 16:31:31 +0200 Subject: [PATCH 4/6] Remove iSWAP from Cirq simulator. --- src/tequila/simulators/simulator_cirq.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tequila/simulators/simulator_cirq.py b/src/tequila/simulators/simulator_cirq.py index b9088b153..782124f2d 100755 --- a/src/tequila/simulators/simulator_cirq.py +++ b/src/tequila/simulators/simulator_cirq.py @@ -120,7 +120,6 @@ def __init__(self, abstract_circuit: QCircuit, variables, qubit_map=None, noise= 'Ry': (cirq.ops.common_gates.YPowGate, map_2), 'Rz': (cirq.ops.common_gates.ZPowGate, map_2), 'SWAP': (cirq.ops.SwapPowGate, None), - 'iSWAP': (cirq.ops.ISwapPowGate, None), } self.tq_to_sympy = {} From 116d79cf624921fa9f8a681fc9c6cf1af7e2bfb1 Mon Sep 17 00:00:00 2001 From: "J. S. Kottmann" Date: Sun, 10 Sep 2023 14:31:37 +0200 Subject: [PATCH 5/6] orbital optimizer more flexible with regards to qubit encodings (#305) --- .../quantumchemistry/orbital_optimizer.py | 20 ++++++++++++------- .../quantumchemistry/pyscf_interface.py | 18 ++--------------- src/tequila/quantumchemistry/qc_base.py | 13 ++++++++++++ 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/tequila/quantumchemistry/orbital_optimizer.py b/src/tequila/quantumchemistry/orbital_optimizer.py index 34b593ae2..c8c9877e3 100644 --- a/src/tequila/quantumchemistry/orbital_optimizer.py +++ b/src/tequila/quantumchemistry/orbital_optimizer.py @@ -37,7 +37,7 @@ def __call__(self, local_data, *args, **kwargs): self.iterations += 1 def optimize_orbitals(molecule, circuit=None, vqe_solver=None, pyscf_arguments=None, silent=False, - vqe_solver_arguments=None, initial_guess=None, return_mcscf=False, use_hcb=False, *args, **kwargs): + vqe_solver_arguments=None, initial_guess=None, return_mcscf=False, use_hcb=False, molecule_factory=None, *args, **kwargs): """ Parameters @@ -97,9 +97,9 @@ def optimize_orbitals(molecule, circuit=None, vqe_solver=None, pyscf_arguments=N if n_qubits > n_orbitals: warnings.warn("Potential inconsistency in orbital optimization: use_hcb is switched on but we have\n n_qubits={} in the circuit\n n_orbital={} in the molecule\n".format(n_qubits,n_orbitals), TequilaWarning) - wrapper = PySCFVQEWrapper(molecule_arguments=pyscf_molecule.parameters, n_electrons=pyscf_molecule.n_electrons, + wrapper = PySCFVQEWrapper(molecule_arguments={"parameters":pyscf_molecule.parameters, "transformation":molecule.transformation}, n_electrons=pyscf_molecule.n_electrons, const_part=c, circuit=circuit, vqe_solver_arguments=vqe_solver_arguments, silent=silent, - vqe_solver=vqe_solver, *args, **kwargs) + vqe_solver=vqe_solver, molecule_factory=molecule_factory, *args, **kwargs) mc.fcisolver = wrapper mc.internal_rotation = True if pyscf_arguments is not None: @@ -153,7 +153,7 @@ class PySCFVQEWrapper: # needs initialization n_electrons: int = None - molecule_arguments: ParametersQC = None + molecule_arguments: dict = None # internal data rdm1: numpy.ndarray = None @@ -168,6 +168,7 @@ class PySCFVQEWrapper: vqe_solver: typing.Callable = None circuit: QCircuit = None vqe_solver_arguments: dict = field(default_factory=dict) + molecule_factory: typing.Callable = None def reorder(self, M, ordering, to): # convenience since we need to reorder @@ -183,9 +184,14 @@ def kernel(self, h1, h2, *args, **kwargs): restrict_to_hcb = self.vqe_solver_arguments is not None and "restrict_to_hcb" in self.vqe_solver_arguments and \ self.vqe_solver_arguments["restrict_to_hcb"] - molecule = QuantumChemistryBase(one_body_integrals=h1, two_body_integrals=h2of, + if self.molecule_factory is None: + molecule = QuantumChemistryBase(one_body_integrals=h1, two_body_integrals=h2of, nuclear_repulsion=self.const_part, n_electrons=self.n_electrons, - parameters=self.molecule_arguments) + **self.molecule_arguments) + else: + molecule = self.molecule_factory(one_body_integrals=h1, two_body_integrals=h2of, + nuclear_repulsion=self.const_part, n_electrons=self.n_electrons, + **self.molecule_arguments) if restrict_to_hcb: H = molecule.make_hardcore_boson_hamiltonian() else: @@ -214,7 +220,7 @@ def kernel(self, h1, h2, *args, **kwargs): else: # static ansatz U = self.circuit - + rdm1, rdm2 = molecule.compute_rdms(U=U, variables=result.variables, spin_free=True, get_rdm1=True, get_rdm2=True, use_hcb=restrict_to_hcb) rdm2 = self.reorder(rdm2, 'dirac', 'mulliken') if not self.silent: diff --git a/src/tequila/quantumchemistry/pyscf_interface.py b/src/tequila/quantumchemistry/pyscf_interface.py index d72175400..1b60fd615 100644 --- a/src/tequila/quantumchemistry/pyscf_interface.py +++ b/src/tequila/quantumchemistry/pyscf_interface.py @@ -1,11 +1,9 @@ -from tequila import TequilaException, TequilaWarning, ExpectationValue, QCircuit, minimize -from openfermion import MolecularData +from tequila import TequilaException from tequila.quantumchemistry.qc_base import QuantumChemistryBase from tequila.quantumchemistry import ParametersQC, NBodyTensor -from dataclasses import dataclass, field import pyscf -import numpy, typing, warnings +import numpy, typing class OpenVQEEPySCFException(TequilaException): @@ -71,18 +69,6 @@ def __init__(self, parameters: ParametersQC, super().__init__(parameters=parameters, transformation=transformation, *args, **kwargs) - @classmethod - def from_tequila(cls, molecule, transformation=None, *args, **kwargs): - c, h1, h2 = molecule.get_integrals() - if transformation is None: - transformation = molecule.transformation - return cls(nuclear_repulsion=c, - one_body_integrals=h1, - two_body_integrals=h2, - n_electrons=molecule.n_electrons, - transformation=transformation, - parameters=molecule.parameters, *args, **kwargs) - def compute_fci(self, *args, **kwargs): from pyscf import fci c, h1, h2 = self.get_integrals(ordering="chem") diff --git a/src/tequila/quantumchemistry/qc_base.py b/src/tequila/quantumchemistry/qc_base.py index 385ced81a..0f0c1823c 100644 --- a/src/tequila/quantumchemistry/qc_base.py +++ b/src/tequila/quantumchemistry/qc_base.py @@ -106,6 +106,19 @@ def __init__(self, parameters: ParametersQC, self._rdm1 = None self._rdm2 = None + + @classmethod + def from_tequila(cls, molecule, transformation=None, *args, **kwargs): + c, h1, h2 = molecule.get_integrals() + if transformation is None: + transformation = molecule.transformation + return cls(nuclear_repulsion=c, + one_body_integrals=h1, + two_body_integrals=h2, + n_electrons=molecule.n_electrons, + transformation=transformation, + parameters=molecule.parameters, *args, **kwargs) + def supports_ucc(self): """ check if the current molecule supports UCC operations From cd6c4a34945d59363765aaf1d96695623be3e4f3 Mon Sep 17 00:00:00 2001 From: dariatols Date: Mon, 11 Sep 2023 12:31:33 +0200 Subject: [PATCH 6/6] Adjust iSWAP and Givens implementation according to comments. --- src/tequila/circuit/gates.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/tequila/circuit/gates.py b/src/tequila/circuit/gates.py index aa3275432..d4a182324 100644 --- a/src/tequila/circuit/gates.py +++ b/src/tequila/circuit/gates.py @@ -533,8 +533,13 @@ def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, powe """ generator = paulis.from_string(f"X({first})X({second}) + Y({first})Y({second})") - return GeneralizedRotation(angle=power*(-np.pi/2), control=control, generator=generator, - eigenvalues_magnitude=0.25) + + p0 = paulis.Projector("|00>") + paulis.Projector("|11>") + p0 = p0.map_qubits({0:first, 1:second}) + + gate = QubitExcitationImpl(angle=power*(-np.pi/2), target=generator.qubits, generator=generator, p0=p0, control=control, compile_options="vanilla", *args, **kwargs) + + return QCircuit.wrap_gate(gate) def Givens(first: int, second: int, control: typing.Union[int, list] = None, angle: float = None, *args, @@ -544,7 +549,7 @@ def Givens(first: int, second: int, control: typing.Union[int, list] = None, ang ---------- Givens gate G .. math:: - G = e^{-i\\frac{\\theta}{2} (Y \\otimes X - X \\otimes Y )} + G = e^{-i\\theta \\frac{(Y \\otimes X - X \\otimes Y )}{2}} Parameters ---------- @@ -563,9 +568,7 @@ def Givens(first: int, second: int, control: typing.Union[int, list] = None, ang """ - generator = paulis.from_string(f"1.0*Y({first})X({second}) - 1.0*X({first})Y({second})") - - return GeneralizedRotation(angle=angle, control=control, generator=generator,) + return QubitExcitation(target=[second,first], angle=2*angle, control=control, *args, **kwargs) # twice the angle since theta is not divided by two in the matrix exponential """