示例#1
0
    def test_different_input_types(self, op):
        """Test all different supported input types and that they yield the same."""
        expected = QuantumCircuit(2)
        expected.rx(4, 1)

        with self.subTest(msg="plain"):
            evo = PauliEvolutionGate(op, time=2, synthesis=LieTrotter())
            self.assertEqual(evo.definition, expected)

        with self.subTest(msg="wrapped in list"):
            evo = PauliEvolutionGate([op], time=2, synthesis=LieTrotter())
            self.assertEqual(evo.definition, expected)
示例#2
0
    def test_cnot_chain_options(self, option):
        """Test selecting different kinds of CNOT chains."""

        op = Z ^ Z ^ Z
        synthesis = LieTrotter(reps=1, cx_structure=option)
        evo = PauliEvolutionGate(op, synthesis=synthesis)

        expected = QuantumCircuit(3)
        if option == "chain":
            expected.cx(2, 1)
            expected.cx(1, 0)
        else:
            expected.cx(1, 0)
            expected.cx(2, 0)

        expected.rz(2, 0)

        if option == "chain":
            expected.cx(1, 0)
            expected.cx(2, 1)
        else:
            expected.cx(2, 0)
            expected.cx(1, 0)

        self.assertEqual(expected, evo.definition)
示例#3
0
 def test_lie_trotter(self):
     """Test constructing the circuit with Lie Trotter decomposition."""
     op = (X ^ 3) + (Y ^ 3) + (Z ^ 3)
     time = 0.123
     reps = 4
     evo_gate = PauliEvolutionGate(op, time, synthesis=LieTrotter(reps=reps))
     decomposed = evo_gate.definition.decompose()
     self.assertEqual(decomposed.count_ops()["cx"], reps * 3 * 4)
示例#4
0
 def test_passing_grouped_paulis(self):
     """Test passing a list of already grouped Paulis."""
     grouped_ops = [(X ^ Y) + (Y ^ X), (Z ^ I) + (Z ^ Z) + (I ^ Z), (X ^ X)]
     evo_gate = PauliEvolutionGate(grouped_ops, time=0.12, synthesis=LieTrotter())
     decomposed = evo_gate.definition.decompose()
     self.assertEqual(decomposed.count_ops()["rz"], 4)
     self.assertEqual(decomposed.count_ops()["rzz"], 1)
     self.assertEqual(decomposed.count_ops()["rxx"], 1)
示例#5
0
 def test_paulisumop_coefficients_respected(self):
     """Test that global ``PauliSumOp`` coefficients are being taken care of."""
     evo = PauliEvolutionGate(5 * (2 * X + 3 * Y - Z), time=1, synthesis=LieTrotter())
     circuit = evo.definition.decompose()
     rz_angles = [
         circuit.data[0][0].params[0],  # X
         circuit.data[1][0].params[0],  # Y
         circuit.data[2][0].params[0],  # Z
     ]
     self.assertListEqual(rz_angles, [20, 30, -10])
示例#6
0
    def test_lie_trotter_two_qubit_correct_order(self):
        """Test that evolutions on two qubit operators are in the right order.

        Regression test of Qiskit/qiskit-terra#7544.
        """
        operator = I ^ Z ^ Z
        time = 0.5
        exact = scipy.linalg.expm(-1j * time * operator.to_matrix())
        lie_trotter = PauliEvolutionGate(operator,
                                         time,
                                         synthesis=LieTrotter())

        self.assertTrue(Operator(lie_trotter).equiv(exact))
示例#7
0
    def __init__(
        self,
        ansatz: QuantumCircuit,
        initial_parameters: np.ndarray,
        expectation: ExpectationBase,
        optimizer: Optional[Union[Optimizer, Minimizer]] = None,
        num_timesteps: Optional[int] = None,
        evolution: Optional[EvolutionSynthesis] = None,
        use_parameter_shift: bool = True,
        initial_guess: Optional[np.ndarray] = None,
        quantum_instance: Optional[Union[Backend, QuantumInstance]] = None,
    ) -> None:
        """
        Args:
            ansatz: A parameterized circuit preparing the variational ansatz to model the
                time evolved quantum state.
            initial_parameters: The initial parameters for the ansatz. Together with the ansatz,
                these define the initial state of the time evolution.
            expectation: The expectation converter to evaluate expectation values.
            optimizer: The classical optimizers used to minimize the overlap between
                Trotterization and ansatz. Can be either a :class:`.Optimizer` or a callable
                using the :class:`.Minimizer` protocol. This argument is optional since it is
                not required for :meth:`get_loss`, but it has to be set before :meth:`evolve`
                is called.
            num_timestep: The number of time steps. If ``None`` it will be set such that the timestep
                is close to 0.01.
            evolution: The evolution synthesis to use for the construction of the Trotter step.
                Defaults to first-order Lie-Trotter decomposition, see also
                :mod:`~qiskit.synthesis.evolution` for different options.
            use_parameter_shift: If True, use the parameter shift rule to compute gradients.
                If False, the optimizer will not be passed a gradient callable. In that case,
                Qiskit optimizers will use a finite difference rule to approximate the gradients.
            initial_guess: The initial guess for the first VQE optimization. Afterwards the
                previous iteration result is used as initial guess. If None, this is set to
                a random vector with elements in the interval :math:`[-0.01, 0.01]`.
            quantum_instance: The backend or quantum instance used to evaluate the circuits.
        """
        if evolution is None:
            evolution = LieTrotter()

        self.ansatz = ansatz
        self.initial_parameters = initial_parameters
        self.num_timesteps = num_timesteps
        self.optimizer = optimizer
        self.initial_guess = initial_guess
        self.expectation = expectation
        self.evolution = evolution
        self.use_parameter_shift = use_parameter_shift

        self._sampler = None
        self.quantum_instance = quantum_instance
    def test_evolutiongate(self):
        """Test loading a circuit with evolution gate works."""
        synthesis = LieTrotter(reps=2)
        evo = PauliEvolutionGate((Z ^ I) + (I ^ Z), time=2, synthesis=synthesis)
        qc = QuantumCircuit(2)
        qc.append(evo, range(2))
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]

        self.assertEqual(qc, new_circ)
        self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])

        new_evo = new_circ.data[0][0]
        self.assertIsInstance(new_evo, PauliEvolutionGate)
    def test_evolutiongate_param_vec_time(self):
        """Test loading a an evolution gate that has a param vector element for time."""
        synthesis = LieTrotter(reps=2)
        time = ParameterVector("TimeVec", 1)
        evo = PauliEvolutionGate((Z ^ I) + (I ^ Z), time=time[0], synthesis=synthesis)
        qc = QuantumCircuit(2)
        qc.append(evo, range(2))
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]

        self.assertEqual(qc, new_circ)
        self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])

        new_evo = new_circ.data[0][0]
        self.assertIsInstance(new_evo, PauliEvolutionGate)
示例#10
0
    def test_list_from_grouped_paulis(self):
        """Test getting a string representation from grouped Paulis."""
        grouped_ops = [(X ^ Y) + (Y ^ X), (Z ^ I) + (Z ^ Z) + (I ^ Z), (X ^ X)]
        evo_gate = PauliEvolutionGate(grouped_ops, time=0.12, synthesis=LieTrotter())

        pauli_strings = []
        for op in evo_gate.operator:
            if isinstance(op, SparsePauliOp):
                pauli_strings.append(op.to_list())
            else:
                pauli_strings.append([(str(op), 1 + 0j)])

        expected = [
            [("XY", 1 + 0j), ("YX", 1 + 0j)],
            [("ZI", 1 + 0j), ("ZZ", 1 + 0j), ("IZ", 1 + 0j)],
            [("XX", 1 + 0j)],
        ]
        self.assertListEqual(pauli_strings, expected)
    def test_evolutiongate_param_expr_time(self):
        """Test loading a circuit with an evolution gate that has a parameter for time."""
        synthesis = LieTrotter(reps=2)
        time = Parameter("t")
        evo = PauliEvolutionGate((Z ^ I) + (I ^ Z),
                                 time=time * time,
                                 synthesis=synthesis)
        qc = QuantumCircuit(2)
        qc.append(evo, range(2))
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]

        self.assertEqual(qc, new_circ)
        self.assertEqual([x.operation.label for x in qc.data],
                         [x.operation.label for x in new_circ.data])

        new_evo = new_circ.data[0].operation
        self.assertIsInstance(new_evo, PauliEvolutionGate)
    def __init__(
        self,
        operator,
        time: Union[int, float, ParameterExpression] = 1.0,
        label: Optional[str] = None,
        synthesis: Optional[EvolutionSynthesis] = None,
    ) -> None:
        """
        Args:
            operator (Pauli | PauliOp | SparsePauliOp | PauliSumOp | list):
                The operator to evolve. Can also be provided as list of non-commuting
                operators where the elements are sums of commuting operators.
                For example: ``[XY + YX, ZZ + ZI + IZ, YY]``.
            time: The evolution time.
            label: A label for the gate to display in visualizations. Per default, the label is
                set to ``exp(-it <operators>)`` where ``<operators>`` is the sum of the Paulis.
                Note that the label does not include any coefficients of the Paulis. See the
                class docstring for an example.
            synthesis: A synthesis strategy. If None, the default synthesis is the Lie-Trotter
                product formula with a single repetition.
        """
        if isinstance(operator, list):
            operator = [_to_sparse_pauli_op(op) for op in operator]
        else:
            operator = _to_sparse_pauli_op(operator)

        if synthesis is None:
            synthesis = LieTrotter()

        if label is None:
            label = _get_default_label(operator)

        num_qubits = operator[0].num_qubits if isinstance(
            operator, list) else operator.num_qubits
        super().__init__(name="PauliEvolution",
                         num_qubits=num_qubits,
                         params=[time],
                         label=label)

        self.operator = operator
        self.synthesis = synthesis
示例#13
0
 def __init__(
     self,
     product_formula: Optional[ProductFormula] = None,
     expectation: Optional[ExpectationBase] = None,
     quantum_instance: Optional[Union[QuantumInstance, Backend]] = None,
 ) -> None:
     """
     Args:
         product_formula: A Lie-Trotter-Suzuki product formula. The default is the Lie-Trotter
             first order product formula with a single repetition.
         expectation: An instance of ExpectationBase which defines a method for calculating
             expectation values of EvolutionProblem.aux_operators.
         quantum_instance: A quantum instance used for calculating expectation values of
             EvolutionProblem.aux_operators.
     """
     if product_formula is None:
         product_formula = LieTrotter()
     self._product_formula = product_formula
     self._quantum_instance = None
     self._circuit_sampler = None
     if quantum_instance is not None:
         self.quantum_instance = quantum_instance
     self._expectation = expectation
示例#14
0
    def __init__(
        self,
        operator,
        time: Union[int, float, ParameterExpression] = 1.0,
        label: Optional[str] = None,
        synthesis: Optional[EvolutionSynthesis] = None,
    ) -> None:
        """
        Args:
            operator (Pauli | PauliOp | SparsePauliOp | PauliSumOp | list):
                The operator to evolve. Can also be provided as list of non-commuting
                operators where the elements are sums of commuting operators.
                For example: ``[XY + YX, ZZ + ZI + IZ, YY]``.
            time: The evolution time.
            label: A label for the gate to display in visualizations.
            synthesis: A synthesis strategy. If None, the default synthesis is the Lie-Trotter
                product formula with a single repetition.
        """
        if isinstance(operator, list):
            operator = [_to_sparse_pauli_op(op) for op in operator]
            name = f"exp(-i {[' + '.join(op.paulis.to_labels()) for op in operator]})"
        else:
            operator = _to_sparse_pauli_op(operator)
            name = f"exp(-i {' + '.join(operator.paulis.to_labels())})"

        if synthesis is None:
            synthesis = LieTrotter()

        num_qubits = operator[0].num_qubits if isinstance(
            operator, list) else operator.num_qubits
        super().__init__(name=name,
                         num_qubits=num_qubits,
                         params=[time],
                         label=label)

        self.operator = operator
        self.synthesis = synthesis
示例#15
0
 def test_pauliop_coefficients_respected(self):
     """Test that global ``PauliOp`` coefficients are being taken care of."""
     evo = PauliEvolutionGate(5 * (Z ^ I), time=1, synthesis=LieTrotter())
     circuit = evo.definition.decompose()
     rz_angle = circuit.data[0][0].params[0]
     self.assertEqual(rz_angle, 10)
示例#16
0
 def _get_evolution_synthesis(self):
     """Return the ``EvolutionSynthesis`` corresponding to this Trotterization."""
     if self.trotter.order == 1:
         return LieTrotter(reps=self.trotter.reps)
     return SuzukiTrotter(reps=self.trotter.reps, order=self.trotter.order)