Example #1
0
    def test_qubitop_to_paulisum_more_terms(self):
        # Given
        qubit_operator = (
            QubitOperator("Z0 Z1 Z2", -1.5)
            + QubitOperator("X0", 2.5)
            + QubitOperator("Y1", 3.5)
        )
        expected_qubits = (LineQubit(0), LineQubit(5), LineQubit(8))
        expected_paulisum = (
            PauliSum()
            + (
                PauliString(Z.on(expected_qubits[0]))
                * PauliString(Z.on(expected_qubits[1]))
                * PauliString(Z.on(expected_qubits[2]))
                * -1.5
            )
            + (PauliString(X.on(expected_qubits[0]) * 2.5))
            + (PauliString(Y.on(expected_qubits[1]) * 3.5))
        )

        # When
        paulisum = qubitop_to_paulisum(qubit_operator, qubits=expected_qubits)

        # Then
        self.assertEqual(paulisum.qubits, expected_qubits)
        self.assertEqual(paulisum, expected_paulisum)
Example #2
0
    def test_qubitop_to_paulisum_setting_qubits(self):
        # Given
        qubit_operator = QubitOperator("Z0 Z1", -1.5)
        expected_qubits = (LineQubit(0), LineQubit(5))
        expected_paulisum = (PauliSum() +
                             PauliString(Z.on(expected_qubits[0])) *
                             PauliString(Z.on(expected_qubits[1])) * -1.5)

        # When
        paulisum = qubitop_to_paulisum(qubit_operator, qubits=expected_qubits)

        # Then
        self.assertEqual(paulisum.qubits, expected_qubits)
        self.assertEqual(paulisum, expected_paulisum)
Example #3
0
    def test_qubitop_to_paulisum_z0z1_operator(self):
        # Given
        qubit_operator = QubitOperator("Z0 Z1", -1.5)
        expected_qubits = (GridQubit(0, 0), GridQubit(1, 0))
        expected_paulisum = (PauliSum() +
                             PauliString(Z.on(expected_qubits[0])) *
                             PauliString(Z.on(expected_qubits[1])) * -1.5)

        # When
        paulisum = qubitop_to_paulisum(qubit_operator)

        # Then
        self.assertEqual(paulisum.qubits, expected_qubits)
        self.assertEqual(paulisum, expected_paulisum)
def simplify_cirq_pauli_sum(cirq_pauli_sum):
    """
    Simplifies the input CirqPauliSum object according to Pauli algebra rules
    
    Parameters
    ----------
    cirq_pauli_sum  :   (CirqPauliSum object) represents the objects that needs to be simplified according to 
                        Pauli algebra rules
                
    Returns
    -------
    CirqPauliSum object simplified according to Pauli algebra rules
    """

    pauli_strings = []
    identity_strings = []
    for pauli_string in cirq_pauli_sum.pauli_strings:
        if not pauli_string._qubit_pauli_map == {} and not np.isclose(pauli_string.coefficient, 0.0):
            pauli_strings.append(pauli_string)
        else:
            identity_strings.append(pauli_string)
    coeff = sum(i.coefficient for i in identity_strings)
    if not np.isclose(coeff, 0.0):
        total_identity_string = PauliString(
            qubit_pauli_map={}, coefficient=coeff)
        pauli_strings.append(total_identity_string)
    return CirqPauliSum(pauli_strings)
    def create_cost_operators(self):
        """
        Creates family of phase separation operators that depend on the objective function to be optimized

        Returns
        -------
        cost_operators  :   (list) cost clauses for the graph on which Maxcut needs to be solved
        """
        cost_operators = []
        for i, j in self.graph.edges():
            qubit_map_i = {i: Pauli.by_index(2)}
            qubit_map_j = {j: Pauli.by_index(2)}
            pauli_z_term = PauliString(
                qubit_map_i, coefficient=0.5) * PauliString(qubit_map_j)
            pauli_identity_term = PauliString(coefficient=-0.5)
            cost_pauli_sum = add_pauli_strings(
                [pauli_z_term, pauli_identity_term])
            cost_operators.append(cost_pauli_sum)
        return cost_operators
    def create_driver_operators(self):
        """
        Creates family of mixing operators that depend on the domain of the problem and its structure

        Returns
        -------
        driver_operators    :   (list) mixing clauses for the graph on which Maxcut needs to be solved
        """
        driver_operators = []
        for i in self.graph.nodes():
            qubit_map_i = {i: Pauli.by_index(0)}
            driver_operators.append(
                CirqPauliSum([PauliString(qubit_map_i, coefficient=-1.0)]))
        return driver_operators
Example #7
0
def compute_characteristic_function(
    pauli_string: cirq.PauliString, qubits: List[cirq.Qid], density_matrix: np.ndarray
):
    n_qubits = len(qubits)
    d = 2**n_qubits

    qubit_map = dict(zip(qubits, range(n_qubits)))
    # rho_i or sigma_i in https://arxiv.org/abs/1104.3835
    trace = pauli_string.expectation_from_density_matrix(density_matrix, qubit_map)
    assert np.isclose(trace.imag, 0.0, atol=1e-6)
    trace = trace.real

    prob = trace * trace / d  # Pr(i) in https://arxiv.org/abs/1104.3835

    return trace, prob
Example #8
0
def circuit_for_expectation_value(
        circuit: cirq.Circuit, pauli_string: cirq.PauliString) -> cirq.Circuit:
    """Sandwich a PauliString operator between a forwards and backwards
    copy of a circuit.

    This is a circuit representation of the expectation value of an operator
    <A> = <psi|A|psi> = <0|U^dag A U|0>. You can either extract the 0..0
    amplitude of the final state vector (assuming starting from the |0..0>
    state or extract the [0, 0] entry of the unitary matrix of this combined
    circuit.
    """
    assert pauli_string.coefficient == 1
    return cirq.Circuit([
        circuit,
        cirq.Moment(gate.on(q) for q, gate in pauli_string.items()),
        cirq.inverse(circuit)
    ])
Example #9
0
        def _measure_in(circuit: cirq.Circuit, pauli: cirq.PauliString):
            # Transform circuit to canonical qubit layout.
            qubit_map = dict(
                zip(
                    sorted(circuit.all_qubits()),
                    cirq.LineQubit.range(len(circuit.all_qubits())),
                ))
            circuit = circuit.transform_qubits(lambda q: qubit_map[q])

            # Measure the Paulis.
            if not set(pauli).issubset(set(circuit.all_qubits())):
                raise ValueError(
                    f"Qubit mismatch. The PauliString {self} acts on qubits "
                    f"{[q.x for q in pauli.qubits]} but the circuit has qubit "
                    f"indices {sorted([q.x for q in circuit.all_qubits()])}.")
            measured = (circuit + pauli.to_z_basis_ops() +
                        cirq.measure(*pauli.qubits))

            # Transform circuit back to original qubits.
            reverse_qubit_map = dict(zip(qubit_map.values(), qubit_map.keys()))
            return measured.transform_qubits(lambda q: reverse_qubit_map[q])
Example #10
0
def _assert_pass_over(ops: List[cirq.Operation], before: cirq.PauliString,
                      after: cirq.PauliString):
    assert before.pass_operations_over(ops[::-1]) == after
    assert after.pass_operations_over(ops, after_to_before=True) == before