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
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
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
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)
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
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
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
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)], )
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)
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)
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)
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
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
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)
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)
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
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
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