Exemple #1
0
def _max_ent_state_circuit(num_qubits: int) -> Circuit:
    r"""Generates a circuits which prepares the maximally entangled state
    |\omega\rangle = U |0\rangle  = \sum_i |i\rangle \otimes |i\rangle .

    Args:
        num_qubits: The number of qubits on which the circuit is applied.
            Only 2 or 4 qubits are supported.

    Returns:
        The circuits which prepares the state |\omega\rangle.
    """

    qreg = LineQubit.range(num_qubits)
    circ = Circuit()
    if num_qubits == 2:
        circ.append(H.on(qreg[0]))
        circ.append(CNOT.on(*qreg))
    elif num_qubits == 4:
        # Prepare half of the qubits in a uniform superposition
        circ.append(H.on(qreg[0]))
        circ.append(H.on(qreg[1]))
        # Create a perfect correlation between the two halves of the qubits.
        circ.append(CNOT.on(qreg[0], qreg[2]))
        circ.append(CNOT.on(qreg[1], qreg[3]))
    else:
        raise NotImplementedError(
            "Only 2- or 4-qubit maximally entangling circuits are supported."
        )
    return circ
Exemple #2
0
def test_simplify_circuit_exponents():
    qreg = LineQubit.range(2)
    circuit = Circuit([H.on(qreg[0]), CNOT.on(*qreg), Z.on(qreg[1])])

    # Invert circuit
    inverse_circuit = cirq.inverse(circuit)
    inverse_repr = inverse_circuit.__repr__()
    inverse_qasm = inverse_circuit._to_qasm_output().__str__()

    # Expected circuit after simplification
    expected_inv = Circuit([Z.on(qreg[1]), CNOT.on(*qreg), H.on(qreg[0])])
    expected_repr = expected_inv.__repr__()
    expected_qasm = expected_inv._to_qasm_output().__str__()

    # Check inverse_circuit is logically equivalent to expected_inverse
    # but they have a different representation
    assert inverse_circuit == expected_inv
    assert inverse_repr != expected_repr
    assert inverse_qasm != expected_qasm

    # Simplify the circuit
    _simplify_circuit_exponents(inverse_circuit)

    # Check inverse_circuit has the expected simplified representation
    simplified_repr = inverse_circuit.__repr__()
    simplified_qasm = inverse_circuit._to_qasm_output().__str__()
    assert inverse_circuit == expected_inv
    assert simplified_repr == expected_repr
    assert simplified_qasm == expected_qasm
Exemple #3
0
def makeDeutschCircuit(q0, q1, oracle):
    c = cirq.Circuit()

    c.append([X(q1), H(q1), H(q0)])

    c.append(oracle)

    c.append([H(q0), measure(q0, key='result')])
    return c
Exemple #4
0
    def __call__(self, qubits):
        q0, q1, q2 = qubits[0:3]
        yield rx(sympy.Symbol("rad0")).on(q0)
        yield CNOT(q0, q1)
        yield H(q2)
        yield CNOT(q2, q1)
        yield TOFFOLI(q1, q0, q2)

        for q in qubits:
            yield H(q)
Exemple #5
0
def make_deutsch_circuit(q0, q1, oracle):
    c = cirq.Circuit()

    # Initialize qubits.
    c.append([X(q1), H(q1), H(q0)], strategy=InsertStrategy.NEW)

    # Query oracle.
    c.append(oracle, strategy=InsertStrategy.NEW)

    # Measure in X basis.
    c.append([H(q0), measure(q0, key='result')], strategy=InsertStrategy.NEW)
    return c
Exemple #6
0
def make_deutsch_circuit(q0, q1, oracle):
    c = cirq.Circuit()

    # Initialize qubits.
    c.append([X(q1), H(q1), H(q0)])

    # Query oracle.
    c.append(oracle)

    # Measure in X basis.
    c.append(H(q0))
    return c
Exemple #7
0
    def as_circuit(self):
        if self._circuit is not None:
            return self._circuit

        else:
            self._circuit = self.to_circuit()[0]
            self._circuit.insert(0,
                                 Moment([
                                     H(LineQubit(i)) for i in range(self.n)
                                 ]))  # hack to show all qubits
            self._circuit.insert(
                0, Moment([H(LineQubit(i)) for i in range(self.n)]))
            return self._circuit
Exemple #8
0
def _max_ent_state_circuit(num_qubits: int) -> Circuit:
    r"""Generates a circuit which prepares the maximally entangled state
    |\omega\rangle = U |0\rangle  = \sum_i |i\rangle \otimes |i\rangle .

    Args:
        num_qubits: The number of qubits on which the circuit is applied.
            It must be an even number because of the structure of a
            maximally entangled state.

    Returns:
        The circuits which prepares the state |\omega\rangle.

    Raises:
        Value error: if num_qubits is not an even positive integer.
    """

    if not isinstance(num_qubits, int) or num_qubits % 2 or num_qubits == 0:
        raise ValueError(
            "The argument 'num_qubits' must be an even and positive integer.")

    alice_reg = LineQubit.range(num_qubits // 2)
    bob_reg = LineQubit.range(num_qubits // 2, num_qubits)

    return Circuit(
        # Prepare alice_register in a uniform superposition
        H.on_each(*alice_reg),
        # Correlate alice_register with bob_register
        [CNOT.on(alice_reg[i], bob_reg[i]) for i in range(num_qubits // 2)],
    )
Exemple #9
0
def test_minimize_one_norm_with_depolarized_choi():
    for noise_level in [0.01, 0.02, 0.03]:
        q = LineQubit(0)
        ideal_matrix = _operation_to_choi(H(q))
        basis_matrices = [
            _operation_to_choi(
                [H(q), gate(q),
                 DepolarizingChannel(noise_level, 1)(q)])
            for gate in [I, X, Y, Z, H]
        ]
        optimal_coeffs = minimize_one_norm(ideal_matrix, basis_matrices)
        represented_mat = sum(
            [eta * mat for eta, mat in zip(optimal_coeffs, basis_matrices)])
        assert np.allclose(ideal_matrix, represented_mat)

        # Optimal analytic result by Takagi (arXiv:2006.12509)
        eps = 4.0 / 3.0 * noise_level
        expected = (1.0 + 0.5 * eps) / (1.0 - eps)
        assert np.isclose(np.linalg.norm(optimal_coeffs, 1), expected)
Exemple #10
0
    def __call__(self, qubits, **kwargs):
        q0, q1 = qubits[:2]
        yield rx(rad).on(q0)
        yield ControlledGate(rz(rad)).on(q0, q1)
        # yield H(q2)
        # yield CNOT(q2, q1)
        # yield TOFFOLI(q1, q0, q2)

        for q in qubits:
            yield H(q)
Exemple #11
0
def test_minimize_one_norm_with_amp_damp_choi():
    for noise_level in [0.01, 0.02, 0.03]:
        q = LineQubit(0)
        ideal_matrix = _operation_to_choi(H(q))
        basis_matrices = [
            _operation_to_choi(
                [H(q), gate(q),
                 AmplitudeDampingChannel(noise_level)(q)]) for gate in [I, Z]
        ]
        # Append reset channel
        reset_kraus = channel(ResetChannel())
        basis_matrices.append(kraus_to_choi(reset_kraus))
        optimal_coeffs = minimize_one_norm(ideal_matrix, basis_matrices)
        represented_mat = sum(
            [eta * mat for eta, mat in zip(optimal_coeffs, basis_matrices)])
        assert np.allclose(ideal_matrix, represented_mat)

        # Optimal analytic result by Takagi (arXiv:2006.12509)
        expected = (1.0 + noise_level) / (1.0 - noise_level)
        assert np.isclose(np.linalg.norm(optimal_coeffs, 1), expected)
Exemple #12
0
 def qaoa_ansatz(params: np.ndarray) -> Circuit:
     half = int(len(params) / 2)
     betas, gammas = params[:half], params[half:]
     qaoa_steps = sum(
         [
             cost_step(beta) + mix_step(gamma)
             for beta, gamma in zip(betas, gammas)
         ],
         Circuit(),
     )
     return Circuit(H.on_each(qreg)) + qaoa_steps
Exemple #13
0
def test_represent_operations_in_circuit_local(circuit_type: str):
    """Tests all operation representations are created."""
    qreg = LineQubit.range(2)
    circ_mitiq = Circuit([CNOT(*qreg), H(qreg[0]), Y(qreg[1]), CNOT(*qreg)])
    circ = convert_from_mitiq(circ_mitiq, circuit_type)

    reps = represent_operations_in_circuit_with_local_depolarizing_noise(
        ideal_circuit=circ, noise_level=0.1,
    )

    for op in convert_to_mitiq(circ)[0].all_operations():
        found = False
        for rep in reps:
            if _equal(rep.ideal, Circuit(op), require_qubit_equality=True):
                found = True
        assert found

    # The number of reps. should match the number of unique operations
    assert len(reps) == 3
Exemple #14
0
def iqft(n, qubits, circuit):

    #Swap the qubits
    for i in range(n // 2):
        circuit.append(SWAP(qubits[i], qubits[n - i - 1]),
                       strategy=InsertStrategy.NEW)

    #For each qubit
    for i in range(n - 1, -1, -1):
        #Apply CR_k gates where j is the control and i is the target
        k = n - i  #We start with k=n-i
        for j in range(n - 1, i, -1):
            #Define and apply CR_k gate
            crk = CZPowGate(exponent=-2 / 2**(k))
            circuit.append(crk(qubits[j], qubits[i]),
                           strategy=InsertStrategy.NEW)
            k = k - 1  #Decrement at each step

        #Apply Hadamard to the qubit
        circuit.append(H(qubits[i]), strategy=InsertStrategy.NEW)
Exemple #15
0
def test_short_circuit_warning(factory):
    """Tests a warning is raised if the input circuit has very few gates."""
    scale_factors = np.linspace(1.0, 10.0, num=20)

    def executor(circuits) -> List[float]:
        return [1.0] * len(circuits)

    if factory is PolyFactory or factory is PolyExpFactory:
        fac = factory(scale_factors=scale_factors, order=2)
    elif factory is AdaExpFactory:
        fac = factory(steps=4)
    else:
        fac = factory(scale_factors=scale_factors)

    qubit = LineQubit(0)
    circuit = cirq.Circuit(X(qubit), H(qubit), X(qubit))

    with warns(
        UserWarning, match=r"The input circuit is very short.",
    ):
        fac.run(circuit, executor, scale_noise=lambda circ, _: circ)
Exemple #16
0
    def create_initial_state(self, driver_ref):
        """
        Generates a circuit representing the initial state of the QAOA algorithm
        on which the cost and driver operators are alternatively applied

        Parameters
        ----------
        driver_ref          :   (Circuit object) circuit representing the initial state. If driver_ref is None,
                                the function returns state representing equal superposition over
                                all qubits

        Returns
        -------
        circuit             :   (Circuit object) represents the initial state for the QAOA algorithm
        """
        if driver_ref is not None:
            return driver_ref

        circuit = Circuit()
        circuit.append([H(i) for i in self.qubits],
                       strategy=InsertStrategy.EARLIEST)
        return circuit
Exemple #17
0
def deutsch_dircuit_method(first_param, second_param, oracle):
    result = cirq.Circuit()
    result.append([X(second_param), H(second_param), H(first_param)])
    result.append(oracle)
    result.append([H(first_param), measure(first_param, key='result')])
    return result
Exemple #18
0
def make_maxcut(
    graph: List[Tuple[int, int]],
    noise: float = 0,
    scale_noise: Optional[Callable[[QPROGRAM, float], QPROGRAM]] = None,
    factory: Optional[Factory] = None,
) -> Tuple[
    Callable[[np.ndarray], float], Callable[[np.ndarray], Circuit], np.ndarray
]:
    """Makes an executor that evaluates the QAOA ansatz at a given beta
    and gamma parameters.

    Args:
        graph: The MAXCUT graph as a list of edges with integer labelled nodes.
        noise: The level of depolarizing noise.
        scale_noise: The noise scaling method for ZNE.
        factory: The factory to use for ZNE.

    Returns:
        (ansatz_eval, ansatz_maker, cost_obs) as a triple. Here
            ansatz_eval: function that evalutes the maxcut ansatz on
                the noisy cirq backend.
            ansatz_maker: function that returns an ansatz circuit.
            cost_obs: the cost observable as a dense matrix.
    """
    # get the list of unique nodes from the list of edges
    nodes = list({node for edge in graph for node in edge})
    nodes = list(range(max(nodes) + 1))

    # one qubit per node
    qreg = [NamedQubit(str(nn)) for nn in nodes]

    def cost_step(beta: float) -> Circuit:
        return Circuit(ZZ(qreg[u], qreg[v]) ** (beta) for u, v in graph)

    def mix_step(gamma: float) -> Circuit:
        return Circuit(X(qq) ** gamma for qq in qreg)

    init_state_prog = Circuit(H.on_each(qreg))

    def qaoa_ansatz(params: np.ndarray) -> Circuit:
        half = int(len(params) / 2)
        betas, gammas = params[:half], params[half:]
        qaoa_steps = sum(
            [
                cost_step(beta) + mix_step(gamma)
                for beta, gamma in zip(betas, gammas)
            ],
            Circuit(),
        )
        return init_state_prog + qaoa_steps

    # make the cost observable
    identity = np.eye(2 ** len(nodes))
    cost_mat = -0.5 * sum(
        identity - Circuit([id(*qreg), ZZ(qreg[i], qreg[j])]).unitary()
        for i, j in graph
    )
    noisy_backend = make_noisy_backend(noise, cost_mat)

    # must have this function signature to work with scipy minimize
    def qaoa_cost(params: np.ndarray) -> float:
        qaoa_prog = qaoa_ansatz(params)
        if scale_noise is None and factory is None:
            return noisy_backend(qaoa_prog)
        else:
            assert scale_noise is not None
            return execute_with_zne(
                qaoa_prog,
                executor=noisy_backend,
                scale_noise=scale_noise,
                factory=factory,
            )

    return qaoa_cost, qaoa_ansatz, cost_mat
def exponentiate_general_case(pauli_string, param):
    """
    Returns a Circuit object corresponding to the exponential of the `pauli_string` object, 
    i.e. exp(-1.0j * param * pauli_string)

    Parameters:
    ----------
    pauli_string    :   (PauliString object) represents the Pauli term to exponentiate
    param           :   (float) scalar, non-complex, value

    Returns:
    -------
    circuit         :   (Circuit) represents a parameterized circuit corresponding to the exponential of 
                        the input `pauli_string` and parameter `param`
    """
    def reverse_circuit_operations(c):
        reverse_circuit = Circuit()
        operations_in_c = []
        reverse_operations_in_c = []
        for operation in c.all_operations():
            operations_in_c.append(operation)

        reverse_operations_in_c = inverse(operations_in_c)

        for operation in reverse_operations_in_c:
            reverse_circuit.append(
                [operation], strategy=InsertStrategy.EARLIEST)
        return reverse_circuit
    circuit = Circuit()
    change_to_z_basis = Circuit()
    change_to_original_basis = Circuit()
    cnot_seq = Circuit()
    prev_qubit = None
    highest_target_qubit = None

    for qubit, pauli in pauli_string.items():
        if pauli == X:
            change_to_z_basis.append(
                [H(qubit)], strategy=InsertStrategy.EARLIEST)
            change_to_original_basis.append(
                [H(qubit)], strategy=InsertStrategy.EARLIEST)

        elif pauli == Y:
            RX = Rx(np.pi/2.0)
            change_to_z_basis.append(
                [RX(qubit)], strategy=InsertStrategy.EARLIEST)
            RX = inverse(RX)
            change_to_original_basis.append(
                [RX(qubit)], strategy=InsertStrategy.EARLIEST)

        if prev_qubit is not None:
            cnot_seq.append([CNOT(prev_qubit, qubit)],
                            strategy=InsertStrategy.EARLIEST)

        prev_qubit = qubit
        highest_target_qubit = qubit

    circuit += change_to_z_basis
    circuit += cnot_seq
    RZ = Rz(2.0 * pauli_string.coefficient *
            param)
    circuit.append([RZ(highest_target_qubit)],
                   strategy=InsertStrategy.EARLIEST)
    circuit += reverse_circuit_operations(cnot_seq)
    circuit += change_to_original_basis

    return circuit