Esempio n. 1
0
 def test_build_hartree_fock_circuit_bravyi_kitaev(self):
     number_of_qubits = 4
     number_of_alpha_electrons = 1
     number_of_beta_electrons = 1
     transformation = "Bravyi-Kitaev"
     expected_circuit = Circuit([X(0)], n_qubits=number_of_qubits)
     actual_circuit = build_hartree_fock_circuit(
         number_of_qubits,
         number_of_alpha_electrons,
         number_of_beta_electrons,
         transformation,
     )
     assert actual_circuit == expected_circuit
Esempio n. 2
0
 def test_build_hartree_fock_circuit_jordan_wigner(self):
     number_of_qubits = 4
     number_of_alpha_electrons = 1
     number_of_beta_electrons = 1
     transformation = "Jordan-Wigner"
     expected_circuit = Circuit([X(0), X(1)], n_qubits=number_of_qubits)
     actual_circuit = build_hartree_fock_circuit(
         number_of_qubits,
         number_of_alpha_electrons,
         number_of_beta_electrons,
         transformation,
     )
     assert actual_circuit == expected_circuit
Esempio n. 3
0
 def get_qulacs_state_from_circuit(self, circuit: Circuit):
     qulacs_state = qulacs.QuantumState(circuit.n_qubits)
     for executable, operations_group in itertools.groupby(
             circuit.operations, self.can_be_executed_natively):
         if executable:
             qulacs_circuit = convert_to_qulacs(
                 Circuit(operations_group, circuit.n_qubits))
             qulacs_circuit.update_quantum_state(qulacs_state)
         else:
             wavefunction = qulacs_state.get_vector()
             for operation in operations_group:
                 wavefunction = operation.apply(wavefunction)
             qulacs_state.load(wavefunction)
     return qulacs_state
    def test_ansatz_circuit_seven_layers(self, n_qubits, topology):
        # Given
        number_of_layers = 7
        ansatz = QCBMAnsatz(
            number_of_layers=number_of_layers,
            number_of_qubits=n_qubits,
            topology=topology,
        )
        params = [
            np.random.rand(2 * n_qubits),
            np.random.rand(int((n_qubits * (n_qubits - 1)) / 2)),
            np.random.rand(2 * n_qubits),
            np.random.rand(int((n_qubits * (n_qubits - 1)) / 2)),
            np.random.rand(3 * n_qubits),
            np.random.rand(int((n_qubits * (n_qubits - 1)) / 2)),
            np.random.rand(2 * n_qubits),
        ]

        expected_circuit = Circuit([
            # First layer
            *[RX(params[0][i])(i) for i in range(n_qubits)],
            *[RZ(params[0][i + n_qubits])(i) for i in range(n_qubits)],
            # Second layer
            *get_entangling_layer(params[1], n_qubits, XX,
                                  topology).operations,
            # Third layer
            *[RX(params[2][i])(i) for i in range(n_qubits)],
            *[RZ(params[2][i + n_qubits])(i) for i in range(n_qubits)],
            # Fouth layer
            *get_entangling_layer(params[3], n_qubits, XX,
                                  topology).operations,
            # Fifth layer
            *[RX(params[4][i])(i) for i in range(n_qubits)],
            *[RZ(params[4][i + n_qubits])(i) for i in range(n_qubits)],
            *[RX(params[4][i + 2 * n_qubits])(i) for i in range(n_qubits)],
            # Sixth layer
            *get_entangling_layer(params[5], n_qubits, XX,
                                  topology).operations,
            # Seventh layer
            *[RZ(params[6][i])(i) for i in range(n_qubits)],
            *[RX(params[6][i + n_qubits])(i) for i in range(n_qubits)],
        ])

        params = np.concatenate(params)

        # When
        circuit = ansatz.get_executable_circuit(params)

        # Then
        assert circuit == expected_circuit
Esempio n. 5
0
    def test_get_wavefunction_seed(self):
        # Given
        circuit = Circuit([H(0), CNOT(0, 1), CNOT(1, 2)])
        backend1 = ForestSimulator("wavefunction-simulator", seed=5324)
        backend2 = ForestSimulator("wavefunction-simulator", seed=5324)

        # When
        wavefunction1 = backend1.get_wavefunction(circuit)
        wavefunction2 = backend2.get_wavefunction(circuit)

        # Then
        for (ampl1, ampl2) in zip(wavefunction1.amplitudes,
                                  wavefunction2.amplitudes):
            assert ampl1 == ampl2
Esempio n. 6
0
    def test_perform_context_selection(self):
        target_operators = []
        target_operators.append(10.0 * QubitOperator("Z0"))
        target_operators.append(-3 * QubitOperator("Y0"))
        target_operators.append(1 * QubitOperator("X0"))
        target_operators.append(20 * QubitOperator(""))

        expected_operators = []
        expected_operators.append(10.0 * QubitOperator("Z0"))
        expected_operators.append(-3 * QubitOperator("Z0"))
        expected_operators.append(1 * QubitOperator("Z0"))
        expected_operators.append(20 * QubitOperator(""))

        base_circuit = Circuit([X(0)])
        x_term_circuit = Circuit([RY(-np.pi / 2)(0)])
        y_term_circuit = Circuit([RX(np.pi / 2)(0)])

        expected_circuits = [
            base_circuit,
            base_circuit + y_term_circuit,
            base_circuit + x_term_circuit,
            base_circuit,
        ]

        estimation_tasks = [
            EstimationTask(operator, base_circuit, None)
            for operator in target_operators
        ]

        tasks_with_context_selection = perform_context_selection(
            estimation_tasks)

        for task, expected_circuit, expected_operator in zip(
                tasks_with_context_selection, expected_circuits,
                expected_operators):
            assert task.operator.terms == expected_operator.terms
            assert task.circuit == expected_circuit
Esempio n. 7
0
    def circuits(self):
        circuits = [Circuit() for _ in range(5)]

        circuits[1] += RX(1.2)(0)
        circuits[1] += RY(1.5)(1)
        circuits[1] += RX(-0.0002)(0)
        circuits[1] += RY(0)(1)

        for circuit in circuits[2:]:
            circuit += RX(sympy.Symbol("theta_0"))(0)
            circuit += RY(sympy.Symbol("theta_1"))(1)
            circuit += RX(sympy.Symbol("theta_2"))(0)
            circuit += RY(sympy.Symbol("theta_3"))(1)

        return circuits
def create_X_target_unitary(number_of_params, k_body_depth=1):
    thetas = create_thetas(number_of_params)
    symbols_map = create_symbols_map(number_of_params)

    target_circuit = Circuit()
    # Add an x operator to every qubit
    for i in range(3):
        target_circuit += create_x_operator(i, thetas[i])

    if k_body_depth == 2:
        target_circuit += create_2_qubit_x_operator(0, 1, thetas[3])
        target_circuit += create_2_qubit_x_operator(0, 2, thetas[4])
        target_circuit += create_2_qubit_x_operator(1, 2, thetas[5])

    return target_circuit.bind(symbols_map).to_unitary()
def _zquantum_exponentiate_hamiltonian(hamiltonian, time, trotter_order):
    ops = []
    for term in hamiltonian.get_operators():
        mat = _zquantum_exponentiate_qubit_hamiltonian_term(
            term, time, trotter_order)
        ops.append(
            circuits.CustomGateDefinition(
                gate_name="custom_a",
                matrix=sympy.Matrix(mat),
                params_ordering=(),
            )()(0, 1))

    circuit = Circuit(operations=ops * trotter_order)

    return circuit
Esempio n. 10
0
    def test_commutes_with_parameter_substitution(self):
        theta, gamma = sympy.symbols("theta, gamma")
        circuit = Circuit([
            RX(theta / 2)(0),
            X(1),
            RY(gamma / 4).controlled(1)(1, 2),
            YY(0.1)(0, 4)
        ])

        symbols_map = {theta: 0.1, gamma: 0.5}
        parameterized_unitary = circuit.to_unitary()
        unitary = circuit.bind(symbols_map).to_unitary()

        np.testing.assert_array_almost_equal(
            np.array(parameterized_unitary.subs(symbols_map), dtype=complex),
            unitary)
def create_XZ1_target_unitary(number_of_params, k_body_depth=1):
    thetas = create_thetas(number_of_params)
    symbols_map = create_symbols_map(number_of_params)

    target_circuit = Circuit()
    target_circuit += create_x_operator(0, thetas[0])
    target_circuit += RZ(2 * thetas[1])(0)

    target_circuit += create_x_operator(1, thetas[2])
    target_circuit += RZ(2 * thetas[3])(1)

    if k_body_depth == 2:
        target_circuit += create_2_qubit_x_operator(0, 1, thetas[4])
        target_circuit += CNOT(0, 1)
        target_circuit += RZ(2 * thetas[5])(1)
        target_circuit += CNOT(0, 1)

    return target_circuit.bind(symbols_map).to_unitary()
    def test_cvar_estimator_returns_correct_values(self, estimator, backend,
                                                   operator):
        # Given
        estimation_tasks = [EstimationTask(operator, Circuit([H(0)]), 10000)]
        if estimator.alpha <= 0.5:
            target_value = -1
        else:
            target_value = (-1 * 0.5 + 1 *
                            (estimator.alpha - 0.5)) / estimator.alpha

        # When
        expectation_values = estimator(
            backend=backend,
            estimation_tasks=estimation_tasks,
        )

        # Then
        assert expectation_values[0].values == pytest.approx(target_value,
                                                             abs=2e-1)
Esempio n. 13
0
    def test_group_greedily_all_comeasureable(self):
        target_operator = 10.0 * QubitOperator("Y0")
        target_operator -= 3.0 * QubitOperator("Y0 Y1")
        target_operator += 1.0 * QubitOperator("Y1")
        target_operator += 20.0 * QubitOperator("Y0 Y1 Y2")

        circuit = Circuit([X(0), X(1), X(2)])

        estimation_tasks = [EstimationTask(target_operator, circuit, None)]

        grouped_tasks = group_greedily(estimation_tasks)

        assert len(grouped_tasks) == 1
        assert grouped_tasks[0].operator == target_operator

        for initial_task, modified_task in zip(estimation_tasks,
                                               grouped_tasks):
            assert modified_task.circuit == initial_task.circuit
            assert modified_task.number_of_shots == initial_task.number_of_shots
Esempio n. 14
0
    def test_allocate_shots_uniformly(
        self,
        frame_operators,
        n_samples,
        target_n_samples_list,
    ):
        allocate_shots = partial(allocate_shots_uniformly,
                                 number_of_shots=n_samples)
        circuit = Circuit()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1)
            for operator in frame_operators
        ]

        new_estimation_tasks = allocate_shots(estimation_tasks)

        for task, target_n_samples in zip(new_estimation_tasks,
                                          target_n_samples_list):
            assert task.number_of_shots == target_n_samples
    def _build_circuit_layer(self, parameters: np.ndarray) -> Circuit:
        """Build circuit layer for the hardware efficient quantum compiling ansatz

        Args:
            parameters: The variational parameters (or symbolic parameters)

        Returns:
            Circuit containing a single layer of the Hardware Efficient Quantum Compiling Ansatz
        """
        circuit_layer = Circuit()

        # Add RZ(theta) RX(pi/2) RZ(theta') RX(pi/2) RZ(theta'')
        circuit_layer = self._build_rotational_subcircuit(
            circuit_layer, parameters[:3 * self.number_of_qubits])

        qubit_ids = list(range(self.number_of_qubits))
        # Add CNOT(x, x+1) for x in even(qubits)
        for control, target in zip(
                qubit_ids[::2],
                qubit_ids[1::2]):  # loop over qubits 0, 2, 4...
            circuit_layer += CNOT(control, target)

        # Add RZ(theta) RX(pi/2) RZ(theta') RX(pi/2) RZ(theta'')
        circuit_layer = self._build_rotational_subcircuit(
            circuit_layer,
            parameters[3 * self.number_of_qubits:6 * self.number_of_qubits],
        )

        # Add CNOT layer working "inside -> out", skipping every other qubit

        for qubit_index in qubit_ids[:int(self.number_of_qubits /
                                          2)][::-1][::2]:
            control = qubit_index
            target = self.number_of_qubits - qubit_index - 1
            circuit_layer += CNOT(control, target)

            if qubit_index != 0 or self.number_of_qubits % 4 == 0:
                control = self.number_of_qubits - qubit_index
                target = qubit_index - 1
                circuit_layer += CNOT(control, target)

        return circuit_layer
Esempio n. 16
0
def create_target_unitary(thetas, number_of_layers):
    target_circuit = Circuit()
    target_circuit += RY(thetas[0])(0)
    target_circuit += RY(thetas[1])(1)
    betas = create_betas(number_of_layers)
    gammas = create_gammas(number_of_layers)
    symbols_map = create_symbols_map(number_of_layers)
    for layer_id in range(number_of_layers):
        beta = betas[layer_id]
        gamma = gammas[layer_id]
        target_circuit += RZ(2.0 * gamma)(0)
        target_circuit += RZ(2.0 * gamma)(1)
        target_circuit += RY(-thetas[0])(0)
        target_circuit += RY(-thetas[1])(1)
        target_circuit += RZ(-2.0 * beta)(0)
        target_circuit += RZ(-2.0 * beta)(1)
        target_circuit += RY(thetas[0])(0)
        target_circuit += RY(thetas[1])(1)

    return target_circuit.bind(symbols_map).to_unitary()
    def test_ansatz_circuit_one_layer(self, n_qubits, topology):
        # Given
        number_of_layers = 1
        ansatz = QCBMAnsatz(
            number_of_layers=number_of_layers,
            number_of_qubits=n_qubits,
            topology=topology,
        )

        params = [np.random.rand(n_qubits)]

        expected_circuit = Circuit()
        for i in range(n_qubits):
            expected_circuit += RX(params[0][i])(i)

        params = np.concatenate(params)

        # When
        circuit = ansatz.get_executable_circuit(params)

        # Then
        assert circuit == expected_circuit
Esempio n. 18
0
    def test_gibbs_estimator_returns_correct_values(self, estimator, backend,
                                                    operator):
        # Given
        estimation_tasks = [EstimationTask(operator, Circuit([H(0)]), 10000)]

        expval_0 = np.exp(1 *
                          -estimator.alpha)  # Expectation value of bitstring 0
        expval_1 = np.exp(-1 *
                          -estimator.alpha)  # Expectation value of bitstring 1

        # Target value is the -log of the mean of the expectation values of the 2 bitstrings
        target_value = -np.log((expval_1 + expval_0) / 2)

        # When
        expectation_values = estimator(
            backend=backend,
            estimation_tasks=estimation_tasks,
        )

        # Then
        assert expectation_values[0].values == pytest.approx(target_value,
                                                             abs=2e-2)
    def _generate_circuit(self,
                          parameters: Optional[np.ndarray] = None) -> Circuit:
        """Builds the ansatz circuit (based on: 2011.12245, Fig. 1)

        Args:
            params (numpy.array): input parameters of the circuit (1d array).

        Returns:
            Circuit
        """
        if parameters is None:
            parameters = self.symbols

        assert len(parameters) == self.number_of_params

        circuit = Circuit()
        for layer_index in range(self.number_of_layers):
            circuit += self._build_circuit_layer(
                parameters[layer_index *
                           self.number_of_params_per_layer:(layer_index + 1) *
                           self.number_of_params_per_layer])
        return circuit
Esempio n. 20
0
    def test_allocate_shots_proportionally(
        self,
        frame_operators,
        total_n_shots,
        prior_expectation_values,
        target_n_samples_list,
    ):
        allocate_shots = partial(
            allocate_shots_proportionally,
            total_n_shots=total_n_shots,
            prior_expectation_values=prior_expectation_values,
        )
        circuit = Circuit()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1)
            for operator in frame_operators
        ]

        new_estimation_tasks = allocate_shots(estimation_tasks)

        for task, target_n_samples in zip(new_estimation_tasks,
                                          target_n_samples_list):
            assert task.number_of_shots == target_n_samples
Esempio n. 21
0
    def test_gives_the_same_unitary_as_original_gate_up_to_global_phase(
        self, gate_to_be_decomposed, target_qubits
    ):
        circuit = Circuit([gate_to_be_decomposed(*target_qubits)])
        decomposed_circuit = decompose_zquantum_circuit(circuit, DECOMPOSITION_RULES)

        def numpy_caster(x):
            return np.array(x).astype(np.complex128)

        original_matrix = numpy_caster(circuit.operations[0].gate.wrapped_gate.matrix)

        decomposed_matrix = reduce(
            operator.matmul,
            [
                op.gate.wrapped_gate.matrix
                for op in reversed(decomposed_circuit.operations)
            ],
        )

        decomposed_matrix = numpy_caster(decomposed_matrix)

        assert _is_scaled_identity(
            original_matrix @ np.linalg.inv(decomposed_matrix),
        )
Esempio n. 22
0
class TestEstimatorUtils:
    def test_get_context_selection_circuit_for_group(self):
        group = QubitOperator("X0 Y1") - 0.5 * QubitOperator((1, "Y"))
        circuit, ising_operator = get_context_selection_circuit_for_group(
            group)

        # Need to convert to QubitOperator in order to get matrix representation
        qubit_operator = change_operator_type(ising_operator, QubitOperator)

        target_unitary = qubit_operator_sparse(group)
        transformed_unitary = (
            circuit.to_unitary().conj().T
            @ qubit_operator_sparse(qubit_operator) @ circuit.to_unitary())

        assert np.allclose(target_unitary.todense(), transformed_unitary)

    def test_perform_context_selection(self):
        target_operators = []
        target_operators.append(10.0 * QubitOperator("Z0"))
        target_operators.append(-3 * QubitOperator("Y0"))
        target_operators.append(1 * QubitOperator("X0"))
        target_operators.append(20 * QubitOperator(""))

        expected_operators = []
        expected_operators.append(10.0 * QubitOperator("Z0"))
        expected_operators.append(-3 * QubitOperator("Z0"))
        expected_operators.append(1 * QubitOperator("Z0"))
        expected_operators.append(20 * QubitOperator(""))

        base_circuit = Circuit([X(0)])
        x_term_circuit = Circuit([RY(-np.pi / 2)(0)])
        y_term_circuit = Circuit([RX(np.pi / 2)(0)])

        expected_circuits = [
            base_circuit,
            base_circuit + y_term_circuit,
            base_circuit + x_term_circuit,
            base_circuit,
        ]

        estimation_tasks = [
            EstimationTask(operator, base_circuit, None)
            for operator in target_operators
        ]

        tasks_with_context_selection = perform_context_selection(
            estimation_tasks)

        for task, expected_circuit, expected_operator in zip(
                tasks_with_context_selection, expected_circuits,
                expected_operators):
            assert task.operator.terms == expected_operator.terms
            assert task.circuit == expected_circuit

    @pytest.fixture()
    def frame_operators(self):
        operators = [
            2.0 * IsingOperator((1, "Z")) * IsingOperator((2, "Z")),
            1.0 * IsingOperator((3, "Z")) * IsingOperator((0, "Z")),
            -1.0 * IsingOperator((2, "Z")),
        ]

        return operators

    @pytest.fixture()
    def circuits(self):
        circuits = [Circuit() for _ in range(5)]

        circuits[1] += RX(1.2)(0)
        circuits[1] += RY(1.5)(1)
        circuits[1] += RX(-0.0002)(0)
        circuits[1] += RY(0)(1)

        for circuit in circuits[2:]:
            circuit += RX(sympy.Symbol("theta_0"))(0)
            circuit += RY(sympy.Symbol("theta_1"))(1)
            circuit += RX(sympy.Symbol("theta_2"))(0)
            circuit += RY(sympy.Symbol("theta_3"))(1)

        return circuits

    @pytest.mark.parametrize(
        "n_samples, target_n_samples_list",
        [
            (100, [100, 100, 100]),
            (17, [17, 17, 17]),
        ],
    )
    def test_allocate_shots_uniformly(
        self,
        frame_operators,
        n_samples,
        target_n_samples_list,
    ):
        allocate_shots = partial(allocate_shots_uniformly,
                                 number_of_shots=n_samples)
        circuit = Circuit()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1)
            for operator in frame_operators
        ]

        new_estimation_tasks = allocate_shots(estimation_tasks)

        for task, target_n_samples in zip(new_estimation_tasks,
                                          target_n_samples_list):
            assert task.number_of_shots == target_n_samples

    @pytest.mark.parametrize(
        "total_n_shots, prior_expectation_values, target_n_samples_list",
        [
            (400, None, [200, 100, 100]),
            (400, ExpectationValues(np.array([0, 0, 0])), [200, 100, 100]),
            (400, ExpectationValues(np.array([1, 0.3, 0.3])), [0, 200, 200]),
        ],
    )
    def test_allocate_shots_proportionally(
        self,
        frame_operators,
        total_n_shots,
        prior_expectation_values,
        target_n_samples_list,
    ):
        allocate_shots = partial(
            allocate_shots_proportionally,
            total_n_shots=total_n_shots,
            prior_expectation_values=prior_expectation_values,
        )
        circuit = Circuit()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1)
            for operator in frame_operators
        ]

        new_estimation_tasks = allocate_shots(estimation_tasks)

        for task, target_n_samples in zip(new_estimation_tasks,
                                          target_n_samples_list):
            assert task.number_of_shots == target_n_samples

    @pytest.mark.parametrize(
        "n_samples",
        [-1],
    )
    def test_allocate_shots_uniformly_invalid_inputs(
        self,
        n_samples,
    ):
        estimation_tasks = []
        with pytest.raises(ValueError):
            allocate_shots_uniformly(estimation_tasks,
                                     number_of_shots=n_samples)

    @pytest.mark.parametrize(
        "total_n_shots, prior_expectation_values",
        [
            (-1, ExpectationValues(np.array([0, 0, 0]))),
        ],
    )
    def test_allocate_shots_proportionally_invalid_inputs(
        self,
        total_n_shots,
        prior_expectation_values,
    ):
        estimation_tasks = []
        with pytest.raises(ValueError):
            _ = allocate_shots_proportionally(estimation_tasks, total_n_shots,
                                              prior_expectation_values)

    def test_evaluate_estimation_circuits_no_symbols(
        self,
        circuits,
    ):
        evaluate_circuits = partial(evaluate_estimation_circuits,
                                    symbols_maps=[[] for _ in circuits])
        operator = QubitOperator()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1) for circuit in circuits
        ]

        new_estimation_tasks = evaluate_circuits(estimation_tasks)

        for old_task, new_task in zip(estimation_tasks, new_estimation_tasks):
            assert old_task.circuit == new_task.circuit

    def test_evaluate_estimation_circuits_all_symbols(
        self,
        circuits,
    ):
        symbols_maps = [[
            (sympy.Symbol("theta_0"), 0),
            (sympy.Symbol("theta_1"), 0),
            (sympy.Symbol("theta_2"), 0),
            (sympy.Symbol("theta_3"), 0),
        ] for _ in circuits]
        evaluate_circuits = partial(
            evaluate_estimation_circuits,
            symbols_maps=symbols_maps,
        )
        operator = QubitOperator()
        estimation_tasks = [
            EstimationTask(operator, circuit, 1) for circuit in circuits
        ]

        new_estimation_tasks = evaluate_circuits(estimation_tasks)

        for new_task in new_estimation_tasks:
            assert len(new_task.circuit.free_symbols) == 0

    def test_group_greedily_all_different_groups(self):
        target_operator = 10.0 * QubitOperator("Z0")
        target_operator -= 3.0 * QubitOperator("Y0")
        target_operator += 1.0 * QubitOperator("X0")
        target_operator += 20.0 * QubitOperator("")

        expected_operators = [
            10.0 * QubitOperator("Z0"),
            -3.0 * QubitOperator("Y0"),
            1.0 * QubitOperator("X0"),
            20.0 * QubitOperator(""),
        ]

        circuit = Circuit([X(0)])

        estimation_tasks = [EstimationTask(target_operator, circuit, None)]

        grouped_tasks = group_greedily(estimation_tasks)

        for task, operator in zip(grouped_tasks, expected_operators):
            assert task.operator == operator

        for initial_task, modified_task in zip(estimation_tasks,
                                               grouped_tasks):
            assert modified_task.circuit == initial_task.circuit
            assert modified_task.number_of_shots == initial_task.number_of_shots

    def test_group_greedily_all_comeasureable(self):
        target_operator = 10.0 * QubitOperator("Y0")
        target_operator -= 3.0 * QubitOperator("Y0 Y1")
        target_operator += 1.0 * QubitOperator("Y1")
        target_operator += 20.0 * QubitOperator("Y0 Y1 Y2")

        circuit = Circuit([X(0), X(1), X(2)])

        estimation_tasks = [EstimationTask(target_operator, circuit, None)]

        grouped_tasks = group_greedily(estimation_tasks)

        assert len(grouped_tasks) == 1
        assert grouped_tasks[0].operator == target_operator

        for initial_task, modified_task in zip(estimation_tasks,
                                               grouped_tasks):
            assert modified_task.circuit == initial_task.circuit
            assert modified_task.number_of_shots == initial_task.number_of_shots

    def test_group_individually(self):
        target_operator = 10.0 * QubitOperator("Z0")
        target_operator += 5.0 * QubitOperator("Z1")
        target_operator -= 3.0 * QubitOperator("Y0")
        target_operator += 1.0 * QubitOperator("X0")
        target_operator += 20.0 * QubitOperator("")

        expected_operator_terms_per_frame = [
            (10.0 * QubitOperator("Z0")).terms,
            (5.0 * QubitOperator("Z1")).terms,
            (-3.0 * QubitOperator("Y0")).terms,
            (1.0 * QubitOperator("X0")).terms,
            (20.0 * QubitOperator("")).terms,
        ]

        circuit = Circuit([X(0)])

        estimation_tasks = [EstimationTask(target_operator, circuit, None)]

        grouped_tasks = group_individually(estimation_tasks)

        assert len(grouped_tasks) == 5

        for task in grouped_tasks:
            assert task.operator.terms in expected_operator_terms_per_frame

    @pytest.mark.parametrize(
        ",".join([
            "estimation_tasks",
            "ref_estimation_tasks_to_measure",
            "ref_non_measured_estimation_tasks",
            "ref_indices_to_measure",
            "ref_non_measured_indices",
        ]),
        [
            (
                [
                    EstimationTask(IsingOperator("2[Z0] + 3 [Z1 Z2]"),
                                   Circuit([X(0)]), 10),
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4[]"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [
                    EstimationTask(IsingOperator("2[Z0] + 3 [Z1 Z2]"),
                                   Circuit([X(0)]), 10),
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4 []"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [],
                [0, 1, 2],
                [],
            ),
            (
                [
                    EstimationTask(IsingOperator("2[Z0] + 3 [Z1 Z2]"),
                                   Circuit([X(0)]), 10),
                    EstimationTask(
                        IsingOperator("4[] "),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [
                    EstimationTask(IsingOperator("2[Z0] + 3 [Z1 Z2]"),
                                   Circuit([X(0)]), 10),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [
                    EstimationTask(IsingOperator("4[]"),
                                   Circuit([RZ(np.pi / 2)(0)]), 1000)
                ],
                [0, 2],
                [1],
            ),
            (
                [
                    EstimationTask(IsingOperator("- 3 []"), Circuit([X(0)]),
                                   0),
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4[]"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4 []"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        17,
                    ),
                ],
                [
                    EstimationTask(IsingOperator("- 3 []"), Circuit([X(0)]),
                                   0),
                ],
                [1, 2],
                [0],
            ),
            (
                [
                    EstimationTask(IsingOperator("- 3 []"), Circuit([X(0)]),
                                   0),
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4[]"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        0,
                    ),
                ],
                [
                    EstimationTask(
                        IsingOperator("2[Z0] + 3 [Z1 Z2] + 4 []"),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                ],
                [
                    EstimationTask(IsingOperator("- 3 []"), Circuit([X(0)]),
                                   0),
                    EstimationTask(
                        IsingOperator("4[Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        0,
                    ),
                ],
                [1],
                [0, 2],
            ),
        ],
    )
    def test_split_estimation_tasks_to_measure(
        self,
        estimation_tasks,
        ref_estimation_tasks_to_measure,
        ref_non_measured_estimation_tasks,
        ref_indices_to_measure,
        ref_non_measured_indices,
    ):

        (
            estimation_task_to_measure,
            non_measured_estimation_tasks,
            indices_to_measure,
            indices_for_non_measureds,
        ) = split_estimation_tasks_to_measure(estimation_tasks)

        assert estimation_task_to_measure == ref_estimation_tasks_to_measure
        assert non_measured_estimation_tasks == ref_non_measured_estimation_tasks
        assert indices_to_measure == ref_indices_to_measure
        assert ref_non_measured_indices == indices_for_non_measureds

    @pytest.mark.parametrize(
        "estimation_tasks,ref_expectation_values",
        [
            (
                [
                    EstimationTask(
                        IsingOperator("4[] "),
                        Circuit([RZ(np.pi / 2)(0)]),
                        1000,
                    ),
                ],
                [
                    ExpectationValues(
                        np.asarray([4.0]),
                        correlations=[np.asarray([[0.0]])],
                        estimator_covariances=[np.asarray([[0.0]])],
                    ),
                ],
            ),
            (
                [
                    EstimationTask(IsingOperator("- 2.5 [] - 0.5 []"),
                                   Circuit([X(0)]), 0),
                    EstimationTask(IsingOperator("0.001[] "),
                                   Circuit([RZ(np.pi / 2)(0)]), 2),
                    EstimationTask(
                        IsingOperator("2.5 [Z1] + 1.0 [Z2 Z3]"),
                        Circuit([RY(np.pi / 2)(0)]),
                        0,
                    ),
                ],
                [
                    ExpectationValues(
                        np.asarray([-3.0]),
                        correlations=[np.asarray([[0.0]])],
                        estimator_covariances=[np.asarray([[0.0]])],
                    ),
                    ExpectationValues(
                        np.asarray([0.001]),
                        correlations=[np.asarray([[0.0]])],
                        estimator_covariances=[np.asarray([[0.0]])],
                    ),
                    ExpectationValues(
                        np.asarray([0.0]),
                        correlations=[np.asarray([[0.0]])],
                        estimator_covariances=[np.asarray([[0.0]])],
                    ),
                ],
            ),
        ],
    )
    def test_evaluate_non_measured_estimation_tasks(self, estimation_tasks,
                                                    ref_expectation_values):

        expectation_values = evaluate_non_measured_estimation_tasks(
            estimation_tasks)

        for ex_val, ref_ex_val in zip(expectation_values,
                                      ref_expectation_values):
            assert np.allclose(ex_val.values, ref_ex_val.values)
            assert np.allclose(ex_val.correlations, ref_ex_val.correlations)
            assert np.allclose(ex_val.estimator_covariances,
                               ref_ex_val.estimator_covariances)

    @pytest.mark.parametrize(
        "estimation_tasks",
        [
            ([
                EstimationTask(IsingOperator("- 2.5 [] - 0.5 [Z1]"),
                               Circuit([X(0)]), 1),
            ]),
            ([
                EstimationTask(
                    IsingOperator("0.001 [Z0]"),
                    Circuit([RZ(np.pi / 2)(0)]),
                    0,
                ),
                EstimationTask(IsingOperator("2.0[] "),
                               Circuit([RZ(np.pi / 2)(0)]), 2),
                EstimationTask(
                    IsingOperator("1.5 [Z0 Z1]"),
                    Circuit([RY(np.pi / 2)(0)]),
                    10,
                ),
            ]),
        ],
    )
    def test_evaluate_non_measured_estimation_tasks_fails_with_non_zero_shots(
            self, estimation_tasks):
        with pytest.raises(RuntimeError):
            _ = evaluate_non_measured_estimation_tasks(estimation_tasks)
Esempio n. 23
0
def concatenate_circuits(circuit_set: Union[str, List[Circuit]]):
    if isinstance(circuit_set, str):
        circuit_set = load_circuitset(circuit_set)
    result_circuit = sum(circuit_set, Circuit())
    save_circuitset(result_circuit, "result-circuit.json")
Esempio n. 24
0
    def test_leaves_gates_not_matching_predicate_unaffected(self, operations):
        circuit = Circuit(operations)
        decomposed_circuit = decompose_zquantum_circuit(circuit, DECOMPOSITION_RULES)

        assert circuit.operations == decomposed_circuit.operations
Esempio n. 25
0
class TestCreatingUnitaryFromCircuit:
    @pytest.fixture
    def cirq_unitaries(self):
        """
        Note: We decided to go with file-based approach after extracting cirq
        from z-quantum-core and not being able to use `export_to_cirq` anymore.
        """
        path_to_array = ("/".join(__file__.split("/")[:-1]) +
                         "/hardcoded_cirq_unitaries.npy")
        return np.load(path_to_array, allow_pickle=True)

    @pytest.mark.parametrize(
        "circuit, unitary_index",
        [
            # Identity gates in some test cases below are used so that comparable
            # Cirq circuits have the same number of qubits as Zquantum ones.
            (Circuit([RX(np.pi / 5)(0)]), 0),
            (Circuit([RY(np.pi / 2)(0), RX(np.pi / 5)(0)]), 1),
            (
                Circuit(
                    [I(1),
                     I(2),
                     I(3),
                     I(4),
                     RX(np.pi / 5)(0),
                     XX(0.1)(5, 0)]),
                2,
            ),
            (
                Circuit([
                    XY(np.pi).controlled(1)(3, 1, 4),
                    RZ(0.1 * np.pi).controlled(2)(0, 2, 1),
                ]),
                3,
            ),
            (
                Circuit(
                    [H(1),
                     YY(0.1).controlled(1)(0, 1, 2),
                     X(2),
                     Y(3),
                     Z(4)]),
                4,
            ),
        ],
    )
    def test_without_free_params_gives_the_same_result_as_cirq(
            self, circuit, unitary_index, cirq_unitaries):
        zquantum_unitary = circuit.to_unitary()

        assert isinstance(
            zquantum_unitary, np.ndarray
        ), "Unitary constructed from non-parameterized circuit is not a numpy array."

        np.testing.assert_array_almost_equal(zquantum_unitary,
                                             cirq_unitaries[unitary_index])

    def test_commutes_with_parameter_substitution(self):
        theta, gamma = sympy.symbols("theta, gamma")
        circuit = Circuit([
            RX(theta / 2)(0),
            X(1),
            RY(gamma / 4).controlled(1)(1, 2),
            YY(0.1)(0, 4)
        ])

        symbols_map = {theta: 0.1, gamma: 0.5}
        parameterized_unitary = circuit.to_unitary()
        unitary = circuit.bind(symbols_map).to_unitary()

        np.testing.assert_array_almost_equal(
            np.array(parameterized_unitary.subs(symbols_map), dtype=complex),
            unitary)
 def circuit(self):
     return Circuit([X(0)])
Esempio n. 27
0
    def _generate_circuit(self,
                          params: Optional[np.ndarray] = None) -> Circuit:
        """Builds a qcbm ansatz circuit, using the ansatz in https://advances.sciencemag.org/content/5/10/eaaw9918/tab-pdf (Fig.2 - top).
        Args:
            params (numpy.array): input parameters of the circuit (1d array).
        Returns:
            Circuit
        """
        if params is None:
            params = np.asarray([
                sympy.Symbol("theta_{}".format(i))
                for i in range(self.number_of_params)
            ])

        assert len(params) == self.number_of_params

        if self.number_of_layers == 1:
            # Only one layer, should be a single layer of rotations with RX
            return create_layer_of_gates(self.number_of_qubits, RX, params)

        circuit = Circuit()
        parameter_index = 0
        for layer_index in range(self.number_of_layers):
            if layer_index == 0:
                # First layer is always 2 single qubit rotations on RX RZ
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index:parameter_index +
                           self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RZ,
                    params[parameter_index +
                           self.number_of_qubits:parameter_index +
                           2 * self.number_of_qubits],
                )
                parameter_index += 2 * self.number_of_qubits
            elif (self.number_of_layers % 2 == 1
                  and layer_index == self.number_of_layers - 1):
                # Last layer for odd number of layers is rotations on RX RZ
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RZ,
                    params[parameter_index:parameter_index +
                           self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index +
                           self.number_of_qubits:parameter_index +
                           2 * self.number_of_qubits],
                )
                parameter_index += 2 * self.number_of_qubits
            elif (self.number_of_layers % 2 == 0
                  and layer_index == self.number_of_layers - 2):
                # Even number of layers, second to last layer is 3 rotation layer with RX RZ RX
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index:parameter_index +
                           self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RZ,
                    params[parameter_index +
                           self.number_of_qubits:parameter_index +
                           2 * self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index +
                           2 * self.number_of_qubits:parameter_index +
                           3 * self.number_of_qubits],
                )
                parameter_index += 3 * self.number_of_qubits
            elif (self.number_of_layers % 2 == 1
                  and layer_index == self.number_of_layers - 3):
                # Odd number of layers, third to last layer is 3 rotation layer with RX RZ RX
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index:parameter_index +
                           self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RZ,
                    params[parameter_index +
                           self.number_of_qubits:parameter_index +
                           2 * self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index +
                           2 * self.number_of_qubits:parameter_index +
                           3 * self.number_of_qubits],
                )
                parameter_index += 3 * self.number_of_qubits
            elif layer_index % 2 == 1:
                # Currently on an entangling layer
                circuit += get_entangling_layer(
                    params[parameter_index:parameter_index +
                           self.n_params_per_ent_layer],
                    self.number_of_qubits,
                    XX,
                    self.topology,
                )
                parameter_index += self.n_params_per_ent_layer
            else:
                # A normal single qubit rotation layer of RX RZ
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RX,
                    params[parameter_index:parameter_index +
                           self.number_of_qubits],
                )
                circuit += create_layer_of_gates(
                    self.number_of_qubits,
                    RZ,
                    params[parameter_index +
                           self.number_of_qubits:parameter_index +
                           2 * self.number_of_qubits],
                )
                parameter_index += 2 * self.number_of_qubits

        return circuit
Esempio n. 28
0
                    10,
                ),
            ]),
        ],
    )
    def test_evaluate_non_measured_estimation_tasks_fails_with_non_zero_shots(
            self, estimation_tasks):
        with pytest.raises(RuntimeError):
            _ = evaluate_non_measured_estimation_tasks(estimation_tasks)


TEST_CASES_EIGENSTATES = [
    (
        [
            EstimationTask(IsingOperator("Z0"),
                           circuit=Circuit([X(0)]),
                           number_of_shots=10),
            EstimationTask(
                IsingOperator((), coefficient=2.0),
                circuit=Circuit([RY(np.pi / 4)(0)]),
                number_of_shots=30,
            ),
        ],
        [ExpectationValues(np.array([-1])),
         ExpectationValues(np.array([2]))],
    ),
]
TEST_CASES_NONEIGENSTATES = [
    (
        [
            EstimationTask(
        assert contract(estimator)
"""

import numpy as np
from openfermion import IsingOperator
from zquantum.core.circuits import RX, RY, RZ, Circuit, H
from zquantum.core.interfaces.estimation import (
    EstimateExpectationValues,
    EstimationTask,
)
from zquantum.core.symbolic_simulator import SymbolicSimulator

_backend = SymbolicSimulator(seed=1997)

_estimation_tasks = [
    EstimationTask(IsingOperator("Z0"), Circuit([H(0)]), 10000),
    EstimationTask(
        IsingOperator("Z0") + IsingOperator("Z1") + IsingOperator("Z2"),
        Circuit([H(0), RX(np.pi / 3)(0), H(2)]),
        10000,
    ),
    EstimationTask(
        IsingOperator("Z0") + IsingOperator("Z1", 4),
        Circuit([
            RX(np.pi)(0),
            RY(0.12)(1),
            RZ(np.pi / 3)(1),
            RY(1.9213)(0),
        ]),
        10000,
    ),
class SymbolicSimulatorWithNonSupportedOperations(SymbolicSimulator):
    def is_natively_supported(self, operation: Operation) -> bool:
        return super().is_natively_supported(
            operation) and operation.gate.name != "RX"


class SymbolicSimulatorWithDefaultSetOfSupportedOperations(SymbolicSimulator):
    def is_natively_supported(self, operation: Operation) -> bool:
        return QuantumSimulator.is_natively_supported(self, operation)


@pytest.mark.parametrize(
    "circuit",
    [
        Circuit([RY(0.5)(0), RX(1)(1),
                 CNOT(0, 2), RX(np.pi)(2)]),
        Circuit([RX(1)(1), CNOT(0, 2),
                 RX(np.pi)(2), RY(0.5)(0)]),
        Circuit([RX(1)(1),
                 CNOT(0, 2),
                 RX(np.pi)(2),
                 RY(0.5)(0),
                 RX(0.5)(0)]),
    ],
)
def test_quantum_simulator_switches_between_native_and_nonnative_modes_of_execution(
    circuit, ):
    simulator = SymbolicSimulatorWithNonSupportedOperations()
    reference_simulator = SymbolicSimulator()

    np.testing.assert_array_equal(