From a274e7bc1b60396b2dd054832262325c12e8596c Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Apr 2020 16:27:15 +0200 Subject: [PATCH 1/8] renamings --- qiskit/circuit/library/__init__.py | 14 +++++++------- .../__init__.py | 12 ++++++------ .../pauli_evolution_feature_map.py} | 14 +++++++------- .../z_evolution_feature_map.py} | 12 ++++++------ .../zz_evolution_feature_map.py} | 8 ++++---- test/python/circuit/test_library.py | 14 +++++++------- 6 files changed, 37 insertions(+), 37 deletions(-) rename qiskit/circuit/library/{data_encoding => data_preparation}/__init__.py (87%) rename qiskit/circuit/library/{data_encoding/pauli_expansion.py => data_preparation/pauli_evolution_feature_map.py} (95%) rename qiskit/circuit/library/{data_encoding/first_order_expansion.py => data_preparation/z_evolution_feature_map.py} (93%) rename qiskit/circuit/library/{data_encoding/second_order_expansion.py => data_preparation/zz_evolution_feature_map.py} (95%) diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index b133938571d6..673cd6b00e1e 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -121,9 +121,9 @@ .. autosummary:: :toctree: ../stubs/ - PauliExpansion - FirstOrderExpansion - SecondOrderExpansion + PauliEvolutionFeatureMap + ZEvolutionFeatureMap + ZZEvolutionFeatureMap """ @@ -153,9 +153,9 @@ RYRZ, SwapRZ, ) -from .data_encoding import ( - PauliExpansion, - FirstOrderExpansion, - SecondOrderExpansion +from .data_preparation import ( + PauliEvolutionFeatureMap, + ZEvolutionFeatureMap, + ZZEvolutionFeatureMap ) from .quantum_volume import QuantumVolume diff --git a/qiskit/circuit/library/data_encoding/__init__.py b/qiskit/circuit/library/data_preparation/__init__.py similarity index 87% rename from qiskit/circuit/library/data_encoding/__init__.py rename to qiskit/circuit/library/data_preparation/__init__.py index f29e62eadd22..613724d5e6b5 100644 --- a/qiskit/circuit/library/data_encoding/__init__.py +++ b/qiskit/circuit/library/data_preparation/__init__.py @@ -40,12 +40,12 @@ """ -from .pauli_expansion import PauliExpansion -from .first_order_expansion import FirstOrderExpansion -from .second_order_expansion import SecondOrderExpansion +from .pauli_evolution_feature_map import PauliEvolutionFeatureMap +from .z_evolution_feature_map import ZEvolutionFeatureMap +from .zz_evolution_feature_map import ZZEvolutionFeatureMap __all__ = [ - 'PauliExpansion', - 'FirstOrderExpansion', - 'SecondOrderExpansion', + 'PauliEvolutionFeatureMap', + 'ZEvolutionFeatureMap', + 'ZZEvolutionFeatureMap', ] diff --git a/qiskit/circuit/library/data_encoding/pauli_expansion.py b/qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py similarity index 95% rename from qiskit/circuit/library/data_encoding/pauli_expansion.py rename to qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py index 4fdaf615452a..e211ff3d75a6 100644 --- a/qiskit/circuit/library/data_encoding/pauli_expansion.py +++ b/qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py @@ -25,7 +25,7 @@ from ..n_local.n_local import NLocal -class PauliExpansion(NLocal): +class PauliEvolutionFeatureMap(NLocal): r"""The Pauli Expansion circuit. The Pauli Expansion circuit is a data encoding circuit that transforms input data @@ -60,13 +60,13 @@ class PauliExpansion(NLocal): ┤ H ├┤ U1(2.0*x[1]) ├┤ RX(pi/2) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ RX(-pi/2) ├ └───┘└──────────────┘└──────────┘└───┘└─────────────────────────────────┘└───┘└───────────┘ - Please refer to :class:`FirstOrderExpansion` for the case :math:`k = 1`, :math:`P_0 = Z` - and to :class:`SecondOrderExpansion` for the case :math:`k = 2`, :math:`P_0 = Z` and + Please refer to :class:`ZEvolutionFeatureMap` for the case :math:`k = 1`, :math:`P_0 = Z` + and to :class:`ZZEvolutionFeatureMap` for the case :math:`k = 2`, :math:`P_0 = Z` and :math:`P_{0,1} = ZZ`. Examples: - >>> prep = PauliExpansion(2, reps=1, paulis=['ZZ']) + >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['ZZ']) >>> print(prep) ┌───┐ q_0: ┤ H ├──■───────────────────────────────────────■── @@ -74,7 +74,7 @@ class PauliExpansion(NLocal): q_1: ┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ └───┘└───┘└─────────────────────────────────┘└───┘ - >>> prep = PauliExpansion(2, reps=1, paulis=['Z', 'XX']) + >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['Z', 'XX']) >>> print(prep) ┌───┐┌──────────────┐┌───┐ ┌───┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├┤ H ├──■───────────────────────────────────────■──┤ H ├ @@ -82,7 +82,7 @@ class PauliExpansion(NLocal): q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ H ├ └───┘└──────────────┘└───┘└───┘└─────────────────────────────────┘└───┘└───┘ - >>> prep = PauliExpansion(2, reps=1, paulis=['ZY']) + >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['ZY']) >>> print(prep) ┌───┐┌──────────┐ ┌───────────┐ q_0: ┤ H ├┤ RX(pi/2) ├──■───────────────────────────────────────■──┤ RX(-pi/2) ├ @@ -91,7 +91,7 @@ class PauliExpansion(NLocal): └───┘ └───┘└─────────────────────────────────┘└───┘ >>> from qiskit.circuit.library import RYRZ - >>> prep = PauliExpansion(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) + >>> prep = PauliEvolutionFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) >>> wavefunction = RYRZ(3, entanglement_blocks='cx') >>> classifier = prep.compose(wavefunction >>> classifier.num_parameters diff --git a/qiskit/circuit/library/data_encoding/first_order_expansion.py b/qiskit/circuit/library/data_preparation/z_evolution_feature_map.py similarity index 93% rename from qiskit/circuit/library/data_encoding/first_order_expansion.py rename to qiskit/circuit/library/data_preparation/z_evolution_feature_map.py index c4e6866050bd..e8a88ee75c31 100644 --- a/qiskit/circuit/library/data_encoding/first_order_expansion.py +++ b/qiskit/circuit/library/data_preparation/z_evolution_feature_map.py @@ -17,10 +17,10 @@ from typing import Callable, Optional import numpy as np -from .pauli_expansion import PauliExpansion +from .pauli_evolution_feature_map import PauliEvolutionFeatureMap -class FirstOrderExpansion(PauliExpansion): +class ZEvolutionFeatureMap(PauliEvolutionFeatureMap): """The first order Pauli Z-evolution circuit. On 3 qubits and with 2 repetitions the circuit is represented by: @@ -35,13 +35,13 @@ class FirstOrderExpansion(PauliExpansion): ┤ H ├┤ U1(2.0*x[2]) ├┤ H ├┤ U1(2.0*x[2]) ├ └───┘└──────────────┘└───┘└──────────────┘ - This is a sub-class of :class:`~qiskit.circuit.library.PauliExpansion` where the Pauli + This is a sub-class of :class:`~qiskit.circuit.library.PauliEvolutionFeatureMap` where the Pauli strings are fixed as `['Z']`. As a result the first order expansion will be a circuit without entangling gates. Examples: - >>> prep = FirstOrderExpansion(3, reps=3, insert_barriers=True) + >>> prep = ZEvolutionFeatureMap(3, reps=3, insert_barriers=True) >>> print(prep) ┌───┐ ░ ┌──────────────┐ ░ ┌───┐ ░ ┌──────────────┐ ░ ┌───┐ ░ ┌──────────────┐ q_0: ┤ H ├─░─┤ U1(2.0*x[0]) ├─░─┤ H ├─░─┤ U1(2.0*x[0]) ├─░─┤ H ├─░─┤ U1(2.0*x[0]) ├ @@ -52,7 +52,7 @@ class FirstOrderExpansion(PauliExpansion): └───┘ ░ └──────────────┘ ░ └───┘ ░ └──────────────┘ ░ └───┘ ░ └──────────────┘ >>> data_map = lambda x: x[0]*x[0] + 1 # note: input is an array - >>> prep = FirstOrderExpansion(3, reps=1, data_map_func=data_map) + >>> prep = ZEvolutionFeatureMap(3, reps=1, data_map_func=data_map) >>> print(prep) ┌───┐┌───────────────────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]**2 + 2.0) ├ @@ -62,7 +62,7 @@ class FirstOrderExpansion(PauliExpansion): q_2: ┤ H ├┤ U1(2.0*x[2]**2 + 2.0) ├ └───┘└───────────────────────┘ - >>> classifier = FirstOrderExpansion(3, reps=1) + RY(3, reps=1) + >>> classifier = ZEvolutionFeatureMap(3, reps=1) + RY(3, reps=1) >>> print(classifier) ┌───┐┌──────────────┐┌──────────┐ ┌──────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├┤ RY(θ[0]) ├─■──■─┤ RY(θ[3]) ├──────────── diff --git a/qiskit/circuit/library/data_encoding/second_order_expansion.py b/qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py similarity index 95% rename from qiskit/circuit/library/data_encoding/second_order_expansion.py rename to qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py index 794175ea6459..df720f9e4b87 100644 --- a/qiskit/circuit/library/data_encoding/second_order_expansion.py +++ b/qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py @@ -16,10 +16,10 @@ from typing import Callable, List, Union, Optional import numpy as np -from .pauli_expansion import PauliExpansion +from .pauli_evolution_feature_map import PauliEvolutionFeatureMap -class SecondOrderExpansion(PauliExpansion): +class ZZEvolutionFeatureMap(PauliEvolutionFeatureMap): """Second-order Pauli-Z evolution circuit. For 3 qubits and 1 repetition and linear entanglement the circuit is represented by: @@ -39,7 +39,7 @@ class SecondOrderExpansion(PauliExpansion): Examples: - >>> prep = SecondOrderExpansion(2, reps=2) + >>> prep = ZZEvolutionFeatureMap(2, reps=2) >>> print(prep) ┌───┐┌──────────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├──■───────────────────────────────────────■── @@ -48,7 +48,7 @@ class SecondOrderExpansion(PauliExpansion): └───┘└──────────────┘└───┘└─────────────────────────────────┘└───┘ >>> from qiskit.circuit.library import RYRZ - >>> classifier = SecondOrderExpansion(3) + RYRZ(3) + >>> classifier = ZZEvolutionFeatureMap(3) + RYRZ(3) >>> classifier.num_parameters 15 >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZ parameters diff --git a/test/python/circuit/test_library.py b/test/python/circuit/test_library.py index ac73e339d009..ee4d725787e4 100644 --- a/test/python/circuit/test_library.py +++ b/test/python/circuit/test_library.py @@ -28,8 +28,8 @@ LinearPauliRotations, PolynomialPauliRotations, IntegerComparator, PiecewiseLinearPauliRotations, WeightedAdder, Diagonal, NLocal, TwoLocal, RY, RYRZ, - SwapRZ, PauliExpansion, FirstOrderExpansion, - SecondOrderExpansion) + SwapRZ, PauliEvolutionFeatureMap, ZEvolutionFeatureMap, + ZZEvolutionFeatureMap) from qiskit.circuit.random.utils import random_circuit from qiskit.converters.circuit_to_dag import circuit_to_dag from qiskit.extensions.standard import (XGate, RXGate, RYGate, RZGate, CRXGate, CCXGate, SwapGate, @@ -1393,7 +1393,7 @@ class TestDataEncoding(QiskitTestCase): def test_pauli_empty(self): """Test instantiating an empty Pauli expansion.""" - encoding = PauliExpansion() + encoding = PauliEvolutionFeatureMap() with self.subTest(msg='equal to empty circuit'): self.assertTrue(Operator(encoding).equiv(QuantumCircuit())) @@ -1406,13 +1406,13 @@ def test_pauli_empty(self): @unpack def test_num_parameters(self, num_qubits, reps, pauli_strings): """Test the number of parameters equals the number of qubits, independent of reps.""" - encoding = PauliExpansion(num_qubits, paulis=pauli_strings, reps=reps) + encoding = PauliEvolutionFeatureMap(num_qubits, paulis=pauli_strings, reps=reps) self.assertEqual(encoding.num_parameters, num_qubits) self.assertEqual(encoding.num_parameters_settable, num_qubits) def test_pauli_evolution(self): """Test the generation of Pauli blocks.""" - encoding = PauliExpansion() + encoding = PauliEvolutionFeatureMap() time = 1.4 with self.subTest(pauli_string='ZZ'): evo = QuantumCircuit(2) @@ -1447,7 +1447,7 @@ def test_pauli_evolution(self): def test_first_order_circuit(self): """Test a first order expansion circuit.""" times = [0.2, 1, np.pi, -1.2] - encoding = FirstOrderExpansion(4, reps=3).assign_parameters(times) + encoding = ZEvolutionFeatureMap(4, reps=3).assign_parameters(times) ref = QuantumCircuit(4) for _ in range(3): @@ -1460,7 +1460,7 @@ def test_first_order_circuit(self): def test_second_order_circuit(self): """Test a second order expansion circuit.""" times = [0.2, 1, np.pi] - encoding = SecondOrderExpansion(3, reps=2).assign_parameters(times) + encoding = ZZEvolutionFeatureMap(3, reps=2).assign_parameters(times) def zz_evolution(circuit, qubit1, qubit2): time = (np.pi - times[qubit1]) * (np.pi - times[qubit2]) From 325bc192135c8c16a0af66a8069290eaacc564e1 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Apr 2020 18:23:05 +0200 Subject: [PATCH 2/8] remove 'evolution' and ryrz -> ryrzansatz --- qiskit/circuit/library/__init__.py | 16 ++++++------ .../library/data_preparation/__init__.py | 12 ++++----- ...on_feature_map.py => pauli_feature_map.py} | 18 ++++++------- ...lution_feature_map.py => z_feature_map.py} | 12 ++++----- ...ution_feature_map.py => zz_feature_map.py} | 12 ++++----- qiskit/circuit/library/n_local/__init__.py | 4 +-- qiskit/circuit/library/n_local/ryrz.py | 19 +++++++------- test/python/circuit/test_library.py | 26 +++++++++---------- 8 files changed, 60 insertions(+), 59 deletions(-) rename qiskit/circuit/library/data_preparation/{pauli_evolution_feature_map.py => pauli_feature_map.py} (94%) rename qiskit/circuit/library/data_preparation/{z_evolution_feature_map.py => z_feature_map.py} (93%) rename qiskit/circuit/library/data_preparation/{zz_evolution_feature_map.py => zz_feature_map.py} (93%) diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index 673cd6b00e1e..67566b44523a 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -111,7 +111,7 @@ NLocal TwoLocal RY - RYRZ + RYRZAnsatz SwapRZ @@ -121,9 +121,9 @@ .. autosummary:: :toctree: ../stubs/ - PauliEvolutionFeatureMap - ZEvolutionFeatureMap - ZZEvolutionFeatureMap + PauliFeatureMap + ZFeatureMap + ZZFeatureMap """ @@ -150,12 +150,12 @@ NLocal, TwoLocal, RY, - RYRZ, + RYRZAnsatz, SwapRZ, ) from .data_preparation import ( - PauliEvolutionFeatureMap, - ZEvolutionFeatureMap, - ZZEvolutionFeatureMap + PauliFeatureMap, + ZFeatureMap, + ZZFeatureMap ) from .quantum_volume import QuantumVolume diff --git a/qiskit/circuit/library/data_preparation/__init__.py b/qiskit/circuit/library/data_preparation/__init__.py index 613724d5e6b5..422a70cfc209 100644 --- a/qiskit/circuit/library/data_preparation/__init__.py +++ b/qiskit/circuit/library/data_preparation/__init__.py @@ -40,12 +40,12 @@ """ -from .pauli_evolution_feature_map import PauliEvolutionFeatureMap -from .z_evolution_feature_map import ZEvolutionFeatureMap -from .zz_evolution_feature_map import ZZEvolutionFeatureMap +from .pauli_feature_map import PauliFeatureMap +from .z_feature_map import ZFeatureMap +from .zz_feature_map import ZZFeatureMap __all__ = [ - 'PauliEvolutionFeatureMap', - 'ZEvolutionFeatureMap', - 'ZZEvolutionFeatureMap', + 'PauliFeatureMap', + 'ZFeatureMap', + 'ZZFeatureMap', ] diff --git a/qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py b/qiskit/circuit/library/data_preparation/pauli_feature_map.py similarity index 94% rename from qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py rename to qiskit/circuit/library/data_preparation/pauli_feature_map.py index e211ff3d75a6..555d398a114f 100644 --- a/qiskit/circuit/library/data_preparation/pauli_evolution_feature_map.py +++ b/qiskit/circuit/library/data_preparation/pauli_feature_map.py @@ -25,7 +25,7 @@ from ..n_local.n_local import NLocal -class PauliEvolutionFeatureMap(NLocal): +class PauliFeatureMap(NLocal): r"""The Pauli Expansion circuit. The Pauli Expansion circuit is a data encoding circuit that transforms input data @@ -60,13 +60,13 @@ class PauliEvolutionFeatureMap(NLocal): ┤ H ├┤ U1(2.0*x[1]) ├┤ RX(pi/2) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ RX(-pi/2) ├ └───┘└──────────────┘└──────────┘└───┘└─────────────────────────────────┘└───┘└───────────┘ - Please refer to :class:`ZEvolutionFeatureMap` for the case :math:`k = 1`, :math:`P_0 = Z` - and to :class:`ZZEvolutionFeatureMap` for the case :math:`k = 2`, :math:`P_0 = Z` and + Please refer to :class:`ZFeatureMap` for the case :math:`k = 1`, :math:`P_0 = Z` + and to :class:`ZZFeatureMap` for the case :math:`k = 2`, :math:`P_0 = Z` and :math:`P_{0,1} = ZZ`. Examples: - >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['ZZ']) + >>> prep = PauliFeatureMap(2, reps=1, paulis=['ZZ']) >>> print(prep) ┌───┐ q_0: ┤ H ├──■───────────────────────────────────────■── @@ -74,7 +74,7 @@ class PauliEvolutionFeatureMap(NLocal): q_1: ┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ └───┘└───┘└─────────────────────────────────┘└───┘ - >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['Z', 'XX']) + >>> prep = PauliFeatureMap(2, reps=1, paulis=['Z', 'XX']) >>> print(prep) ┌───┐┌──────────────┐┌───┐ ┌───┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├┤ H ├──■───────────────────────────────────────■──┤ H ├ @@ -82,7 +82,7 @@ class PauliEvolutionFeatureMap(NLocal): q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ H ├ └───┘└──────────────┘└───┘└───┘└─────────────────────────────────┘└───┘└───┘ - >>> prep = PauliEvolutionFeatureMap(2, reps=1, paulis=['ZY']) + >>> prep = PauliFeatureMap(2, reps=1, paulis=['ZY']) >>> print(prep) ┌───┐┌──────────┐ ┌───────────┐ q_0: ┤ H ├┤ RX(pi/2) ├──■───────────────────────────────────────■──┤ RX(-pi/2) ├ @@ -90,9 +90,9 @@ class PauliEvolutionFeatureMap(NLocal): q_1: ┤ H ├────────────┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├───────────── └───┘ └───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZ - >>> prep = PauliEvolutionFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) - >>> wavefunction = RYRZ(3, entanglement_blocks='cx') + >>> from qiskit.circuit.library import RYRZAnsatz + >>> prep = PauliFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) + >>> wavefunction = RYRZAnsatz(3, entanglement_blocks='cx') >>> classifier = prep.compose(wavefunction >>> classifier.num_parameters 27 diff --git a/qiskit/circuit/library/data_preparation/z_evolution_feature_map.py b/qiskit/circuit/library/data_preparation/z_feature_map.py similarity index 93% rename from qiskit/circuit/library/data_preparation/z_evolution_feature_map.py rename to qiskit/circuit/library/data_preparation/z_feature_map.py index e8a88ee75c31..6367840cd4fa 100644 --- a/qiskit/circuit/library/data_preparation/z_evolution_feature_map.py +++ b/qiskit/circuit/library/data_preparation/z_feature_map.py @@ -17,10 +17,10 @@ from typing import Callable, Optional import numpy as np -from .pauli_evolution_feature_map import PauliEvolutionFeatureMap +from .pauli_feature_map import PauliFeatureMap -class ZEvolutionFeatureMap(PauliEvolutionFeatureMap): +class ZFeatureMap(PauliFeatureMap): """The first order Pauli Z-evolution circuit. On 3 qubits and with 2 repetitions the circuit is represented by: @@ -35,13 +35,13 @@ class ZEvolutionFeatureMap(PauliEvolutionFeatureMap): ┤ H ├┤ U1(2.0*x[2]) ├┤ H ├┤ U1(2.0*x[2]) ├ └───┘└──────────────┘└───┘└──────────────┘ - This is a sub-class of :class:`~qiskit.circuit.library.PauliEvolutionFeatureMap` where the Pauli + This is a sub-class of :class:`~qiskit.circuit.library.PauliFeatureMap` where the Pauli strings are fixed as `['Z']`. As a result the first order expansion will be a circuit without entangling gates. Examples: - >>> prep = ZEvolutionFeatureMap(3, reps=3, insert_barriers=True) + >>> prep = ZFeatureMap(3, reps=3, insert_barriers=True) >>> print(prep) ┌───┐ ░ ┌──────────────┐ ░ ┌───┐ ░ ┌──────────────┐ ░ ┌───┐ ░ ┌──────────────┐ q_0: ┤ H ├─░─┤ U1(2.0*x[0]) ├─░─┤ H ├─░─┤ U1(2.0*x[0]) ├─░─┤ H ├─░─┤ U1(2.0*x[0]) ├ @@ -52,7 +52,7 @@ class ZEvolutionFeatureMap(PauliEvolutionFeatureMap): └───┘ ░ └──────────────┘ ░ └───┘ ░ └──────────────┘ ░ └───┘ ░ └──────────────┘ >>> data_map = lambda x: x[0]*x[0] + 1 # note: input is an array - >>> prep = ZEvolutionFeatureMap(3, reps=1, data_map_func=data_map) + >>> prep = ZFeatureMap(3, reps=1, data_map_func=data_map) >>> print(prep) ┌───┐┌───────────────────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]**2 + 2.0) ├ @@ -62,7 +62,7 @@ class ZEvolutionFeatureMap(PauliEvolutionFeatureMap): q_2: ┤ H ├┤ U1(2.0*x[2]**2 + 2.0) ├ └───┘└───────────────────────┘ - >>> classifier = ZEvolutionFeatureMap(3, reps=1) + RY(3, reps=1) + >>> classifier = ZFeatureMap(3, reps=1) + RY(3, reps=1) >>> print(classifier) ┌───┐┌──────────────┐┌──────────┐ ┌──────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├┤ RY(θ[0]) ├─■──■─┤ RY(θ[3]) ├──────────── diff --git a/qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py b/qiskit/circuit/library/data_preparation/zz_feature_map.py similarity index 93% rename from qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py rename to qiskit/circuit/library/data_preparation/zz_feature_map.py index df720f9e4b87..0ae4e93eaed3 100644 --- a/qiskit/circuit/library/data_preparation/zz_evolution_feature_map.py +++ b/qiskit/circuit/library/data_preparation/zz_feature_map.py @@ -16,10 +16,10 @@ from typing import Callable, List, Union, Optional import numpy as np -from .pauli_evolution_feature_map import PauliEvolutionFeatureMap +from .pauli_feature_map import PauliFeatureMap -class ZZEvolutionFeatureMap(PauliEvolutionFeatureMap): +class ZZFeatureMap(PauliFeatureMap): """Second-order Pauli-Z evolution circuit. For 3 qubits and 1 repetition and linear entanglement the circuit is represented by: @@ -39,7 +39,7 @@ class ZZEvolutionFeatureMap(PauliEvolutionFeatureMap): Examples: - >>> prep = ZZEvolutionFeatureMap(2, reps=2) + >>> prep = ZZFeatureMap(2, reps=2) >>> print(prep) ┌───┐┌──────────────┐ q_0: ┤ H ├┤ U1(2.0*x[0]) ├──■───────────────────────────────────────■── @@ -47,11 +47,11 @@ class ZZEvolutionFeatureMap(PauliEvolutionFeatureMap): q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ └───┘└──────────────┘└───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZ - >>> classifier = ZZEvolutionFeatureMap(3) + RYRZ(3) + >>> from qiskit.circuit.library import RYRZAnsatz + >>> classifier = ZZFeatureMap(3) + RYRZAnsatz(3) >>> classifier.num_parameters 15 - >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZ parameters + >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZAnsatz parameters {Parameter(θ[9]), Parameter(θ[4]), Parameter(θ[6]), Parameter(θ[1]), Parameter(x[2]), Parameter(θ[7]), Parameter(x[1]), Parameter(θ[8]), Parameter(θ[2]), Parameter(θ[10]), Parameter(θ[5]), Parameter(θ[0]), Parameter(θ[3]), Parameter(x[0]), Parameter(θ[11])} diff --git a/qiskit/circuit/library/n_local/__init__.py b/qiskit/circuit/library/n_local/__init__.py index fe251047cf22..50a7d45a3407 100644 --- a/qiskit/circuit/library/n_local/__init__.py +++ b/qiskit/circuit/library/n_local/__init__.py @@ -17,13 +17,13 @@ from .n_local import NLocal from .two_local import TwoLocal from .ry import RY -from .ryrz import RYRZ +from .ryrz import RYRZAnsatz from .swaprz import SwapRZ __all__ = [ 'NLocal', 'TwoLocal', 'RY', - 'RYRZ', + 'RYRZAnsatz', 'SwapRZ' ] diff --git a/qiskit/circuit/library/n_local/ryrz.py b/qiskit/circuit/library/n_local/ryrz.py index 0a0714010093..40e108ef325e 100644 --- a/qiskit/circuit/library/n_local/ryrz.py +++ b/qiskit/circuit/library/n_local/ryrz.py @@ -12,7 +12,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""The RYRZ 2-local circuit.""" +"""The RYRZAnsatz 2-local circuit.""" from typing import Union, Optional, List, Tuple, Callable, Any from numpy import pi @@ -22,11 +22,12 @@ from .two_local import TwoLocal -class RYRZ(TwoLocal): - r"""The RYRZ 2-local circuit. +class RYRZAnsatz(TwoLocal): + r"""The RYRZAnsatz 2-local circuit. - The RYRZ circuit consists of layers of :math:`Y` plus :math:`Z` rotations with entanglements. - It can be used to prepare trial wave functions for variational quantum algorithms. + The RYRZAnsatz circuit consists of layers of :math:`Y` plus :math:`Z` rotations with + entanglements. It can be used to prepare trial wave functions for variational quantum + algorithms. .. parsed-literal:: @@ -43,7 +44,7 @@ class RYRZ(TwoLocal): Examples: - >>> ryrz = RYRZ(3, reps=1) # create the variational form on 3 qubits + >>> ryrz = RYRZAnsatz(3, reps=1) # create the variational form on 3 qubits >>> print(ryrz) # show the circuit ┌──────────┐┌──────────┐ ┌──────────┐┌──────────┐ q_0: ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├─■──■─┤ RY(θ[6]) ├┤ RZ(θ[9]) ├───────────── @@ -53,7 +54,7 @@ class RYRZ(TwoLocal): q_2: ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├┤ RZ(θ[11]) ├ └──────────┘└──────────┘ └──────────┘└───────────┘ - >>> ryrz = RYRZ(4, entanglement='circular', reps=1) + >>> ryrz = RYRZAnsatz(4, entanglement='circular', reps=1) >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form >>> qc += ryrz.to_circuit() >>> qc.decompose().draw() @@ -82,10 +83,10 @@ def __init__(self, insert_barriers: bool = False, initial_state: Optional[Any] = None, ) -> None: - """Create a new RYRZ 2-local circuit. + """Create a new RYRZAnsatz 2-local circuit. Args: - num_qubits: The number of qubits of the RYRZ circuit. + num_qubits: The number of qubits of the RYRZAnsatz circuit. reps: Specifies how often the structure of a rotation layer followed by an entanglement layer is repeated. entanglement_blocks: The gates used in the entanglement layer. Can be specified via the diff --git a/test/python/circuit/test_library.py b/test/python/circuit/test_library.py index ee4d725787e4..b74b24348e52 100644 --- a/test/python/circuit/test_library.py +++ b/test/python/circuit/test_library.py @@ -27,9 +27,9 @@ from qiskit.circuit.library import (BlueprintCircuit, Permutation, XOR, InnerProduct, OR, AND, QFT, LinearPauliRotations, PolynomialPauliRotations, IntegerComparator, PiecewiseLinearPauliRotations, - WeightedAdder, Diagonal, NLocal, TwoLocal, RY, RYRZ, - SwapRZ, PauliEvolutionFeatureMap, ZEvolutionFeatureMap, - ZZEvolutionFeatureMap) + WeightedAdder, Diagonal, NLocal, TwoLocal, RY, RYRZAnsatz, + SwapRZ, PauliFeatureMap, ZFeatureMap, + ZZFeatureMap) from qiskit.circuit.random.utils import random_circuit from qiskit.converters.circuit_to_dag import circuit_to_dag from qiskit.extensions.standard import (XGate, RXGate, RYGate, RZGate, CRXGate, CCXGate, SwapGate, @@ -1303,8 +1303,8 @@ def test_ry_circuit(self): self.assertCircuitEqual(library, expected) def test_ryrz_blocks(self): - """Test that the RYRZ circuit is instantiated correctly.""" - two = RYRZ(3) + """Test that the RYRZAnsatz circuit is instantiated correctly.""" + two = RYRZAnsatz(3) with self.subTest(msg='test rotation gate'): self.assertEqual(len(two.rotation_blocks), 2) self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate) @@ -1315,7 +1315,7 @@ def test_ryrz_blocks(self): np.testing.assert_almost_equal(two.parameter_bounds, expected) def test_ryrz_circuit(self): - """Test an RYRZ circuit.""" + """Test an RYRZAnsatz circuit.""" num_qubits = 3 reps = 2 entanglement = 'circular' @@ -1337,8 +1337,8 @@ def test_ryrz_circuit(self): for i in range(num_qubits): expected.rz(next(param_iter), i) - library = RYRZ(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, - entanglement=entanglement).assign_parameters(parameters) + library = RYRZAnsatz(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, + entanglement=entanglement).assign_parameters(parameters) self.assertCircuitEqual(library, expected) @@ -1393,7 +1393,7 @@ class TestDataEncoding(QiskitTestCase): def test_pauli_empty(self): """Test instantiating an empty Pauli expansion.""" - encoding = PauliEvolutionFeatureMap() + encoding = PauliFeatureMap() with self.subTest(msg='equal to empty circuit'): self.assertTrue(Operator(encoding).equiv(QuantumCircuit())) @@ -1406,13 +1406,13 @@ def test_pauli_empty(self): @unpack def test_num_parameters(self, num_qubits, reps, pauli_strings): """Test the number of parameters equals the number of qubits, independent of reps.""" - encoding = PauliEvolutionFeatureMap(num_qubits, paulis=pauli_strings, reps=reps) + encoding = PauliFeatureMap(num_qubits, paulis=pauli_strings, reps=reps) self.assertEqual(encoding.num_parameters, num_qubits) self.assertEqual(encoding.num_parameters_settable, num_qubits) def test_pauli_evolution(self): """Test the generation of Pauli blocks.""" - encoding = PauliEvolutionFeatureMap() + encoding = PauliFeatureMap() time = 1.4 with self.subTest(pauli_string='ZZ'): evo = QuantumCircuit(2) @@ -1447,7 +1447,7 @@ def test_pauli_evolution(self): def test_first_order_circuit(self): """Test a first order expansion circuit.""" times = [0.2, 1, np.pi, -1.2] - encoding = ZEvolutionFeatureMap(4, reps=3).assign_parameters(times) + encoding = ZFeatureMap(4, reps=3).assign_parameters(times) ref = QuantumCircuit(4) for _ in range(3): @@ -1460,7 +1460,7 @@ def test_first_order_circuit(self): def test_second_order_circuit(self): """Test a second order expansion circuit.""" times = [0.2, 1, np.pi] - encoding = ZZEvolutionFeatureMap(3, reps=2).assign_parameters(times) + encoding = ZZFeatureMap(3, reps=2).assign_parameters(times) def zz_evolution(circuit, qubit1, qubit2): time = (np.pi - times[qubit1]) * (np.pi - times[qubit2]) From fc0020a6dae20d6477af2c8226f3761af957bb5b Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Apr 2020 19:50:59 +0200 Subject: [PATCH 3/8] more renaming, missing: SwapRZ --- qiskit/circuit/library/__init__.py | 2 +- qiskit/circuit/library/n_local/__init__.py | 6 +++--- qiskit/circuit/library/n_local/{ry.py => ry_ansatz.py} | 10 +++++----- .../library/n_local/{ryrz.py => ryrz_ansatz.py} | 0 test/python/circuit/test_library.py | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) rename qiskit/circuit/library/n_local/{ry.py => ry_ansatz.py} (97%) rename qiskit/circuit/library/n_local/{ryrz.py => ryrz_ansatz.py} (100%) diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index 67566b44523a..baa8d2d9bb83 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -149,7 +149,7 @@ from .n_local import ( NLocal, TwoLocal, - RY, + RYAnsatz, RYRZAnsatz, SwapRZ, ) diff --git a/qiskit/circuit/library/n_local/__init__.py b/qiskit/circuit/library/n_local/__init__.py index 50a7d45a3407..974da563c241 100644 --- a/qiskit/circuit/library/n_local/__init__.py +++ b/qiskit/circuit/library/n_local/__init__.py @@ -16,14 +16,14 @@ from .n_local import NLocal from .two_local import TwoLocal -from .ry import RY -from .ryrz import RYRZAnsatz +from .ry_ansatz import RYAnsatz +from .ryrz_ansatz import RYRZAnsatz from .swaprz import SwapRZ __all__ = [ 'NLocal', 'TwoLocal', - 'RY', + 'RYAnsatz', 'RYRZAnsatz', 'SwapRZ' ] diff --git a/qiskit/circuit/library/n_local/ry.py b/qiskit/circuit/library/n_local/ry_ansatz.py similarity index 97% rename from qiskit/circuit/library/n_local/ry.py rename to qiskit/circuit/library/n_local/ry_ansatz.py index 30905ab2ca51..dceffc3c667a 100644 --- a/qiskit/circuit/library/n_local/ry.py +++ b/qiskit/circuit/library/n_local/ry_ansatz.py @@ -22,7 +22,7 @@ from .two_local import TwoLocal -class RY(TwoLocal): +class RYAnsatz(TwoLocal): r"""The RY 2-local circuit. The RY trial wave function consistes of alternating layers of :math:`Y` rotations @@ -64,7 +64,7 @@ class RY(TwoLocal): Examples: - >>> ry = RY(3, reps=2) # create the variational form on 3 qubits + >>> ry = RYAnsatz(3, reps=2) # create the variational form on 3 qubits >>> print(ry) # show the circuit ┌──────────┐ ┌──────────┐ ┌──────────┐ q_0: ┤ RY(θ[0]) ├─■──■─┤ RY(θ[3]) ├─────────────■──■─┤ RY(θ[6]) ├──────────── @@ -74,7 +74,7 @@ class RY(TwoLocal): q_2: ┤ RY(θ[2]) ├────■──────■──────┤ RY(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├ └──────────┘ └──────────┘ └──────────┘ - >>> ry = RY(3, entanglement='linear', reps=2, insert_barriers=True) + >>> ry = RYAnsatz(3, entanglement='linear', reps=2, insert_barriers=True) >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form >>> qc += ry.to_circuit() >>> qc.decompose().draw() @@ -86,7 +86,7 @@ class RY(TwoLocal): q_2: ┤ RY(θ[2]) ├─░─────■──░─┤ RY(θ[5]) ├─░─────■──░─┤ RY(θ[8]) ├ └──────────┘ ░ ░ └──────────┘ ░ ░ └──────────┘ - >>> ry = RY(4, 'crx', entanglement='circular', reps=2, insert_barriers=True) + >>> ry = RYAnsatz(4, 'crx', entanglement='circular', reps=2, insert_barriers=True) >>> print(ry) ┌──────────┐ ░ ┌──────────┐ ░ ┌──────────┐ q_0: ┤ RY(θ[0]) ├─░─┤ Rx(θ[4]) ├─────■───────────────────────────────░──┤ RY(θ[8]) ├ @@ -99,7 +99,7 @@ class RY(TwoLocal): └──────────┘ ░ └──────────┘ ░ └───────────┘ >>> entanglement = [[0, 1], [0, 2]] - >>> ry = RY(3, 'cx', entanglement, reps=2) + >>> ry = RYAnsatz(3, 'cx', entanglement, reps=2) >>> print(ry) ┌──────────┐ ┌──────────┐ ┌──────────┐ q_0: ┤ RY(θ[0]) ├──■────────────────■──┤ RY(θ[3]) ├──■────────────────■──┤ RY(θ[6]) ├ diff --git a/qiskit/circuit/library/n_local/ryrz.py b/qiskit/circuit/library/n_local/ryrz_ansatz.py similarity index 100% rename from qiskit/circuit/library/n_local/ryrz.py rename to qiskit/circuit/library/n_local/ryrz_ansatz.py diff --git a/test/python/circuit/test_library.py b/test/python/circuit/test_library.py index b74b24348e52..e2d6452ec488 100644 --- a/test/python/circuit/test_library.py +++ b/test/python/circuit/test_library.py @@ -27,7 +27,7 @@ from qiskit.circuit.library import (BlueprintCircuit, Permutation, XOR, InnerProduct, OR, AND, QFT, LinearPauliRotations, PolynomialPauliRotations, IntegerComparator, PiecewiseLinearPauliRotations, - WeightedAdder, Diagonal, NLocal, TwoLocal, RY, RYRZAnsatz, + WeightedAdder, Diagonal, NLocal, TwoLocal, RYAnsatz, RYRZAnsatz, SwapRZ, PauliFeatureMap, ZFeatureMap, ZZFeatureMap) from qiskit.circuit.random.utils import random_circuit @@ -1269,7 +1269,7 @@ def test_adding_two(self): def test_ry_blocks(self): """Test that the RY circuit is instantiated correctly.""" - two = RY(4) + two = RYAnsatz(4) with self.subTest(msg='test rotation gate'): self.assertEqual(len(two.rotation_blocks), 1) self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate) @@ -1297,8 +1297,8 @@ def test_ry_circuit(self): for i in range(num_qubits): expected.ry(next(param_iter), i) - library = RY(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, - entanglement=entanglement).assign_parameters(parameters) + library = RYAnsatz(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, + entanglement=entanglement).assign_parameters(parameters) self.assertCircuitEqual(library, expected) From 131cc99f6b9b0d13a915e70e235b01c69d0f5a33 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Apr 2020 11:49:22 +0200 Subject: [PATCH 4/8] put ry/ryrz naming on hold --- .../data_preparation/pauli_feature_map.py | 4 ++-- .../library/data_preparation/zz_feature_map.py | 6 +++--- qiskit/circuit/library/n_local/__init__.py | 8 ++++---- qiskit/circuit/library/n_local/ry_ansatz.py | 10 +++++----- qiskit/circuit/library/n_local/ryrz_ansatz.py | 16 ++++++++-------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/qiskit/circuit/library/data_preparation/pauli_feature_map.py b/qiskit/circuit/library/data_preparation/pauli_feature_map.py index 3b0432c6484a..1128bed08450 100644 --- a/qiskit/circuit/library/data_preparation/pauli_feature_map.py +++ b/qiskit/circuit/library/data_preparation/pauli_feature_map.py @@ -90,9 +90,9 @@ class PauliFeatureMap(NLocal): q_1: ┤ H ├────────────┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├───────────── └───┘ └───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZAnsatz + >>> from qiskit.circuit.library import RYRZ >>> prep = PauliFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) - >>> wavefunction = RYRZAnsatz(3, entanglement_blocks='cx') + >>> wavefunction = RYRZ(3, entanglement_blocks='cx') >>> classifier = prep.compose(wavefunction >>> classifier.num_parameters 27 diff --git a/qiskit/circuit/library/data_preparation/zz_feature_map.py b/qiskit/circuit/library/data_preparation/zz_feature_map.py index 0ae4e93eaed3..1fa539cbb5ba 100644 --- a/qiskit/circuit/library/data_preparation/zz_feature_map.py +++ b/qiskit/circuit/library/data_preparation/zz_feature_map.py @@ -47,11 +47,11 @@ class ZZFeatureMap(PauliFeatureMap): q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ └───┘└──────────────┘└───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZAnsatz - >>> classifier = ZZFeatureMap(3) + RYRZAnsatz(3) + >>> from qiskit.circuit.library import RYRZ + >>> classifier = ZZFeatureMap(3) + RYRZ(3) >>> classifier.num_parameters 15 - >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZAnsatz parameters + >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZ parameters {Parameter(θ[9]), Parameter(θ[4]), Parameter(θ[6]), Parameter(θ[1]), Parameter(x[2]), Parameter(θ[7]), Parameter(x[1]), Parameter(θ[8]), Parameter(θ[2]), Parameter(θ[10]), Parameter(θ[5]), Parameter(θ[0]), Parameter(θ[3]), Parameter(x[0]), Parameter(θ[11])} diff --git a/qiskit/circuit/library/n_local/__init__.py b/qiskit/circuit/library/n_local/__init__.py index 974da563c241..310b8e43ebb7 100644 --- a/qiskit/circuit/library/n_local/__init__.py +++ b/qiskit/circuit/library/n_local/__init__.py @@ -16,14 +16,14 @@ from .n_local import NLocal from .two_local import TwoLocal -from .ry_ansatz import RYAnsatz -from .ryrz_ansatz import RYRZAnsatz +from .ry_ansatz import RY +from .ryrz_ansatz import RYRZ from .swaprz import SwapRZ __all__ = [ 'NLocal', 'TwoLocal', - 'RYAnsatz', - 'RYRZAnsatz', + 'RY', + 'RYRZ', 'SwapRZ' ] diff --git a/qiskit/circuit/library/n_local/ry_ansatz.py b/qiskit/circuit/library/n_local/ry_ansatz.py index 5883949ad778..e26ccc9c9cf9 100644 --- a/qiskit/circuit/library/n_local/ry_ansatz.py +++ b/qiskit/circuit/library/n_local/ry_ansatz.py @@ -22,7 +22,7 @@ from .two_local import TwoLocal -class RYAnsatz(TwoLocal): +class RY(TwoLocal): r"""The RY 2-local circuit. The RY trial wave function consistes of alternating layers of :math:`Y` rotations @@ -64,7 +64,7 @@ class RYAnsatz(TwoLocal): Examples: - >>> ry = RYAnsatz(3, reps=2) # create the variational form on 3 qubits + >>> ry = RY(3, reps=2) # create the variational form on 3 qubits >>> print(ry) # show the circuit ┌──────────┐ ┌──────────┐ ┌──────────┐ q_0: ┤ RY(θ[0]) ├─■──■─┤ RY(θ[3]) ├─────────────■──■─┤ RY(θ[6]) ├──────────── @@ -74,7 +74,7 @@ class RYAnsatz(TwoLocal): q_2: ┤ RY(θ[2]) ├────■──────■──────┤ RY(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├ └──────────┘ └──────────┘ └──────────┘ - >>> ry = RYAnsatz(3, entanglement='linear', reps=2, insert_barriers=True) + >>> ry = RY(3, entanglement='linear', reps=2, insert_barriers=True) >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form >>> qc += ry.to_circuit() >>> qc.decompose().draw() @@ -86,7 +86,7 @@ class RYAnsatz(TwoLocal): q_2: ┤ RY(θ[2]) ├─░─────■──░─┤ RY(θ[5]) ├─░─────■──░─┤ RY(θ[8]) ├ └──────────┘ ░ ░ └──────────┘ ░ ░ └──────────┘ - >>> ry = RYAnsatz(4, 'crx', entanglement='circular', reps=2, insert_barriers=True) + >>> ry = RY(4, 'crx', entanglement='circular', reps=2, insert_barriers=True) >>> print(ry) ┌──────────┐ ░ ┌──────────┐ ░ ┌──────────┐ q_0: ┤ RY(θ[0]) ├─░─┤ Rx(θ[4]) ├─────■───────────────────────────────░──┤ RY(θ[8]) ├ @@ -99,7 +99,7 @@ class RYAnsatz(TwoLocal): └──────────┘ ░ └──────────┘ ░ └───────────┘ >>> entanglement = [[0, 1], [0, 2]] - >>> ry = RYAnsatz(3, 'cx', entanglement, reps=2) + >>> ry = RY(3, 'cx', entanglement, reps=2) >>> print(ry) ┌──────────┐ ┌──────────┐ ┌──────────┐ q_0: ┤ RY(θ[0]) ├──■────────────────■──┤ RY(θ[3]) ├──■────────────────■──┤ RY(θ[6]) ├ diff --git a/qiskit/circuit/library/n_local/ryrz_ansatz.py b/qiskit/circuit/library/n_local/ryrz_ansatz.py index 177f20562cdb..863db56cc0a6 100644 --- a/qiskit/circuit/library/n_local/ryrz_ansatz.py +++ b/qiskit/circuit/library/n_local/ryrz_ansatz.py @@ -12,7 +12,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""The RYRZAnsatz 2-local circuit.""" +"""The RYRZ 2-local circuit.""" from typing import Union, Optional, List, Tuple, Callable, Any from numpy import pi @@ -22,10 +22,10 @@ from .two_local import TwoLocal -class RYRZAnsatz(TwoLocal): - r"""The RYRZAnsatz 2-local circuit. +class RYRZ(TwoLocal): + r"""The RYRZ 2-local circuit. - The RYRZAnsatz circuit consists of layers of :math:`Y` plus :math:`Z` rotations with + The RYRZ circuit consists of layers of :math:`Y` plus :math:`Z` rotations with entanglements. It can be used to prepare trial wave functions for variational quantum algorithms. @@ -44,7 +44,7 @@ class RYRZAnsatz(TwoLocal): Examples: - >>> ryrz = RYRZAnsatz(3, reps=1) # create the variational form on 3 qubits + >>> ryrz = RYRZ(3, reps=1) # create the variational form on 3 qubits >>> print(ryrz) # show the circuit ┌──────────┐┌──────────┐ ┌──────────┐┌──────────┐ q_0: ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├─■──■─┤ RY(θ[6]) ├┤ RZ(θ[9]) ├───────────── @@ -54,7 +54,7 @@ class RYRZAnsatz(TwoLocal): q_2: ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├┤ RZ(θ[11]) ├ └──────────┘└──────────┘ └──────────┘└───────────┘ - >>> ryrz = RYRZAnsatz(4, entanglement='circular', reps=1) + >>> ryrz = RYRZ(4, entanglement='circular', reps=1) >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form >>> qc += ryrz.to_circuit() >>> qc.decompose().draw() @@ -83,10 +83,10 @@ def __init__(self, insert_barriers: bool = False, initial_state: Optional[Any] = None, ) -> None: - """Create a new RYRZAnsatz 2-local circuit. + """Create a new RYRZ 2-local circuit. Args: - num_qubits: The number of qubits of the RYRZAnsatz circuit. + num_qubits: The number of qubits of the RYRZ circuit. reps: Specifies how often the structure of a rotation layer followed by an entanglement layer is repeated. entanglement_blocks: The gates used in the entanglement layer. Can be specified via the From 9e8cdc56c673e8a2ef386751edc55eae0acaff54 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Apr 2020 19:48:04 +0200 Subject: [PATCH 5/8] rename n local circuits --- qiskit/circuit/library/__init__.py | 12 +- .../library/data_encoding/pauli_expansion.py | 4 +- .../data_encoding/second_order_expansion.py | 6 +- .../data_preparation/pauli_feature_map.py | 261 ++++++++++++++++++ qiskit/circuit/library/n_local/__init__.py | 12 +- .../circuit/library/n_local/efficient_su2.py | 141 ++++++++++ .../{swaprz.py => excitation_preserving.py} | 87 +++--- .../library/n_local/real_amplitudes.py | 161 +++++++++++ qiskit/circuit/library/n_local/ry.py | 178 ------------ qiskit/circuit/library/n_local/ryrz.py | 133 --------- test/python/circuit/test_library.py | 71 +++-- 11 files changed, 683 insertions(+), 383 deletions(-) create mode 100644 qiskit/circuit/library/data_preparation/pauli_feature_map.py create mode 100644 qiskit/circuit/library/n_local/efficient_su2.py rename qiskit/circuit/library/n_local/{swaprz.py => excitation_preserving.py} (63%) create mode 100644 qiskit/circuit/library/n_local/real_amplitudes.py delete mode 100644 qiskit/circuit/library/n_local/ry.py delete mode 100644 qiskit/circuit/library/n_local/ryrz.py diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index 47e21ea2add2..175f37b0354d 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -155,9 +155,9 @@ NLocal TwoLocal - RY - RYRZ - SwapRZ + RealAmplitudes + EfficientSU2 + ExcitationPreserving Data encoding circuits @@ -201,9 +201,9 @@ from .n_local import ( NLocal, TwoLocal, - RY, - RYRZ, - SwapRZ, + RealAmplitudes, + EfficientSU2, + ExcitationPreserving, ) from .data_encoding import ( PauliExpansion, diff --git a/qiskit/circuit/library/data_encoding/pauli_expansion.py b/qiskit/circuit/library/data_encoding/pauli_expansion.py index 29ad762c048c..d586c4a39454 100644 --- a/qiskit/circuit/library/data_encoding/pauli_expansion.py +++ b/qiskit/circuit/library/data_encoding/pauli_expansion.py @@ -90,9 +90,9 @@ class PauliExpansion(NLocal): q_1: ┤ H ├────────────┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├───────────── └───┘ └───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZ + >>> from qiskit.circuit.library import EfficientSU2 >>> prep = PauliExpansion(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) - >>> wavefunction = RYRZ(3, entanglement_blocks='cx') + >>> wavefunction = EfficientSU2(3, entanglement_blocks='cx') >>> classifier = prep.compose(wavefunction >>> classifier.num_parameters 27 diff --git a/qiskit/circuit/library/data_encoding/second_order_expansion.py b/qiskit/circuit/library/data_encoding/second_order_expansion.py index 794175ea6459..16f05b1f08b9 100644 --- a/qiskit/circuit/library/data_encoding/second_order_expansion.py +++ b/qiskit/circuit/library/data_encoding/second_order_expansion.py @@ -47,11 +47,11 @@ class SecondOrderExpansion(PauliExpansion): q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ └───┘└──────────────┘└───┘└─────────────────────────────────┘└───┘ - >>> from qiskit.circuit.library import RYRZ - >>> classifier = SecondOrderExpansion(3) + RYRZ(3) + >>> from qiskit.circuit.library import EfficientSU2 + >>> classifier = SecondOrderExpansion(3) + EfficientSU2(3) >>> classifier.num_parameters 15 - >>> classifier.parameters # 'x' for the data preparation, 'θ' for the RYRZ parameters + >>> classifier.parameters # 'x' for the data preparation, 'θ' for the EfficientSU2 parameters {Parameter(θ[9]), Parameter(θ[4]), Parameter(θ[6]), Parameter(θ[1]), Parameter(x[2]), Parameter(θ[7]), Parameter(x[1]), Parameter(θ[8]), Parameter(θ[2]), Parameter(θ[10]), Parameter(θ[5]), Parameter(θ[0]), Parameter(θ[3]), Parameter(x[0]), Parameter(θ[11])} diff --git a/qiskit/circuit/library/data_preparation/pauli_feature_map.py b/qiskit/circuit/library/data_preparation/pauli_feature_map.py new file mode 100644 index 000000000000..e98bf842e470 --- /dev/null +++ b/qiskit/circuit/library/data_preparation/pauli_feature_map.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""The Pauli expansion circuit module.""" + +from typing import Optional, Callable, List, Union +from functools import reduce +import numpy as np + +from qiskit.circuit import QuantumCircuit +from qiskit.circuit import Parameter, ParameterVector +from qiskit.circuit.library.standard_gates import HGate + +from ..n_local.n_local import NLocal + + +class PauliFeatureMap(NLocal): + r"""The Pauli Expansion circuit. + + The Pauli Expansion circuit is a data encoding circuit that transforms input data + :math:`\vec{x} \in \mathbb{R}^n` as + + .. math:: + + U_{\Phi(\vec{x})}=\exp\left(i\sum_{S\subseteq [n]} + \phi_S(\vec{x})\prod_{i\in S} P_i\right) + + The circuit contains ``reps`` repetitions of this transformation. + The variable :math:`P_i \in \{ I, X, Y, Z \}` denotes the Pauli matrices. + The index :math:`S` describes connectivities between different qubits or datapoints: + :math:`S \in \{\binom{n}{k}\ combinations,\ k = 1,... n \}`. Per default the data-mapping + :math:`\phi_S` is + + .. math:: + + \phi_S(\vec{x}) = \begin{cases} + x_0 \text{ if } k = 1 \\ + \prod_{j \in S} (\pi - x_j) + + For example, if the Pauli strings are chosen to be :math:`P_0 = Z` and :math:`P_{0,1} = YY` on + 2 qubits and with 1 repetition using the default data-mapping, the Pauli evolution feature map + is represented by: + + .. parsed-literal:: + + ┌───┐┌──────────────┐┌──────────┐ ┌───────────┐ + ┤ H ├┤ U1(2.0*x[0]) ├┤ RX(pi/2) ├──■───────────────────────────────────────■──┤ RX(-pi/2) ├ + ├───┤├──────────────┤├──────────┤┌─┴─┐┌─────────────────────────────────┐┌─┴─┐├───────────┤ + ┤ H ├┤ U1(2.0*x[1]) ├┤ RX(pi/2) ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ RX(-pi/2) ├ + └───┘└──────────────┘└──────────┘└───┘└─────────────────────────────────┘└───┘└───────────┘ + + Please refer to :class:`ZFeatureMap` for the case :math:`k = 1`, :math:`P_0 = Z` + and to :class:`ZZFeatureMap` for the case :math:`k = 2`, :math:`P_0 = Z` and + :math:`P_{0,1} = ZZ`. + + Examples: + + >>> prep = PauliFeatureMap(2, reps=1, paulis=['ZZ']) + >>> print(prep) + ┌───┐ + q_0: ┤ H ├──■───────────────────────────────────────■── + ├───┤┌─┴─┐┌─────────────────────────────────┐┌─┴─┐ + q_1: ┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├ + └───┘└───┘└─────────────────────────────────┘└───┘ + + >>> prep = PauliFeatureMap(2, reps=1, paulis=['Z', 'XX']) + >>> print(prep) + ┌───┐┌──────────────┐┌───┐ ┌───┐ + q_0: ┤ H ├┤ U1(2.0*x[0]) ├┤ H ├──■───────────────────────────────────────■──┤ H ├ + ├───┤├──────────────┤├───┤┌─┴─┐┌─────────────────────────────────┐┌─┴─┐├───┤ + q_1: ┤ H ├┤ U1(2.0*x[1]) ├┤ H ├┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├┤ H ├ + └───┘└──────────────┘└───┘└───┘└─────────────────────────────────┘└───┘└───┘ + + >>> prep = PauliFeatureMap(2, reps=1, paulis=['ZY']) + >>> print(prep) + ┌───┐┌──────────┐ ┌───────────┐ + q_0: ┤ H ├┤ RX(pi/2) ├──■───────────────────────────────────────■──┤ RX(-pi/2) ├ + ├───┤└──────────┘┌─┴─┐┌─────────────────────────────────┐┌─┴─┐└───────────┘ + q_1: ┤ H ├────────────┤ X ├┤ U1(2.0*(pi - x[0])*(pi - x[1])) ├┤ X ├───────────── + └───┘ └───┘└─────────────────────────────────┘└───┘ + + >>> from qiskit.circuit.library import EfficientSU2 + >>> prep = PauliFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ']) + >>> wavefunction = EfficientSU2(3, entanglement_blocks='cx') + >>> classifier = prep.compose(wavefunction + >>> classifier.num_parameters + 27 + >>> classifier.count_ops() + OrderedDict([('cx', 39), ('rx', 36), ('u1', 21), ('h', 15), ('ry', 12), ('rz', 12)]) + + References: + [1]: Havlicek et al. (2018), Supervised learning with quantum enhanced feature spaces. + `arXiv:1804.11326 `_ + """ + + def __init__(self, + feature_dimension: Optional[int] = None, + reps: int = 2, + entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', + paulis: Optional[List[str]] = None, + data_map_func: Optional[Callable[[np.ndarray], float]] = None, + parameter_prefix: str = 'x', + insert_barriers: bool = False, + ) -> None: + """Create a new Pauli expansion circuit. + + Args: + feature_dimension: Number of qubits in the circuit. + reps: The number of repeated circuits. + entanglement: Specifies the entanglement structure. Refer to + :class:`~qiskit.circuit.library.NLocal` for detail. + paulis: A list of strings for to-be-used paulis. If None are provided, ``['Z', 'ZZ']`` + will be used. + data_map_func: A mapping function for data x which can be supplied to override the + default mapping from :meth:`self_product`. + parameter_prefix: The prefix used if default parameters are generated. + insert_barriers: If True, barriers are inserted in between the evolution instructions + and hadamard layers. + + """ + + super().__init__(num_qubits=feature_dimension, + reps=reps, + rotation_blocks=HGate(), + entanglement=entanglement, + parameter_prefix=parameter_prefix, + insert_barriers=insert_barriers, + skip_final_rotation_layer=True) + + self._data_map_func = data_map_func or self_product + self._paulis = paulis or ['Z', 'ZZ'] + + # pylint: disable=unused-argument + def _parameter_generator(self, rep: int, block: int, indices: List[int] + ) -> Optional[List[Parameter]]: + """If certain blocks should use certain parameters this method can be overriden.""" + params = [self.ordered_parameters[i] for i in indices] + return params + + @property + def num_parameters_settable(self): + """The number of distinct parameters.""" + return self.feature_dimension + + @property + def paulis(self) -> List[str]: + """The Pauli strings used in the entanglement of the qubits. + + Returns: + The Pauli strings as list. + """ + return self._paulis + + @paulis.setter + def paulis(self, paulis: List[str]) -> None: + """Set the pauli strings. + + Args: + paulis: The new pauli strings. + """ + self._invalidate() + self._paulis = paulis + + @property + def entanglement_blocks(self): + return [self.pauli_block(pauli) for pauli in self._paulis] + + @entanglement_blocks.setter + def entanglement_blocks(self, entanglement_blocks): + self._entanglement_blocks = entanglement_blocks + + @property + def feature_dimension(self) -> int: + """Returns the feature dimension (which is equal to the number of qubits). + + Returns: + The feature dimension of this feature map. + """ + return self.num_qubits + + @feature_dimension.setter + def feature_dimension(self, feature_dimension: int) -> None: + """Set the feature dimension. + + Args: + feature_dimension: The new feature dimension. + """ + self.num_qubits = feature_dimension + + def _extract_data_for_rotation(self, pauli, x): + where_non_i = np.where(np.asarray(list(pauli[::-1])) != 'I')[0] + x = np.asarray(x) + return x[where_non_i] + + def pauli_block(self, pauli_string): + """Get the Pauli block for the feature map circuit.""" + params = ParameterVector('_', length=len(pauli_string)) + time = self._data_map_func(np.asarray(params)) + return self.pauli_evolution(pauli_string, time) + + def pauli_evolution(self, pauli_string, time): + """Get the evolution block for the given pauli string.""" + # for some reason this is in reversed order + pauli_string = pauli_string[::-1] + + # trim the pauli string if identities are included + trimmed = [] + indices = [] + for i, pauli in enumerate(pauli_string): + if pauli != 'I': + trimmed += [pauli] + indices += [i] + + evo = QuantumCircuit(len(pauli_string)) + + if len(trimmed) == 0: + return evo + + def basis_change(circuit, inverse=False): + for i, pauli in enumerate(pauli_string): + if pauli == 'X': + circuit.h(i) + elif pauli == 'Y': + circuit.rx(-np.pi / 2 if inverse else np.pi / 2, i) + + def cx_chain(circuit, inverse=False): + num_cx = len(indices) - 1 + for i in reversed(range(num_cx)) if inverse else range(num_cx): + circuit.cx(indices[i], indices[i + 1]) + + basis_change(evo) + cx_chain(evo) + evo.u1(2.0 * time, indices[-1]) + cx_chain(evo, inverse=True) + basis_change(evo, inverse=True) + return evo + + +def self_product(x: np.ndarray) -> float: + """ + Define a function map from R^n to R. + + Args: + x: data + + Returns: + float: the mapped value + """ + coeff = x[0] if len(x) == 1 else reduce(lambda m, n: m * n, np.pi - x) + return coeff diff --git a/qiskit/circuit/library/n_local/__init__.py b/qiskit/circuit/library/n_local/__init__.py index fe251047cf22..2a5e3c57572f 100644 --- a/qiskit/circuit/library/n_local/__init__.py +++ b/qiskit/circuit/library/n_local/__init__.py @@ -16,14 +16,14 @@ from .n_local import NLocal from .two_local import TwoLocal -from .ry import RY -from .ryrz import RYRZ -from .swaprz import SwapRZ +from .real_amplitudes import RealAmplitudes +from .efficient_su2 import EfficientSU2 +from .excitation_preserving import ExcitationPreserving __all__ = [ 'NLocal', 'TwoLocal', - 'RY', - 'RYRZ', - 'SwapRZ' + 'RealAmplitudes', + 'EfficientSU2', + 'ExcitationPreserving' ] diff --git a/qiskit/circuit/library/n_local/efficient_su2.py b/qiskit/circuit/library/n_local/efficient_su2.py new file mode 100644 index 000000000000..f63b7183c562 --- /dev/null +++ b/qiskit/circuit/library/n_local/efficient_su2.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""The EfficientSU2 2-local circuit.""" + +from typing import Union, Optional, List, Tuple, Callable, Any +from numpy import pi + +from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.circuit.library.standard_gates import RYGate, RZGate, CXGate +from .two_local import TwoLocal + + +class EfficientSU2(TwoLocal): + r"""The hardware efficient SU(2) 2-local circuit. + + The ``EfficientSU2`` circuit consists of layers of single qubit operations spanned by SU(2) + and :math:`CX` entanglements. This is a heuristic pattern that can be used to prepare trial wave + functions for variational quantum algorithms or classification circuit for machine learning. + + SU(2) stands for special unitary group of degree 2, its elements are :math:`2 \times 2` + unitary matrices with determinant 1, such as the Pauli rotation gates. + + On 3 qubits and using the Pauli :math:`Y` and :math:`Z` su2_gates as single qubit gates, the + hardware efficient SU(2) circuit is represented by: + + .. parsed-literal:: + + ┌──────────┐┌──────────┐ ░ ░ ░ ┌───────────┐┌───────────┐ + ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├─░───■────■────────░─ ... ─░─┤ RY(θ[12]) ├┤ RZ(θ[15]) ├ + ├──────────┤├──────────┤ ░ ┌─┴─┐ │ ░ ░ ├───────────┤├───────────┤ + ┤ RY(θ[1]) ├┤ RZ(θ[4]) ├─░─┤ X ├──┼────■───░─ ... ─░─┤ RY(θ[13]) ├┤ RZ(θ[16]) ├ + ├──────────┤├──────────┤ ░ └───┘┌─┴─┐┌─┴─┐ ░ ░ ├───────────┤├───────────┤ + ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├─░──────┤ X ├┤ X ├─░─ ... ─░─┤ RY(θ[14]) ├┤ RZ(θ[17]) ├ + └──────────┘└──────────┘ ░ └───┘└───┘ ░ ░ └───────────┘└───────────┘ + + See :class:`~qiskit.circuit.library.RealAmplitudes` for more detail on the possible arguments + and options such as skipping unentanglement qubits, which apply here too. + + Examples: + + >>> circuit = EfficientSU2(3, reps=1) + >>> print(circuit) + ┌──────────┐┌──────────┐ ┌──────────┐┌──────────┐ + q_0: ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├──■────■──┤ RY(θ[6]) ├┤ RZ(θ[9]) ├───────────── + ├──────────┤├──────────┤┌─┴─┐ │ └──────────┘├──────────┤┌───────────┐ + q_1: ┤ RY(θ[1]) ├┤ RZ(θ[4]) ├┤ X ├──┼───────■──────┤ RY(θ[7]) ├┤ RZ(θ[10]) ├ + ├──────────┤├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤├───────────┤ + q_2: ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├─────┤ X ├───┤ X ├────┤ RY(θ[8]) ├┤ RZ(θ[11]) ├ + └──────────┘└──────────┘ └───┘ └───┘ └──────────┘└───────────┘ + + >>> ansatz = EfficientSU2(4, su2_gates=['rx', 'y'], entanglement='circular', reps=1) + >>> qc = QuantumCircuit(4) # create a circuit and append the RY variational form + >>> qc.compose(ansatz, inplace=True) + >>> qc.draw() + + ┌──────────┐┌───┐┌───┐ ┌──────────┐ ┌───┐ + q_0: ┤ RX(θ[0]) ├┤ Y ├┤ X ├──■──┤ RX(θ[4]) ├───┤ Y ├───────────────────── + ├──────────┤├───┤└─┬─┘┌─┴─┐└──────────┘┌──┴───┴───┐ ┌───┐ + q_1: ┤ RX(θ[1]) ├┤ Y ├──┼──┤ X ├─────■──────┤ RX(θ[5]) ├───┤ Y ├───────── + ├──────────┤├───┤ │ └───┘ ┌─┴─┐ └──────────┘┌──┴───┴───┐┌───┐ + q_2: ┤ RX(θ[2]) ├┤ Y ├──┼──────────┤ X ├─────────■──────┤ RX(θ[6]) ├┤ Y ├ + ├──────────┤├───┤ │ └───┘ ┌─┴─┐ ├──────────┤├───┤ + q_3: ┤ RX(θ[3]) ├┤ Y ├──■──────────────────────┤ X ├────┤ RX(θ[7]) ├┤ Y ├ + └──────────┘└───┘ └───┘ └──────────┘└───┘ + """ + + def __init__(self, + num_qubits: Optional[int] = None, + su2_gates: Optional[Union[ + str, type, Instruction, QuantumCircuit, + List[Union[str, type, Instruction, QuantumCircuit]] + ]] = None, + entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', + reps: int = 3, + skip_unentangled_qubits: bool = False, + skip_final_rotation_layer: bool = False, + parameter_prefix: str = 'θ', + insert_barriers: bool = False, + initial_state: Optional[Any] = None, + ) -> None: + """Create a new EfficientSU2 2-local circuit. + + Args: + num_qubits: The number of qubits of the EfficientSU2 circuit. + reps: Specifies how often the structure of a rotation layer followed by an entanglement + layer is repeated. + su2_gates: The SU(2) single qubit gates to apply in single qubit gate layers. + If only one gate is provided, the same gate is applied to each qubit. + If a list of gates is provided, all gates are applied to each qubit in the provided + order. + entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' + , 'circular' or 'sca'), a list of integer-pairs specifying the indices of qubits + entangled with one another, or a callable returning such a list provided with + the index of the entanglement layer. + See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more + detail. + initial_state: An `InitialState` object to prepend to the circuit. + skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits + that are entangled with another qubit. If False, the single qubit gates are applied + to each qubit in the Ansatz. Defaults to False. + skip_final_rotation_layer: If False, a rotation layer is added at the end of the + ansatz. If True, no rotation layer is added. + parameter_prefix: The parameterized gates require a parameter to be defined, for which + we use :class:`~qiskit.circuit.ParameterVector`. + insert_barriers: If True, barriers are inserted in between each layer. If False, + no barriers are inserted. + + """ + if su2_gates is None: + su2_gates = [RYGate, RZGate] + super().__init__(num_qubits=num_qubits, + rotation_blocks=su2_gates, + entanglement_blocks=CXGate, + entanglement=entanglement, + reps=reps, + skip_unentangled_qubits=skip_unentangled_qubits, + skip_final_rotation_layer=skip_final_rotation_layer, + parameter_prefix=parameter_prefix, + insert_barriers=insert_barriers, + initial_state=initial_state) + + @property + def parameter_bounds(self) -> List[Tuple[float, float]]: + """Return the parameter bounds. + + Returns: + The parameter bounds. + """ + return self.num_parameters * [(-pi, pi)] diff --git a/qiskit/circuit/library/n_local/swaprz.py b/qiskit/circuit/library/n_local/excitation_preserving.py similarity index 63% rename from qiskit/circuit/library/n_local/swaprz.py rename to qiskit/circuit/library/n_local/excitation_preserving.py index 894d59c709bf..a9396ac9e62b 100644 --- a/qiskit/circuit/library/n_local/swaprz.py +++ b/qiskit/circuit/library/n_local/excitation_preserving.py @@ -12,7 +12,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""The SwapRZ 2-local circuit.""" +"""The ExcitationPreserving 2-local circuit.""" from typing import Union, Optional, List, Tuple, Callable, Any from numpy import pi @@ -22,42 +22,43 @@ from .two_local import TwoLocal -class SwapRZ(TwoLocal): - r"""The SwapRZ ansatz. +class ExcitationPreserving(TwoLocal): + r"""The heurisitic excitation-preserving wave function ansatz. - This trial wave function is layers of :math:`Z` rotations with entanglements using 2-qubit - :math:`XX+YY` rotations. It was designed principally to be a particle-preserving wave function - for :mod:`qiskit.chemistry`. Given an initial state as a set of 1's and 0's it will preserve - the number of 1's - where for chemistry a 1 will indicate a particle. + The ``ExcitationPreserving`` circuit preserves the ratio of :math:`|00\rangle`, + :math:`|01\rangle + |10\rangle` and :math:`|11\rangle` states. The matrix representing + the operation is - Note: - - In chemistry, to define the particles for SwapRZ, use a - :class:`~qiskit.chemistry.components.initial_states.HartreeFock` initial state with - the `Jordan-Wigner` qubit mapping + .. math:: - See :class:`~qiskit.circuit.library.RY` for more detail on the possible arguments and options - such as skipping unentanglement qubits, which apply here too. + \newcommand{\th}{\theta/2} - The rotations of the SwapRZ ansatz can be written as + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & \cos(\th) & -\sin(\th) & 0 \\ + 0 & \sin(\th) & \cos(\th) & 0 \\ + 0 & 0 & 0 e^{-i\phi} + \end{pmatrix} - .. math:: - R_Z(\theta) = e^{-i \theta Z} + for the mode ``'fsim'`` or with :math:`e^{-i\phi} = 1` for the mode ``'iswap'``. - and + Note that other wave functions, such as UCC-ansatzes, are also excitation preserving. + However these can become complex quickly, while this heuristically motivated circuit follows + a simpler pattern. - .. math:: + This trial wave function consists of layers of :math:`Z` rotations with 2-qubit entanglements. + The entangling is creating using :math:`XX+YY` rotations and optionally a controlled-phase + gate for the mode ``'fsim'``. - R_{XX+YY}(\theta) = e^{-i \theta / 2 (X \otimes X + Y \otimes Y)} - \approx e^{-i \theta / 2 X \otimes X} e^{-i \theta /2 Y \otimes Y } - = R_{XX}(\theta) R_{YY}(\theta) + See :class:`~qiskit.circuit.library.RealAmplitudes` for more detail on the possible arguments + and options such as skipping unentanglement qubits, which apply here too. - where the approximation used comes from the Trotter expansion of the sum in the exponential. + The rotations of the ExcitationPreserving ansatz can be written as Examples: - >>> swaprz = SwapRZ(3, reps=1, insert_barriers=True, entanglement='linear') - >>> print(swaprz) # show the circuit + >>> ansatz = ExcitationPreserving(3, reps=1, insert_barriers=True, entanglement='linear') + >>> print(ansatz) # show the circuit ┌──────────┐ ░ ┌────────────┐┌────────────┐ ░ ┌──────────┐ q_0: ┤ RZ(θ[0]) ├─░─┤0 ├┤0 ├─────────────────────────────░─┤ RZ(θ[5]) ├ ├──────────┤ ░ │ RXX(θ[3]) ││ RYY(θ[3]) │┌────────────┐┌────────────┐ ░ ├──────────┤ @@ -66,10 +67,10 @@ class SwapRZ(TwoLocal): q_2: ┤ RZ(θ[2]) ├─░─────────────────────────────┤1 ├┤1 ├─░─┤ RZ(θ[7]) ├ └──────────┘ ░ └────────────┘└────────────┘ ░ └──────────┘ - >>> swaprz = SwapRZ(2, reps=1) + >>> ansatz = ExcitationPreserving(2, reps=1) >>> qc = QuantumCircuit(2) # create a circuit and append the RY variational form >>> qc.cry(0.2, 0, 1) # do some previous operation - >>> qc.compose(swaprz, inplace=True) # add the swaprz + >>> qc.compose(ansatz, inplace=True) # add the swaprz >>> qc.draw() ┌──────────┐┌────────────┐┌────────────┐┌──────────┐ q_0: ─────■─────┤ RZ(θ[0]) ├┤0 ├┤0 ├┤ RZ(θ[3]) ├ @@ -77,10 +78,21 @@ class SwapRZ(TwoLocal): q_1: ┤ RY(0.2) ├┤ RZ(θ[1]) ├┤1 ├┤1 ├┤ RZ(θ[4]) ├ └─────────┘└──────────┘└────────────┘└────────────┘└──────────┘ + >>> ansatz = ExcitationPreserving(3, reps=1, mode='fsim', entanglement=[[0,2]], + ... insert_barriers=True) + >>> print(ansatz) + ┌──────────┐ ░ ┌────────────┐┌────────────┐ ░ ┌──────────┐ + q_0: ┤ RZ(θ[0]) ├─░─┤0 ├┤0 ├─■──────░─┤ RZ(θ[5]) ├ + ├──────────┤ ░ │ ││ │ │ ░ ├──────────┤ + q_1: ┤ RZ(θ[1]) ├─░─┤ RXX(θ[3]) ├┤ RYY(θ[3]) ├─┼──────░─┤ RZ(θ[6]) ├ + ├──────────┤ ░ │ ││ │ │θ[4] ░ ├──────────┤ + q_2: ┤ RZ(θ[2]) ├─░─┤1 ├┤1 ├─■──────░─┤ RZ(θ[7]) ├ + └──────────┘ ░ └────────────┘└────────────┘ ░ └──────────┘ """ def __init__(self, num_qubits: Optional[int] = None, + mode: str = 'iswap', entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', reps: int = 3, skip_unentangled_qubits: bool = False, @@ -89,10 +101,11 @@ def __init__(self, insert_barriers: bool = False, initial_state: Optional[Any] = None, ) -> None: - """Create a new SwapRZ 2-local circuit. + """Create a new ExcitationPreserving 2-local circuit. Args: - num_qubits: The number of qubits of the SwapRZ circuit. + num_qubits: The number of qubits of the ExcitationPreserving circuit. + mode: aa reps: Specifies how often the structure of a rotation layer followed by an entanglement layer is repeated. entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' @@ -115,16 +128,24 @@ def __init__(self, insert_barriers: If True, barriers are inserted in between each layer. If False, no barriers are inserted. + Raises: + ValueError: If the selected mode is not supported. """ + supported_modes = ['iswap', 'fsim'] + if mode not in supported_modes: + raise ValueError('Unsupported mode {}, choose one of {}'.format(mode, supported_modes)) theta = Parameter('θ') - rxxyy = QuantumCircuit(2, name='Rxx+yy') - rxxyy.rxx(theta, 0, 1) - rxxyy.ryy(theta, 0, 1) + swap = QuantumCircuit(2, name='Interaction') + swap.rxx(theta, 0, 1) + swap.ryy(theta, 0, 1) + if mode == 'fsim': + phi = Parameter('φ') + swap.cu1(phi, 0, 1) super().__init__(num_qubits=num_qubits, rotation_blocks=RZGate, - entanglement_blocks=rxxyy, + entanglement_blocks=swap, entanglement=entanglement, reps=reps, skip_unentangled_qubits=skip_unentangled_qubits, diff --git a/qiskit/circuit/library/n_local/real_amplitudes.py b/qiskit/circuit/library/n_local/real_amplitudes.py new file mode 100644 index 000000000000..7139f44fd189 --- /dev/null +++ b/qiskit/circuit/library/n_local/real_amplitudes.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2020. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""The real-amplitudes 2-local circuit.""" + +from typing import Union, Optional, List, Tuple, Callable, Any +import numpy as np + +from qiskit.circuit.library.standard_gates import RYGate, CXGate +from .two_local import TwoLocal + + +class RealAmplitudes(TwoLocal): + r"""The RealAmplitudes 2-local circuit. + + The ``RealAmplitudes`` circuit is a heuristic trial wave function used as Ansatz in chemistry + applications or classification circuits in machine learning. The circuit consists of + of alternating layers of :math:`Y` rotations and :math:`CX` entanglements. The entanglement + pattern can be user-defined or selected from a predefined set. + + For example a ``RealAmplitudes`` circuit with 2 repetitions on 3 qubits with ``'full'`` + entanglement is + + .. parsed-literal:: + + ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ + ┤ RY(θ[0]) ├─░───■────■────────░─┤ RY(θ[3]) ├─░───■────■────────░─┤ RY(θ[6]) ├ + ├──────────┤ ░ ┌─┴─┐ │ ░ ├──────────┤ ░ ┌─┴─┐ │ ░ ├──────────┤ + ┤ RY(θ[1]) ├─░─┤ X ├──┼────■───░─┤ RY(θ[4]) ├─░─┤ X ├──┼────■───░─┤ RY(θ[7]) ├ + ├──────────┤ ░ └───┘┌─┴─┐┌─┴─┐ ░ ├──────────┤ ░ └───┘┌─┴─┐┌─┴─┐ ░ ├──────────┤ + ┤ RY(θ[2]) ├─░──────┤ X ├┤ X ├─░─┤ RY(θ[5]) ├─░──────┤ X ├┤ X ├─░─┤ RY(θ[8]) ├ + └──────────┘ ░ └───┘└───┘ ░ └──────────┘ ░ └───┘└───┘ ░ └──────────┘ + + The entanglement can be set using the ``entanglement`` keyword as string or a list of + index-pairs. See the documentation of :class:`~qiskit.circuit.library.TwoLocal` and + :class:`~qiskit.circuit.NLocal` for more detail. Additional options that can be set include the + number of repetitions, skipping rotation gates on qubits that are not entangled, leaving out + the final rotation layer and inserting barriers in between the rotation and entanglement + layers. + + If some qubits are not entangled with other qubits it makes sense to not apply rotation gates + on these qubits, since a sequence of :math:`Y` rotations can be reduced to a single :math:`Y` + rotation with summed rotation angles. + + Examples: + + >>> ansatz = RealAmplitudes(3, reps=2) # create the circuit on 3 qubits + >>> print(ansatz) + ┌──────────┐ ┌──────────┐ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├──■────■──┤ RY(θ[3]) ├──────────────■────■──┤ RY(θ[6]) ├──────────── + ├──────────┤┌─┴─┐ │ └──────────┘┌──────────┐┌─┴─┐ │ └──────────┘┌──────────┐ + q_1: ┤ RY(θ[1]) ├┤ X ├──┼───────■──────┤ RY(θ[4]) ├┤ X ├──┼───────■──────┤ RY(θ[7]) ├ + ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─────┤ X ├───┤ X ├────┤ RY(θ[5]) ├─────┤ X ├───┤ X ├────┤ RY(θ[8]) ├ + └──────────┘ └───┘ └───┘ └──────────┘ └───┘ └───┘ └──────────┘ + + >>> ansatz = RealAmplitudes(3, entanglement='linear', reps=2, insert_barriers=True) + >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form + >>> qc.compose(ansatz, inplace=True) + >>> qc.draw() + ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├─░───■────────░─┤ RY(θ[3]) ├─░───■────────░─┤ RY(θ[6]) ├ + ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ + q_1: ┤ RY(θ[1]) ├─░─┤ X ├──■───░─┤ RY(θ[4]) ├─░─┤ X ├──■───░─┤ RY(θ[7]) ├ + ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─░──────┤ X ├─░─┤ RY(θ[5]) ├─░──────┤ X ├─░─┤ RY(θ[8]) ├ + └──────────┘ ░ └───┘ ░ └──────────┘ ░ └───┘ ░ └──────────┘ + + >>> ansatz = RealAmplitudes(4, reps=1, entanglement='circular', insert_barriers=True) + >>> print(ansatz) + ┌──────────┐ ░ ┌───┐ ░ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├─░─┤ X ├──■─────────────░─┤ RY(θ[4]) ├ + ├──────────┤ ░ └─┬─┘┌─┴─┐ ░ ├──────────┤ + q_1: ┤ RY(θ[1]) ├─░───┼──┤ X ├──■────────░─┤ RY(θ[5]) ├ + ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─░───┼───────┤ X ├──■───░─┤ RY(θ[6]) ├ + ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ + q_3: ┤ RY(θ[3]) ├─░───■────────────┤ X ├─░─┤ RY(θ[7]) ├ + └──────────┘ ░ └───┘ ░ └──────────┘ + + >>> ansatz = RealAmplitudes(4, reps=2, entanglement=[[0,3], [0,2]], + ... skip_unentangled_qubits=True) + >>> print(ansatz) + ┌──────────┐ ┌──────────┐ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├──■───────■──────┤ RY(θ[3]) ├──■───────■──────┤ RY(θ[6]) ├ + └──────────┘ │ │ └──────────┘ │ │ └──────────┘ + q_1: ──────────────┼───────┼────────────────────┼───────┼────────────────── + ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ + q_2: ┤ RY(θ[1]) ├──┼─────┤ X ├────┤ RY(θ[4]) ├──┼─────┤ X ├────┤ RY(θ[7]) ├ + ├──────────┤┌─┴─┐┌──┴───┴───┐└──────────┘┌─┴─┐┌──┴───┴───┐└──────────┘ + q_3: ┤ RY(θ[2]) ├┤ X ├┤ RY(θ[5]) ├────────────┤ X ├┤ RY(θ[8]) ├──────────── + └──────────┘└───┘└──────────┘ └───┘└──────────┘ + """ + + def __init__(self, + num_qubits: Optional[int] = None, + entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', + reps: int = 3, + skip_unentangled_qubits: bool = False, + skip_final_rotation_layer: bool = False, + parameter_prefix: str = 'θ', + insert_barriers: bool = False, + initial_state: Optional[Any] = None, + ) -> None: + """Create a new RealAmplitudes 2-local circuit. + + Args: + num_qubits: The number of qubits of the RealAmplitudes circuit. + reps: Specifies how often the structure of a rotation layer followed by an entanglement + layer is repeated. + entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' + or 'sca'), a list of integer-pairs specifying the indices of qubits + entangled with one another, or a callable returning such a list provided with + the index of the entanglement layer. + See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more + detail. + initial_state: An `InitialState` object to prepend to the circuit. + skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits + that are entangled with another qubit. If False, the single qubit gates are applied + to each qubit in the Ansatz. Defaults to False. + skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits + that are entangled with another qubit. If False, the single qubit gates are applied + to each qubit in the Ansatz. Defaults to False. + skip_final_rotation_layer: If False, a rotation layer is added at the end of the + ansatz. If True, no rotation layer is added. + parameter_prefix: The parameterized gates require a parameter to be defined, for which + we use :class:`~qiskit.circuit.ParameterVector`. + insert_barriers: If True, barriers are inserted in between each layer. If False, + no barriers are inserted. + + """ + super().__init__(num_qubits=num_qubits, + reps=reps, + rotation_blocks=RYGate, + entanglement_blocks=CXGate, + entanglement=entanglement, + initial_state=initial_state, + skip_unentangled_qubits=skip_unentangled_qubits, + skip_final_rotation_layer=skip_final_rotation_layer, + parameter_prefix=parameter_prefix, + insert_barriers=insert_barriers) + + @property + def parameter_bounds(self) -> List[Tuple[float, float]]: + """Return the parameter bounds. + + Returns: + The parameter bounds. + """ + return self.num_parameters * [(-np.pi, np.pi)] diff --git a/qiskit/circuit/library/n_local/ry.py b/qiskit/circuit/library/n_local/ry.py deleted file mode 100644 index e26ccc9c9cf9..000000000000 --- a/qiskit/circuit/library/n_local/ry.py +++ /dev/null @@ -1,178 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2020. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""The RY 2-local circuit.""" - -from typing import Union, Optional, List, Tuple, Callable, Any -import numpy as np - -from qiskit.circuit import QuantumCircuit, Instruction -from qiskit.circuit.library.standard_gates import RYGate, CZGate -from .two_local import TwoLocal - - -class RY(TwoLocal): - r"""The RY 2-local circuit. - - The RY trial wave function consistes of alternating layers of :math:`Y` rotations - and entanglements. The entanglements are usually realized using CZ or CX gates. - - For example a RY circuit with 2 repetitions on 3 qubits with full CZ entanglement is - - .. parsed-literal:: - - ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ - ┤ RY(θ[0]) ├─░──■──■─────░─┤ RY(θ[3]) ├─░──■──■─────░─┤ RY(θ[6]) ├ - ├──────────┤ ░ │ │ ░ ├──────────┤ ░ │ │ ░ ├──────────┤ - ┤ RY(θ[1]) ├─░──■──┼──■──░─┤ RY(θ[4]) ├─░──■──┼──■──░─┤ RY(θ[7]) ├ - ├──────────┤ ░ │ │ ░ ├──────────┤ ░ │ │ ░ ├──────────┤ - ┤ RY(θ[2]) ├─░─────■──■──░─┤ RY(θ[5]) ├─░─────■──■──░─┤ RY(θ[8]) ├ - └──────────┘ ░ ░ └──────────┘ ░ ░ └──────────┘ - - - The qubits can be entangled using different structures. This can be set using the - ``entanglement`` keyword as string or a list of index-pairs, see the documentation of - :class:`~qiskit.circuit.library.TwoLocal` and :class:`~qiskit.circuit.NLocal` for more detail. - - Additional options that can be set include skipping rotation gates on qubits that are not - entangled, leaving out the final rotation layer and inserting barriers in between the - rotation and entanglement layers. - - When all qubits are entangled and the entanglement gates themselves have no additional - parameters, the number of parameters of this circuit is :math:`q \times (r + 1)`, - where :math:`q` is the total number of qubits and :math:`r` is the number of repetitions, - set using `reps`. It is sensible to remove the rotation gates on the unentangled qubits since - a sequence of RY gates can be reduced to a single RY with summed rotation angles and more - parameters introduce overhead in optimization routines. - - If the form uses entanglement gates with parameters (such as ``'crx'``) the number of parameters - increases by the number of entanglements. For instance with `'linear'` or `'sca'` entanglement - the total number of parameters is :math:`2q \times (d + 1/2)`. For `'full'` entanglement an - additional :math:`q \times (q - 1)/2 \times d` parameters, hence a total of - :math:`d \times q \times (q + 1) / 2 + q`. - - Examples: - - >>> ry = RY(3, reps=2) # create the variational form on 3 qubits - >>> print(ry) # show the circuit - ┌──────────┐ ┌──────────┐ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├─■──■─┤ RY(θ[3]) ├─────────────■──■─┤ RY(θ[6]) ├──────────── - ├──────────┤ │ │ └──────────┘┌──────────┐ │ │ └──────────┘┌──────────┐ - q_1: ┤ RY(θ[1]) ├─■──┼──────■──────┤ RY(θ[4]) ├─■──┼──────■──────┤ RY(θ[7]) ├ - ├──────────┤ │ │ ├──────────┤ │ │ ├──────────┤ - q_2: ┤ RY(θ[2]) ├────■──────■──────┤ RY(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├ - └──────────┘ └──────────┘ └──────────┘ - - >>> ry = RY(3, entanglement='linear', reps=2, insert_barriers=True) - >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form - >>> qc += ry.to_circuit() - >>> qc.decompose().draw() - ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├─░──■─────░─┤ RY(θ[3]) ├─░──■─────░─┤ RY(θ[6]) ├ - ├──────────┤ ░ │ ░ ├──────────┤ ░ │ ░ ├──────────┤ - q_1: ┤ RY(θ[1]) ├─░──■──■──░─┤ RY(θ[4]) ├─░──■──■──░─┤ RY(θ[7]) ├ - ├──────────┤ ░ │ ░ ├──────────┤ ░ │ ░ ├──────────┤ - q_2: ┤ RY(θ[2]) ├─░─────■──░─┤ RY(θ[5]) ├─░─────■──░─┤ RY(θ[8]) ├ - └──────────┘ ░ ░ └──────────┘ ░ ░ └──────────┘ - - >>> ry = RY(4, 'crx', entanglement='circular', reps=2, insert_barriers=True) - >>> print(ry) - ┌──────────┐ ░ ┌──────────┐ ░ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├─░─┤ Rx(θ[4]) ├─────■───────────────────────────────░──┤ RY(θ[8]) ├ - ├──────────┤ ░ └────┬─────┘┌────┴─────┐ ░ ├──────────┤ - q_1: ┤ RY(θ[1]) ├─░──────┼──────┤ Rx(θ[5]) ├─────■───────────────────░──┤ RY(θ[9]) ├ - ├──────────┤ ░ │ └──────────┘┌────┴─────┐ ░ ┌┴──────────┤ - q_2: ┤ RY(θ[2]) ├─░──────┼──────────────────┤ Rx(θ[6]) ├─────■───────░─┤ RY(θ[10]) ├ - ├──────────┤ ░ │ └──────────┘┌────┴─────┐ ░ ├───────────┤ - q_3: ┤ RY(θ[3]) ├─░──────■──────────────────────────────┤ Rx(θ[7]) ├─░─┤ RY(θ[11]) ├ - └──────────┘ ░ └──────────┘ ░ └───────────┘ - - >>> entanglement = [[0, 1], [0, 2]] - >>> ry = RY(3, 'cx', entanglement, reps=2) - >>> print(ry) - ┌──────────┐ ┌──────────┐ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├──■────────────────■──┤ RY(θ[3]) ├──■────────────────■──┤ RY(θ[6]) ├ - ├──────────┤┌─┴─┐┌──────────┐ │ └──────────┘┌─┴─┐┌──────────┐ │ └──────────┘ - q_1: ┤ RY(θ[1]) ├┤ X ├┤ RY(θ[4]) ├──┼──────────────┤ X ├┤ RY(θ[7]) ├──┼────────────── - ├──────────┤└───┘└──────────┘┌─┴─┐┌──────────┐└───┘└──────────┘┌─┴─┐┌──────────┐ - q_2: ┤ RY(θ[2]) ├─────────────────┤ X ├┤ RY(θ[5]) ├─────────────────┤ X ├┤ RY(θ[8]) ├ - └──────────┘ └───┘└──────────┘ └───┘└──────────┘ - """ - - def __init__(self, - num_qubits: Optional[int] = None, - entanglement_blocks: Union[ - str, type, Instruction, QuantumCircuit, - List[Union[str, type, Instruction, QuantumCircuit]] - ] = CZGate, - entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', - reps: int = 3, - skip_unentangled_qubits: bool = False, - skip_final_rotation_layer: bool = False, - parameter_prefix: str = 'θ', - insert_barriers: bool = False, - initial_state: Optional[Any] = None, - ) -> None: - """Create a new RY 2-local circuit. - - Args: - num_qubits: The number of qubits of the RY circuit. - reps: Specifies how often the structure of a rotation layer followed by an entanglement - layer is repeated. - entanglement_blocks: The gates used in the entanglement layer. Can be specified via the - name of a gate (e.g. ``'cx'``), the gate type itself (e.g. ``CXGate``) or a - ``QuantumCircuit`` with two qubits. - If only one gate is provided, the gate same gate is applied to each qubit. - If a list of gates is provided, all gates are applied to each qubit in the provided - order. - entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' - or 'sca'), a list of integer-pairs specifying the indices of qubits - entangled with one another, or a callable returning such a list provided with - the index of the entanglement layer. - See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more - detail. - initial_state: An `InitialState` object to prepend to the circuit. - skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits - that are entangled with another qubit. If False, the single qubit gates are applied - to each qubit in the Ansatz. Defaults to False. - skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits - that are entangled with another qubit. If False, the single qubit gates are applied - to each qubit in the Ansatz. Defaults to False. - skip_final_rotation_layer: If False, a rotation layer is added at the end of the - ansatz. If True, no rotation layer is added. - parameter_prefix: The parameterized gates require a parameter to be defined, for which - we use :class:`~qiskit.circuit.ParameterVector`. - insert_barriers: If True, barriers are inserted in between each layer. If False, - no barriers are inserted. - - """ - super().__init__(num_qubits=num_qubits, - reps=reps, - rotation_blocks=RYGate, - entanglement_blocks=entanglement_blocks, - entanglement=entanglement, - initial_state=initial_state, - skip_unentangled_qubits=skip_unentangled_qubits, - skip_final_rotation_layer=skip_final_rotation_layer, - parameter_prefix=parameter_prefix, - insert_barriers=insert_barriers) - - @property - def parameter_bounds(self) -> List[Tuple[float, float]]: - """Return the parameter bounds. - - Returns: - The parameter bounds. - """ - return self.num_parameters * [(-np.pi, np.pi)] diff --git a/qiskit/circuit/library/n_local/ryrz.py b/qiskit/circuit/library/n_local/ryrz.py deleted file mode 100644 index a2c4da7dfb49..000000000000 --- a/qiskit/circuit/library/n_local/ryrz.py +++ /dev/null @@ -1,133 +0,0 @@ -# -*- coding: utf-8 -*- - -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2020. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""The RYRZ 2-local circuit.""" - -from typing import Union, Optional, List, Tuple, Callable, Any -from numpy import pi - -from qiskit.circuit import QuantumCircuit, Instruction -from qiskit.circuit.library.standard_gates import RYGate, RZGate, CZGate -from .two_local import TwoLocal - - -class RYRZ(TwoLocal): - r"""The RYRZ 2-local circuit. - - The RYRZ circuit consists of layers of :math:`Y` plus :math:`Z` rotations with entanglements. - It can be used to prepare trial wave functions for variational quantum algorithms. - - .. parsed-literal:: - - ┌──────────┐┌──────────┐ ░ ░ ░ ┌───────────┐┌───────────┐ - ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├─░──■─────░─ ... ─░─┤ RY(θ[12]) ├┤ RZ(θ[15]) ├ - ├──────────┤├──────────┤ ░ │ ░ ░ ├───────────┤├───────────┤ - ┤ RY(θ[1]) ├┤ RZ(θ[4]) ├─░──■──■──░─ ... ─░─┤ RY(θ[13]) ├┤ RZ(θ[16]) ├ - ├──────────┤├──────────┤ ░ │ ░ ░ ├───────────┤├───────────┤ - ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├─░─────■──░─ ... ─░─┤ RY(θ[14]) ├┤ RZ(θ[17]) ├ - └──────────┘└──────────┘ ░ ░ ░ └───────────┘└───────────┘ - - See :class:`~qiskit.circuit.library.RY` for more detail on the possible arguments and options - such as skipping unentanglement qubits, which apply here too. - - Examples: - - >>> ryrz = RYRZ(3, reps=1) # create the variational form on 3 qubits - >>> print(ryrz) # show the circuit - ┌──────────┐┌──────────┐ ┌──────────┐┌──────────┐ - q_0: ┤ RY(θ[0]) ├┤ RZ(θ[3]) ├─■──■─┤ RY(θ[6]) ├┤ RZ(θ[9]) ├───────────── - ├──────────┤├──────────┤ │ │ └──────────┘├──────────┤┌───────────┐ - q_1: ┤ RY(θ[1]) ├┤ RZ(θ[4]) ├─■──┼──────■──────┤ RY(θ[7]) ├┤ RZ(θ[10]) ├ - ├──────────┤├──────────┤ │ │ ├──────────┤├───────────┤ - q_2: ┤ RY(θ[2]) ├┤ RZ(θ[5]) ├────■──────■──────┤ RY(θ[8]) ├┤ RZ(θ[11]) ├ - └──────────┘└──────────┘ └──────────┘└───────────┘ - - >>> ryrz = RYRZ(4, entanglement='circular', reps=1) - >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form - >>> qc += ryrz.to_circuit() - >>> qc.decompose().draw() - ┌──────────┐┌──────────┐ ┌──────────┐┌───────────┐ - q_0: ┤ RY(θ[0]) ├┤ RZ(θ[4]) ├─■──■─┤ RY(θ[8]) ├┤ RZ(θ[12]) ├────────────────────────── - ├──────────┤├──────────┤ │ │ └──────────┘└┬──────────┤┌───────────┐ - q_1: ┤ RY(θ[1]) ├┤ RZ(θ[5]) ├─┼──■──────■───────┤ RY(θ[9]) ├┤ RZ(θ[13]) ├───────────── - ├──────────┤├──────────┤ │ │ └──────────┘├───────────┤┌───────────┐ - q_2: ┤ RY(θ[2]) ├┤ RZ(θ[6]) ├─┼─────────■────────────■──────┤ RY(θ[10]) ├┤ RZ(θ[14]) ├ - ├──────────┤├──────────┤ │ │ ├───────────┤├───────────┤ - q_3: ┤ RY(θ[3]) ├┤ RZ(θ[7]) ├─■──────────────────────■──────┤ RY(θ[11]) ├┤ RZ(θ[15]) ├ - └──────────┘└──────────┘ └───────────┘└───────────┘ - """ - - def __init__(self, - num_qubits: Optional[int] = None, - entanglement_blocks: Union[ - str, type, Instruction, QuantumCircuit, - List[Union[str, type, Instruction, QuantumCircuit]] - ] = CZGate, - entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', - reps: int = 3, - skip_unentangled_qubits: bool = False, - skip_final_rotation_layer: bool = False, - parameter_prefix: str = 'θ', - insert_barriers: bool = False, - initial_state: Optional[Any] = None, - ) -> None: - """Create a new RYRZ 2-local circuit. - - Args: - num_qubits: The number of qubits of the RYRZ circuit. - reps: Specifies how often the structure of a rotation layer followed by an entanglement - layer is repeated. - entanglement_blocks: The gates used in the entanglement layer. Can be specified via the - name of a gate (e.g. ``'cx'``), the gate type itself (e.g. ``CXGate``) or a - ``QuantumCircuit`` with two qubits. - If only one gate is provided, the same gate is applied to each qubit. - If a list of gates is provided, all gates are applied to each qubit in the provided - order. - entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' - , 'circular' or 'sca'), a list of integer-pairs specifying the indices of qubits - entangled with one another, or a callable returning such a list provided with - the index of the entanglement layer. - See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more - detail. - initial_state: An `InitialState` object to prepend to the circuit. - skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits - that are entangled with another qubit. If False, the single qubit gates are applied - to each qubit in the Ansatz. Defaults to False. - skip_final_rotation_layer: If False, a rotation layer is added at the end of the - ansatz. If True, no rotation layer is added. - parameter_prefix: The parameterized gates require a parameter to be defined, for which - we use :class:`~qiskit.circuit.ParameterVector`. - insert_barriers: If True, barriers are inserted in between each layer. If False, - no barriers are inserted. - - """ - super().__init__(num_qubits=num_qubits, - rotation_blocks=[RYGate, RZGate], - entanglement_blocks=entanglement_blocks, - entanglement=entanglement, - reps=reps, - skip_unentangled_qubits=skip_unentangled_qubits, - skip_final_rotation_layer=skip_final_rotation_layer, - parameter_prefix=parameter_prefix, - insert_barriers=insert_barriers, - initial_state=initial_state) - - @property - def parameter_bounds(self) -> List[Tuple[float, float]]: - """Return the parameter bounds. - - Returns: - The parameter bounds. - """ - return self.num_parameters * [(-pi, pi)] diff --git a/test/python/circuit/test_library.py b/test/python/circuit/test_library.py index 1f096b74c3bc..453b4a78b0ca 100644 --- a/test/python/circuit/test_library.py +++ b/test/python/circuit/test_library.py @@ -28,8 +28,8 @@ InnerProduct, OR, AND, QFT, LinearPauliRotations, PolynomialPauliRotations, IntegerComparator, PiecewiseLinearPauliRotations, - WeightedAdder, Diagonal, NLocal, TwoLocal, RY, RYRZ, - SwapRZ, PauliExpansion, FirstOrderExpansion, + WeightedAdder, Diagonal, NLocal, TwoLocal, RealAmplitudes, EfficientSU2, + ExcitationPreserving, PauliExpansion, FirstOrderExpansion, SecondOrderExpansion, MCMT, MCMTVChain) from qiskit.circuit.random.utils import random_circuit from qiskit.converters.circuit_to_dag import circuit_to_dag @@ -1415,8 +1415,8 @@ def test_adding_two(self): self.assertCircuitEqual(reference, circuit) def test_ry_blocks(self): - """Test that the RY circuit is instantiated correctly.""" - two = RY(4) + """Test that the RealAmplitudes circuit is instantiated correctly.""" + two = RealAmplitudes(4) with self.subTest(msg='test rotation gate'): self.assertEqual(len(two.rotation_blocks), 1) self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate) @@ -1426,11 +1426,10 @@ def test_ry_blocks(self): np.testing.assert_almost_equal(two.parameter_bounds, expected) def test_ry_circuit(self): - """Test an RY circuit.""" + """Test an RealAmplitudes circuit.""" num_qubits = 3 reps = 2 entanglement = 'full' - entanglement_gate = 'cx' parameters = ParameterVector('theta', num_qubits * (reps + 1)) param_iter = iter(parameters) @@ -1444,14 +1443,14 @@ def test_ry_circuit(self): for i in range(num_qubits): expected.ry(next(param_iter), i) - library = RY(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, - entanglement=entanglement).assign_parameters(parameters) + library = RealAmplitudes(num_qubits, reps=reps, + entanglement=entanglement).assign_parameters(parameters) self.assertCircuitEqual(library, expected) def test_ryrz_blocks(self): - """Test that the RYRZ circuit is instantiated correctly.""" - two = RYRZ(3) + """Test that the EfficientSU2 circuit is instantiated correctly.""" + two = EfficientSU2(3) with self.subTest(msg='test rotation gate'): self.assertEqual(len(two.rotation_blocks), 2) self.assertIsInstance(two.rotation_blocks[0].data[0][0], RYGate) @@ -1462,11 +1461,10 @@ def test_ryrz_blocks(self): np.testing.assert_almost_equal(two.parameter_bounds, expected) def test_ryrz_circuit(self): - """Test an RYRZ circuit.""" + """Test an EfficientSU2 circuit.""" num_qubits = 3 reps = 2 entanglement = 'circular' - entanglement_gate = 'cz' parameters = ParameterVector('theta', 2 * num_qubits * (reps + 1)) param_iter = iter(parameters) @@ -1476,22 +1474,23 @@ def test_ryrz_circuit(self): expected.ry(next(param_iter), i) for i in range(num_qubits): expected.rz(next(param_iter), i) - expected.cz(2, 0) - expected.cz(0, 1) - expected.cz(1, 2) + expected.cx(2, 0) + expected.cx(0, 1) + expected.cx(1, 2) for i in range(num_qubits): expected.ry(next(param_iter), i) for i in range(num_qubits): expected.rz(next(param_iter), i) - library = RYRZ(num_qubits, reps=reps, entanglement_blocks=entanglement_gate, - entanglement=entanglement).assign_parameters(parameters) + library = EfficientSU2(num_qubits, reps=reps, entanglement=entanglement).assign_parameters( + parameters + ) self.assertCircuitEqual(library, expected) def test_swaprz_blocks(self): - """Test that the SwapRZ circuit is instantiated correctly.""" - two = SwapRZ(5) + """Test that the ExcitationPreserving circuit is instantiated correctly.""" + two = ExcitationPreserving(5) with self.subTest(msg='test rotation gate'): self.assertEqual(len(two.rotation_blocks), 1) self.assertIsInstance(two.rotation_blocks[0].data[0][0], RZGate) @@ -1508,7 +1507,7 @@ def test_swaprz_blocks(self): np.testing.assert_almost_equal(two.parameter_bounds, expected) def test_swaprz_circuit(self): - """Test a SwapRZ circuit.""" + """Test a ExcitationPreserving circuit in iswap mode.""" num_qubits = 3 reps = 2 entanglement = 'linear' @@ -1528,8 +1527,36 @@ def test_swaprz_circuit(self): for i in range(num_qubits): expected.rz(next(param_iter), i) - library = SwapRZ(num_qubits, reps=reps, - entanglement=entanglement).assign_parameters(parameters) + library = ExcitationPreserving(num_qubits, reps=reps, + entanglement=entanglement).assign_parameters(parameters) + + self.assertCircuitEqual(library, expected) + + def test_fsim_circuit(self): + """Test a ExcitationPreserving circuit in fsim mode.""" + num_qubits = 3 + reps = 2 + entanglement = 'linear' + parameters = ParameterVector('theta', num_qubits * (reps + 1) + reps * (1 + num_qubits)) + param_iter = iter(parameters) + + expected = QuantumCircuit(3) + for _ in range(reps): + for i in range(num_qubits): + expected.rz(next(param_iter), i) + shared_param = next(param_iter) + expected.rxx(shared_param, 0, 1) + expected.ryy(shared_param, 0, 1) + expected.cu1(next(param_iter), 0, 1) + shared_param = next(param_iter) + expected.rxx(shared_param, 1, 2) + expected.ryy(shared_param, 1, 2) + expected.cu1(next(param_iter), 1, 2) + for i in range(num_qubits): + expected.rz(next(param_iter), i) + + library = ExcitationPreserving(num_qubits, reps=reps, mode='fsim', + entanglement=entanglement).assign_parameters(parameters) self.assertCircuitEqual(library, expected) From 7638aa8f29aa897613e97d1e2678f19ab33aee30 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Apr 2020 20:17:10 +0200 Subject: [PATCH 6/8] fix test --- test/python/circuit/test_library.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/python/circuit/test_library.py b/test/python/circuit/test_library.py index f7a721678eef..0ccf230ec653 100644 --- a/test/python/circuit/test_library.py +++ b/test/python/circuit/test_library.py @@ -971,8 +971,8 @@ def assertCircuitEqual(self, qc1, qc2, visual=False, transpiled=True): """An equality test specialized to circuits.""" if transpiled: basis_gates = ['id', 'u1', 'u3', 'cx'] - qc1_transpiled = transpile(qc1, basis_gates=basis_gates) - qc2_transpiled = transpile(qc2, basis_gates=basis_gates) + qc1_transpiled = transpile(qc1, basis_gates=basis_gates, optimization_level=0) + qc2_transpiled = transpile(qc2, basis_gates=basis_gates, optimization_level=0) qc1, qc2 = qc1_transpiled, qc2_transpiled if visual: @@ -1278,8 +1278,8 @@ def assertCircuitEqual(self, qc1, qc2, visual=False, transpiled=True): """An equality test specialized to circuits.""" if transpiled: basis_gates = ['id', 'u1', 'u3', 'cx'] - qc1_transpiled = transpile(qc1, basis_gates=basis_gates) - qc2_transpiled = transpile(qc2, basis_gates=basis_gates) + qc1_transpiled = transpile(qc1, basis_gates=basis_gates, optimization_level=0) + qc2_transpiled = transpile(qc2, basis_gates=basis_gates, optimization_level=0) qc1, qc2 = qc1_transpiled, qc2_transpiled if visual: @@ -1537,7 +1537,9 @@ def test_fsim_circuit(self): num_qubits = 3 reps = 2 entanglement = 'linear' - parameters = ParameterVector('theta', num_qubits * (reps + 1) + reps * (1 + num_qubits)) + # need the parameters in the entanglement blocks to be the same because the order + # can get mixed up in ExcitationPreserving (since parameters are not ordered in circuits) + parameters = [1] * (num_qubits * (reps + 1) + reps * (1 + num_qubits)) param_iter = iter(parameters) expected = QuantumCircuit(3) From d50444a02451d845727788bd7fc03af1197b564b Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Apr 2020 22:28:59 +0200 Subject: [PATCH 7/8] try to fix sphinx --- qiskit/circuit/library/n_local/efficient_su2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/circuit/library/n_local/efficient_su2.py b/qiskit/circuit/library/n_local/efficient_su2.py index f63b7183c562..d09852a7d13c 100644 --- a/qiskit/circuit/library/n_local/efficient_su2.py +++ b/qiskit/circuit/library/n_local/efficient_su2.py @@ -64,7 +64,6 @@ class EfficientSU2(TwoLocal): >>> qc = QuantumCircuit(4) # create a circuit and append the RY variational form >>> qc.compose(ansatz, inplace=True) >>> qc.draw() - ┌──────────┐┌───┐┌───┐ ┌──────────┐ ┌───┐ q_0: ┤ RX(θ[0]) ├┤ Y ├┤ X ├──■──┤ RX(θ[4]) ├───┤ Y ├───────────────────── ├──────────┤├───┤└─┬─┘┌─┴─┐└──────────┘┌──┴───┴───┐ ┌───┐ @@ -74,6 +73,7 @@ class EfficientSU2(TwoLocal): ├──────────┤├───┤ │ └───┘ ┌─┴─┐ ├──────────┤├───┤ q_3: ┤ RX(θ[3]) ├┤ Y ├──■──────────────────────┤ X ├────┤ RX(θ[7]) ├┤ Y ├ └──────────┘└───┘ └───┘ └──────────┘└───┘ + """ def __init__(self, From 07b26ec161b70ec7d660c6dad9d81fec6d290ed2 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 30 Apr 2020 07:39:11 +0200 Subject: [PATCH 8/8] fix spacing?? --- .../library/n_local/real_amplitudes.py | 139 +++++++++--------- 1 file changed, 70 insertions(+), 69 deletions(-) diff --git a/qiskit/circuit/library/n_local/real_amplitudes.py b/qiskit/circuit/library/n_local/real_amplitudes.py index 7139f44fd189..c47405c6749f 100644 --- a/qiskit/circuit/library/n_local/real_amplitudes.py +++ b/qiskit/circuit/library/n_local/real_amplitudes.py @@ -55,52 +55,53 @@ class RealAmplitudes(TwoLocal): Examples: - >>> ansatz = RealAmplitudes(3, reps=2) # create the circuit on 3 qubits - >>> print(ansatz) - ┌──────────┐ ┌──────────┐ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├──■────■──┤ RY(θ[3]) ├──────────────■────■──┤ RY(θ[6]) ├──────────── - ├──────────┤┌─┴─┐ │ └──────────┘┌──────────┐┌─┴─┐ │ └──────────┘┌──────────┐ - q_1: ┤ RY(θ[1]) ├┤ X ├──┼───────■──────┤ RY(θ[4]) ├┤ X ├──┼───────■──────┤ RY(θ[7]) ├ - ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤ - q_2: ┤ RY(θ[2]) ├─────┤ X ├───┤ X ├────┤ RY(θ[5]) ├─────┤ X ├───┤ X ├────┤ RY(θ[8]) ├ - └──────────┘ └───┘ └───┘ └──────────┘ └───┘ └───┘ └──────────┘ - - >>> ansatz = RealAmplitudes(3, entanglement='linear', reps=2, insert_barriers=True) - >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form - >>> qc.compose(ansatz, inplace=True) - >>> qc.draw() - ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├─░───■────────░─┤ RY(θ[3]) ├─░───■────────░─┤ RY(θ[6]) ├ - ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ - q_1: ┤ RY(θ[1]) ├─░─┤ X ├──■───░─┤ RY(θ[4]) ├─░─┤ X ├──■───░─┤ RY(θ[7]) ├ - ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ - q_2: ┤ RY(θ[2]) ├─░──────┤ X ├─░─┤ RY(θ[5]) ├─░──────┤ X ├─░─┤ RY(θ[8]) ├ - └──────────┘ ░ └───┘ ░ └──────────┘ ░ └───┘ ░ └──────────┘ - - >>> ansatz = RealAmplitudes(4, reps=1, entanglement='circular', insert_barriers=True) - >>> print(ansatz) - ┌──────────┐ ░ ┌───┐ ░ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├─░─┤ X ├──■─────────────░─┤ RY(θ[4]) ├ - ├──────────┤ ░ └─┬─┘┌─┴─┐ ░ ├──────────┤ - q_1: ┤ RY(θ[1]) ├─░───┼──┤ X ├──■────────░─┤ RY(θ[5]) ├ - ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ - q_2: ┤ RY(θ[2]) ├─░───┼───────┤ X ├──■───░─┤ RY(θ[6]) ├ - ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ - q_3: ┤ RY(θ[3]) ├─░───■────────────┤ X ├─░─┤ RY(θ[7]) ├ - └──────────┘ ░ └───┘ ░ └──────────┘ - - >>> ansatz = RealAmplitudes(4, reps=2, entanglement=[[0,3], [0,2]], - ... skip_unentangled_qubits=True) - >>> print(ansatz) - ┌──────────┐ ┌──────────┐ ┌──────────┐ - q_0: ┤ RY(θ[0]) ├──■───────■──────┤ RY(θ[3]) ├──■───────■──────┤ RY(θ[6]) ├ - └──────────┘ │ │ └──────────┘ │ │ └──────────┘ - q_1: ──────────────┼───────┼────────────────────┼───────┼────────────────── - ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ - q_2: ┤ RY(θ[1]) ├──┼─────┤ X ├────┤ RY(θ[4]) ├──┼─────┤ X ├────┤ RY(θ[7]) ├ - ├──────────┤┌─┴─┐┌──┴───┴───┐└──────────┘┌─┴─┐┌──┴───┴───┐└──────────┘ - q_3: ┤ RY(θ[2]) ├┤ X ├┤ RY(θ[5]) ├────────────┤ X ├┤ RY(θ[8]) ├──────────── - └──────────┘└───┘└──────────┘ └───┘└──────────┘ + >>> ansatz = RealAmplitudes(3, reps=2) # create the circuit on 3 qubits + >>> print(ansatz) + ┌──────────┐ ┌──────────┐ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├──■────■──┤ RY(θ[3]) ├──────────────■────■──┤ RY(θ[6]) ├──────────── + ├──────────┤┌─┴─┐ │ └──────────┘┌──────────┐┌─┴─┐ │ └──────────┘┌──────────┐ + q_1: ┤ RY(θ[1]) ├┤ X ├──┼───────■──────┤ RY(θ[4]) ├┤ X ├──┼───────■──────┤ RY(θ[7]) ├ + ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤└───┘┌─┴─┐ ┌─┴─┐ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─────┤ X ├───┤ X ├────┤ RY(θ[5]) ├─────┤ X ├───┤ X ├────┤ RY(θ[8]) ├ + └──────────┘ └───┘ └───┘ └──────────┘ └───┘ └───┘ └──────────┘ + + >>> ansatz = RealAmplitudes(3, entanglement='linear', reps=2, insert_barriers=True) + >>> qc = QuantumCircuit(3) # create a circuit and append the RY variational form + >>> qc.compose(ansatz, inplace=True) + >>> qc.draw() + ┌──────────┐ ░ ░ ┌──────────┐ ░ ░ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├─░───■────────░─┤ RY(θ[3]) ├─░───■────────░─┤ RY(θ[6]) ├ + ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ ░ ┌─┴─┐ ░ ├──────────┤ + q_1: ┤ RY(θ[1]) ├─░─┤ X ├──■───░─┤ RY(θ[4]) ├─░─┤ X ├──■───░─┤ RY(θ[7]) ├ + ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ ░ └───┘┌─┴─┐ ░ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─░──────┤ X ├─░─┤ RY(θ[5]) ├─░──────┤ X ├─░─┤ RY(θ[8]) ├ + └──────────┘ ░ └───┘ ░ └──────────┘ ░ └───┘ ░ └──────────┘ + + >>> ansatz = RealAmplitudes(4, reps=1, entanglement='circular', insert_barriers=True) + >>> print(ansatz) + ┌──────────┐ ░ ┌───┐ ░ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├─░─┤ X ├──■─────────────░─┤ RY(θ[4]) ├ + ├──────────┤ ░ └─┬─┘┌─┴─┐ ░ ├──────────┤ + q_1: ┤ RY(θ[1]) ├─░───┼──┤ X ├──■────────░─┤ RY(θ[5]) ├ + ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ + q_2: ┤ RY(θ[2]) ├─░───┼───────┤ X ├──■───░─┤ RY(θ[6]) ├ + ├──────────┤ ░ │ └───┘┌─┴─┐ ░ ├──────────┤ + q_3: ┤ RY(θ[3]) ├─░───■────────────┤ X ├─░─┤ RY(θ[7]) ├ + └──────────┘ ░ └───┘ ░ └──────────┘ + + >>> ansatz = RealAmplitudes(4, reps=2, entanglement=[[0,3], [0,2]], + ... skip_unentangled_qubits=True) + >>> print(ansatz) + ┌──────────┐ ┌──────────┐ ┌──────────┐ + q_0: ┤ RY(θ[0]) ├──■───────■──────┤ RY(θ[3]) ├──■───────■──────┤ RY(θ[6]) ├ + └──────────┘ │ │ └──────────┘ │ │ └──────────┘ + q_1: ──────────────┼───────┼────────────────────┼───────┼────────────────── + ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ │ ┌─┴─┐ ┌──────────┐ + q_2: ┤ RY(θ[1]) ├──┼─────┤ X ├────┤ RY(θ[4]) ├──┼─────┤ X ├────┤ RY(θ[7]) ├ + ├──────────┤┌─┴─┐┌──┴───┴───┐└──────────┘┌─┴─┐┌──┴───┴───┐└──────────┘ + q_3: ┤ RY(θ[2]) ├┤ X ├┤ RY(θ[5]) ├────────────┤ X ├┤ RY(θ[8]) ├──────────── + └──────────┘└───┘└──────────┘ └───┘└──────────┘ + """ def __init__(self, @@ -116,28 +117,28 @@ def __init__(self, """Create a new RealAmplitudes 2-local circuit. Args: - num_qubits: The number of qubits of the RealAmplitudes circuit. - reps: Specifies how often the structure of a rotation layer followed by an entanglement - layer is repeated. - entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' - or 'sca'), a list of integer-pairs specifying the indices of qubits - entangled with one another, or a callable returning such a list provided with - the index of the entanglement layer. - See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more - detail. - initial_state: An `InitialState` object to prepend to the circuit. - skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits - that are entangled with another qubit. If False, the single qubit gates are applied - to each qubit in the Ansatz. Defaults to False. - skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits - that are entangled with another qubit. If False, the single qubit gates are applied - to each qubit in the Ansatz. Defaults to False. - skip_final_rotation_layer: If False, a rotation layer is added at the end of the - ansatz. If True, no rotation layer is added. - parameter_prefix: The parameterized gates require a parameter to be defined, for which - we use :class:`~qiskit.circuit.ParameterVector`. - insert_barriers: If True, barriers are inserted in between each layer. If False, - no barriers are inserted. + num_qubits: The number of qubits of the RealAmplitudes circuit. + reps: Specifies how often the structure of a rotation layer followed by an entanglement + layer is repeated. + entanglement: Specifies the entanglement structure. Can be a string ('full', 'linear' + or 'sca'), a list of integer-pairs specifying the indices of qubits + entangled with one another, or a callable returning such a list provided with + the index of the entanglement layer. + See the Examples section of :class:`~qiskit.circuit.library.TwoLocal` for more + detail. + initial_state: An `InitialState` object to prepend to the circuit. + skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits + that are entangled with another qubit. If False, the single qubit gates are applied + to each qubit in the Ansatz. Defaults to False. + skip_unentangled_qubits: If True, the single qubit gates are only applied to qubits + that are entangled with another qubit. If False, the single qubit gates are applied + to each qubit in the Ansatz. Defaults to False. + skip_final_rotation_layer: If False, a rotation layer is added at the end of the + ansatz. If True, no rotation layer is added. + parameter_prefix: The parameterized gates require a parameter to be defined, for which + we use :class:`~qiskit.circuit.ParameterVector`. + insert_barriers: If True, barriers are inserted in between each layer. If False, + no barriers are inserted. """ super().__init__(num_qubits=num_qubits, @@ -156,6 +157,6 @@ def parameter_bounds(self) -> List[Tuple[float, float]]: """Return the parameter bounds. Returns: - The parameter bounds. + The parameter bounds. """ return self.num_parameters * [(-np.pi, np.pi)]