def test_simplify_circuit_exponents_with_non_self_inverse_gates(): qreg = LineQubit.range(2) # Make a circuit with gates which are not self-inverse circuit = Circuit([S.on(qreg[0]), T.on(qreg[1])]) inverse_circuit = cirq.inverse(circuit) inverse_repr = inverse_circuit.__repr__() inverse_qasm = inverse_circuit._to_qasm_output().__str__() # Simplify the circuit (it should not change this circuit) _simplify_circuit_exponents(inverse_circuit) # Check inverse_circuit did not change simplified_repr = inverse_circuit.__repr__() simplified_qasm = inverse_circuit._to_qasm_output().__str__() assert simplified_repr == inverse_repr assert simplified_qasm == inverse_qasm
def test_comments(): parser = QasmParser() parsed_qasm = parser.parse( """ //this is the format OPENQASM 2.0; // this is some other comment include "qelib1.inc"; // and something at the end of the file // multiline """ ) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
def exponentiation_circuit(param): circuit = Circuit() if is_constant(pauli_string): PHASE = ZPowGate(exponent=(-param * coeff)/np.pi) circuit.append([X(GridQubit(0, 0))], strategy=InsertStrategy.EARLIEST) circuit.append([PHASE(GridQubit(0, 0))], strategy=InsertStrategy.EARLIEST) circuit.append([X(GridQubit(0, 0))], strategy=InsertStrategy.EARLIEST) circuit.append([PHASE(GridQubit(0, 0))], strategy=InsertStrategy.EARLIEST) elif is_zero(pauli_string): pass else: circuit += exponentiate_general_case(pauli_string, param) return circuit
def test_multiple_creg_declaration(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; creg a_classical_register [1337]; qreg a_quantum_register [1337]; creg c[42]; """ parser = QasmParser() parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat is True assert parsed_qasm.qelib1Include is True ct.assert_same_circuits(parsed_qasm.circuit, Circuit()) assert parsed_qasm.qregs == {'a_quantum_register': 1337} assert parsed_qasm.cregs == {'a_classical_register': 1337, 'c': 42}
def test_to_from_braket_common_two_qubit_gates(common_gate): """These gates should stay the same (i.e., not get decomposed) when converting Cirq -> Braket -> Cirq. """ cirq_circuit = Circuit(common_gate.on(*LineQubit.range(2))) test_circuit = from_braket(to_braket(cirq_circuit)) testing.assert_allclose_up_to_global_phase( protocols.unitary(test_circuit), protocols.unitary(cirq_circuit), atol=1e-7, ) # Cirq AAPowGate has a different global phase than braket AA which gets # lost in translation. Here, AA = XX, YY, or ZZ. if not isinstance(common_gate, (ops.XXPowGate, ops.YYPowGate, ops.ZZPowGate)): assert _equal(test_circuit, cirq_circuit, require_qubit_equality=True)
def test_symbolic_gate(self): sym_circuit = Circuit() qubits = [GridQubit(i, j) for i in range(3) for j in range(3)] gate = GlobalPhaseGate(sympy.Symbol("rad")) sym_circuit.append(gate.on(qubits[0])) print(sym_circuit) rad_list = np.random.rand(10) * 5 for rad in rad_list: simulator = Simulator() circuit = cirq.resolve_parameters(sym_circuit, {"rad": rad}) result = simulator.simulate(circuit) self.assertTrue( np.allclose(result.final_state, np.exp(1.0j * rad * np.pi) * np.array([1, 0])))
def test_aqt_sampler_empty_circuit(): num_points = 10 max_angle = np.pi repetitions = 1000 num_qubits = 4 device, _qubits = get_aqt_device(num_qubits) sampler = AQTSamplerLocalSimulator() sampler.simulate_ideal = True circuit = Circuit(device=device) sweep = study.Linspace(key='theta', start=0.1, stop=max_angle / np.pi, length=num_points) with pytest.raises(RuntimeError): _results = sampler.run_sweep(circuit, params=sweep, repetitions=repetitions)
def test_ms_crosstalk_n_noise(): num_qubits = 4 noise_mod = AQTNoiseModel() device, qubits = get_aqt_device(num_qubits) circuit = Circuit(device=device) circuit.append(XX(qubits[1], qubits[2]) ** 0.5) for moment in circuit.moments: noisy_moment = noise_mod.noisy_moment(moment, qubits) assert noisy_moment == [ (cirq.XX ** 0.5).on(cirq.LineQubit(1), cirq.LineQubit(2)), cirq.depolarize(p=0.01).on(cirq.LineQubit(1)), cirq.depolarize(p=0.01).on(cirq.LineQubit(2)), (cirq.XX ** 0.015).on(cirq.LineQubit(1), cirq.LineQubit(0)), (cirq.XX ** 0.015).on(cirq.LineQubit(1), cirq.LineQubit(3)), (cirq.XX ** 0.015).on(cirq.LineQubit(2), cirq.LineQubit(0)), (cirq.XX ** 0.015).on(cirq.LineQubit(2), cirq.LineQubit(3)), ]
def expectation(all_qubits_in_circuit, cirq_circuit, cirq_pauli_sum): """ Computes the expectation value of `cirq_pauli_sum` over the distribution generated from `cirq_circuit`. The expectation value is calculated by calculating <psi|O|psi> Parameters --------- all_qubits_in_circuit : (list) list of all qubits in `cirq_circuit` cirq_circuit : (Circuit) represents the paramterized circuit for the ansatz cirq_pauli_sum : (CirqPauliSum or ndarray) CirqPauliSum representing the Pauli operator for which the expectation value is to be calculated or a numpy matrix representing the Hamiltonian tensored up to the appropriate size. Returns ------- expectation.real : (float) represents the expectation value of cirq_pauli_sum given the distribution generated from `cirq_circuit`. """ if isinstance(cirq_pauli_sum, np.ndarray): simulator = Simulator() simulation_result = simulator.simulate(cirq_circuit) cirq_circuit_amplitudes = simulation_result.final_state cirq_circuit_amplitudes = np.reshape( cirq_circuit_amplitudes, (-1, 1)) average_exp = np.conj(cirq_circuit_amplitudes).T.dot( cirq_pauli_sum.dot(cirq_circuit_amplitudes)).real return average_exp else: operator_circuits = [] operator_coeffs = [] for p_string in cirq_pauli_sum.pauli_strings: op_circuit = Circuit() for qubit, pauli in p_string.items(): gate = pauli op_circuit.append( [gate(qubit)], strategy=InsertStrategy.EARLIEST) operator_circuits.append(op_circuit) operator_coeffs.append(p_string.coefficient) result_overlaps = VQE.calculate_expectation( all_qubits_in_circuit, cirq_circuit, operator_circuits) result_overlaps = list(result_overlaps) expectation = sum( list(map(lambda x: x[0]*x[1], zip(result_overlaps, operator_coeffs)))) return expectation.real
def test_depolarizing_representation_with_choi(gate: Gate, noise: float): """Tests the representation by comparing exact Choi matrices.""" qreg = LineQubit.range(gate.num_qubits()) ideal_choi = _operation_to_choi(gate.on(*qreg)) op_rep = represent_operation_with_global_depolarizing_noise( Circuit(gate.on(*qreg)), noise, ) choi_components = [] for noisy_op, coeff in op_rep.basis_expansion.items(): implementable_circ = noisy_op.circuit() # Apply noise after each sequence. # NOTE: noise is not applied after each operation. depolarizing_op = DepolarizingChannel(noise, len(qreg))(*qreg) implementable_circ.append(depolarizing_op) sequence_choi = _circuit_to_choi(implementable_circ) choi_components.append(coeff * sequence_choi) combination_choi = np.sum(choi_components, axis=0) assert np.allclose(ideal_choi, combination_choi, atol=10 ** -6)
def simulate_samples(self, repetitions: int) -> study.Result: """Samples the circuit Args: repetitions: Number of times the circuit is simulated Returns: Result from Cirq.Simulator """ if self.simulate_ideal: noise_model = devices.NO_NOISE else: noise_model = AQTNoiseModel() if self.circuit == Circuit(): raise RuntimeError('simulate ideal called without a valid circuit') sim = DensityMatrixSimulator(noise=noise_model) result = sim.run(self.circuit, repetitions=repetitions) return result
def represent_operations_in_circuit_with_local_depolarizing_noise( ideal_circuit: QPROGRAM, noise_level: float ) -> List[OperationRepresentation]: """Iterates over all unique operations of the input ``ideal_circuit`` and, for each of them, generates the corresponding quasi-probability representation (linear combination of implementable noisy operations). This function assumes that the tensor product of ``k`` single-qubit depolarizing channels affects each implemented operation, where ``k`` is the number of qubits associated to the operation. This function internally calls :func:`represent_operation_with_local_depolarizing_noise` (more details about the quasi-probability representation can be found in its docstring). Args: ideal_circuit: The ideal circuit, whose ideal operations should be represented. noise_level: The (gate-independent) depolarizing noise level. Returns: The list of quasi-probability representations associated to the operations of the input ``ideal_circuit``. .. note:: Measurement gates are ignored (not represented). .. note:: The returned representations are always defined in terms of Cirq circuits, even if the input is not a ``cirq.Circuit``. """ circ, _ = convert_to_mitiq(ideal_circuit) representations = [] for op in set(circ.all_operations()): if is_measurement(op): continue representations.append( represent_operation_with_local_depolarizing_noise( Circuit(op), noise_level, ) ) return representations
def test_aqt_sampler_sim(): theta = sympy.Symbol('theta') num_points = 10 max_angle = np.pi repetitions = 1000 num_qubits = 4 device, qubits = get_aqt_device(num_qubits) sampler = AQTSamplerLocalSimulator() sampler.simulate_ideal = True circuit = Circuit(X(qubits[3])**theta, device=device) sweep = study.Linspace(key='theta', start=0.1, stop=max_angle / np.pi, length=num_points) results = sampler.run_sweep(circuit, params=sweep, repetitions=repetitions) excited_state_probs = np.zeros(num_points) for i in range(num_points): excited_state_probs[i] = np.mean(results[i].measurements['m']) assert excited_state_probs[-1] == 0.25
def get_single_qubit_gate_layer(self, params): single_qubit_gate_layer = Circuit() alpha = params[0] beta = params[1] gamma = params[2] single_qubit_gate = np.array( [[ np.exp(complex(0, beta)) * np.cos(alpha), np.exp(complex(0, gamma)) * np.sin(alpha) ], [ -1 * np.exp(complex(0, -1 * gamma)) * np.sin(alpha), np.exp(complex(0, -1 * beta)) * np.cos(alpha) ]]) G = SingleQubitMatrixGate(single_qubit_gate) for qubit in self.qubits: single_qubit_gate_layer.append([G(qubit)], strategy=InsertStrategy.EARLIEST) return single_qubit_gate_layer
def generate_circuit_from_list(self, json_string: str): """Generates a list of cirq operations from a json string. The default behavior is to add a measurement to any qubit at the end of the circuit as there are no measurements defined in the AQT API. Args: json_string: json that specifies the sequence """ self.circuit = Circuit() json_obj = json.loads(json_string) for gate_list in json_obj: gate = gate_list[0] angle = gate_list[1] qubits = [self.qubit_list[i] for i in gate_list[2]] self.circuit.append(gate_dict[gate].on(*qubits)**angle) # TODO: Better solution for measurement at the end. Issue #2199 self.circuit.append( ops.measure(*[qubit for qubit in self.qubit_list], key='m'))
def __init__(self, num_qubits: int, circuit: Circuit = Circuit(), simulate_ideal: bool = False, noise_dict: Union[dict, None] = None): """Initializes the AQT simulator Args: num_qubits: Number of qubits circuit: Optional, circuit to be simulated. Last moment needs to be a measurement over all qubits with key 'm' simulate_ideal: If True, an ideal circuit will be simulated """ self.circuit = circuit self.num_qubits = num_qubits self.qubit_list = LineQubit.range(num_qubits) if noise_dict is None: noise_dict = get_default_noise_dict() self.noise_dict = noise_dict self.simulate_ideal = simulate_ideal
def scale_parameters( circ: Circuit, scale_factor: float, sigma: float, seed: Optional[int] = None, ) -> Circuit: """Adds parameter noise to a circuit with level noise. This adds noise to the actual parameter instead of adding an parameter channel. Args: circ: The quantum program as a Cirq circuit object. All measurements should be in the last moment of the circuit. scale_factor: Amount to scale the base noise level of parameters by. sigma: Base noise level (variance) in parameter rotations seed: random seed Returns: The input circuit with scaled rotation angles """ final_moments = [] noise = (scale_factor - 1) * sigma rng = np.random.RandomState(seed) for moment in circ: curr_moment = [] for op in moment.operations: gate = copy.deepcopy(op.gate) qubits = op.qubits if isinstance(gate, MeasurementGate): curr_moment.append(gate(*qubits)) else: assert isinstance(gate, EigenGate) base_gate = _get_base_gate(gate) param = gate.exponent * np.pi error = rng.normal(loc=0.0, scale=np.sqrt(noise)) new_param = param + error curr_moment.append( base_gate(exponent=new_param / np.pi)(*qubits) ) final_moments.append(Moment(curr_moment)) return Circuit(final_moments)
def test_extensions(): # We test that an extension is being applied, by created an incorrect # gate with an extension. class WrongH(CompositeGate): def default_decompose(self, qubits: Sequence[cirq.QubitId]) -> cirq.OP_TREE: return X(Q1) extensions = Extensions( desired_to_actual_to_wrapper={CompositeGate: { H: lambda e: WrongH() }}) circuit = Circuit() circuit.append([WrongH()(Q1)]) simulator = xmon_simulator.XmonSimulator() results = simulator.simulate(circuit, extensions=extensions) np.testing.assert_almost_equal(results.final_state, np.array([0, -1j]))
def test_scale_with_measurement(): """Tests that we ignore measurement gates. Test circuit: 0: ───H───T───@───M─── │ │ 1: ───H───M───┼───┼─── │ │ 2: ───H───────X───M─── """ qreg = LineQubit.range(3) circ = Circuit( [ops.H.on_each(qreg)], [ops.T.on(qreg[0])], [ops.measure(qreg[1])], [ops.CNOT.on(qreg[0], qreg[2])], [ops.measure(qreg[0], qreg[2])], ) scaled = scale_parameters(circ, scale_factor=1, sigma=0.001) assert _equal(circ, scaled)
def qubit_ops_to_circuit(ops: 'QubitOperator', qpu: List[LineQubit]) -> 'Circuit': """Generate a circuit that can be run on a Cirq simulator from the ops passed Args: ops (Qubit Operator) - a product of operations to compile into a circuit qpu (Qid) - the quantum processing unit that this circuit will be run on Returns: (circuit) - returns a circuit to run in cirq """ gates = [] for operation in ops: gate_type = operation[1] qubit = qpu[operation[0]] gates.append(qubit_op_to_gate(gate_type, qubit)) moment = [Moment(gates)] return Circuit(moment)
def test_r_gate(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[1]; r(pi, pi / 2.0) q[0]; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') expected_circuit = Circuit() expected_circuit.append(QasmUGate(1.0, 0.0, 0.0)(q0)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 1}
def scale_parameters( circuit: QPROGRAM, scale_factor: float, base_variance: float, seed: Optional[int] = None, ) -> Circuit: """Applies parameter-noise scaling to the input circuit, assuming that each gate has the same base level of noise. Args: circuit: The circuit to scale as a QPROGRAM. All measurements should be in the last moment of the circuit. scale_factor: The amount to scale the base noise level by. base_variance: The base level (variance) of parameter noise, assumed to be the same for each gate of the circuit. seed: Optional seed for random number generator. Returns: The parameter noise scaled circuit. """ final_moments = [] noise = (scale_factor - 1) * base_variance rng = np.random.RandomState(seed) for moment in circuit: curr_moment = [] for op in moment.operations: # type: ignore gate = copy.deepcopy(op.gate) qubits = op.qubits if isinstance(gate, MeasurementGate): curr_moment.append(gate(*qubits)) else: assert isinstance(gate, EigenGate) base_gate = _get_base_gate(gate) param = gate.exponent * np.pi error = rng.normal(loc=0.0, scale=np.sqrt(noise)) new_param = param + error curr_moment.append( base_gate(exponent=new_param / np.pi)(*qubits)) final_moments.append(Moment(curr_moment)) return Circuit(final_moments)
def _generate_parameter_calibration_circuit(qubits: List[Qid], depth: int, gate: EigenGate) -> Circuit: """Generates a circuit which should be the identity. Given a rotation gate R(param), it applies R(2 * pi / depth) depth times, resulting in R(2*pi). Requires that the gate is periodic in 2*pi. Args: qubits: A list of qubits. depth: The length of the circuit to create. gate: The base gate to apply several times, must be periodic in 2*pi. Returns: A parameter calibration circuit that can be used for estimating the parameter noise of the input gate. """ num_qubits = gate().num_qubits() if num_qubits != len(qubits): raise CircuitMismatchException( "Number of qubits does not match domain size of gate.") return Circuit( gate(exponent=2 * np.pi / depth).on(*qubits) for _ in range(depth))
def test_expressions(expr: str): qasm = f"""OPENQASM 2.0; qreg q[1]; U({expr}, 2 * pi, pi / 2.0) q[0]; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') expected_circuit = Circuit() expected_circuit.append(QasmUGate(float(sympy.sympify(expr)) / np.pi, 2.0, 1 / 2.0)(q0)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert not parsed_qasm.qelib1Include ct.assert_allclose_up_to_global_phase( cirq.unitary(parsed_qasm.circuit), cirq.unitary(expected_circuit), atol=1e-10 ) assert parsed_qasm.qregs == {'q': 1}
def test_three_qubit_gates(qasm_gate: str, cirq_gate: cirq.TwoQubitGate): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q1[2]; qreg q2[2]; qreg q3[2]; {0} q1[0], q1[1], q2[0]; {0} q1, q2[0], q3[0]; {0} q1, q2, q3; """.format( qasm_gate ) parser = QasmParser() q1_0 = cirq.NamedQubit('q1_0') q1_1 = cirq.NamedQubit('q1_1') q2_0 = cirq.NamedQubit('q2_0') q2_1 = cirq.NamedQubit('q2_1') q3_0 = cirq.NamedQubit('q3_0') q3_1 = cirq.NamedQubit('q3_1') expected_circuit = Circuit() expected_circuit.append(cirq_gate(q1_0, q1_1, q2_0)) expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0)) expected_circuit.append(cirq_gate(q1_1, q2_0, q3_0)) expected_circuit.append(cirq_gate(q1_0, q2_0, q3_0)) expected_circuit.append(cirq_gate(q1_1, q2_1, q3_1)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q1': 2, 'q2': 2, 'q3': 2}
def test_from_braket_non_parameterized_single_qubit_gates(): braket_circuit = BKCircuit() instructions = [ Instruction(braket_gates.I(), target=0), Instruction(braket_gates.X(), target=1), Instruction(braket_gates.Y(), target=2), Instruction(braket_gates.Z(), target=3), Instruction(braket_gates.H(), target=0), Instruction(braket_gates.S(), target=1), Instruction(braket_gates.Si(), target=2), Instruction(braket_gates.T(), target=3), Instruction(braket_gates.Ti(), target=0), Instruction(braket_gates.V(), target=1), Instruction(braket_gates.Vi(), target=2), ] for instr in instructions: braket_circuit.add_instruction(instr) cirq_circuit = from_braket(braket_circuit) for i, op in enumerate(cirq_circuit.all_operations()): assert np.allclose( instructions[i].operator.to_matrix(), protocols.unitary(op) ) qreg = LineQubit.range(4) expected_cirq_circuit = Circuit( ops.I(qreg[0]), ops.X(qreg[1]), ops.Y(qreg[2]), ops.Z(qreg[3]), ops.H(qreg[0]), ops.S(qreg[1]), ops.S(qreg[2]) ** -1, ops.T(qreg[3]), ops.T(qreg[0]) ** -1, ops.X(qreg[1]) ** 0.5, ops.X(qreg[2]) ** -0.5, ) assert _equal(cirq_circuit, expected_cirq_circuit)
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 test_find_optimal_representation_depolarizing_two_qubit_gates(circ_type): """Test optimal representation agrees with a known analytic result.""" for ideal_gate, noise_level in product([CNOT, CZ], [0.1, 0.5]): q = LineQubit.range(2) ideal_op = Circuit(ideal_gate(*q)) implementable_circuits = [Circuit(ideal_op)] # Append two-qubit-gate with Paulis on one qubit for gate in [X, Y, Z]: implementable_circuits.append(Circuit([ideal_op, gate(q[0])])) implementable_circuits.append(Circuit([ideal_op, gate(q[1])])) # Append two-qubit gate with Paulis on both qubits for gate_a, gate_b in product([X, Y, Z], repeat=2): implementable_circuits.append( Circuit([ideal_op, gate_a(q[0]), gate_b(q[1])]) ) noisy_circuits = [ circ + Circuit(DepolarizingChannel(noise_level).on_each(*q)) for circ in implementable_circuits ] super_operators = [ choi_to_super(_circuit_to_choi(circ)) for circ in noisy_circuits ] # Define circuits with native types implementable_native = [ convert_from_mitiq(c, circ_type) for c in implementable_circuits ] ideal_op_native = convert_from_mitiq(ideal_op, circ_type) noisy_operations = [ NoisyOperation(ideal, real) for ideal, real in zip(implementable_native, super_operators) ] # Find optimal representation noisy_basis = NoisyBasis(*noisy_operations) rep = find_optimal_representation( ideal_op_native, noisy_basis, tol=1.0e-8 ) # Expected analytical result expected_rep = represent_operation_with_local_depolarizing_noise( ideal_op_native, noise_level, ) assert np.allclose(np.sort(rep.coeffs), np.sort(expected_rep.coeffs)) assert rep == expected_rep
def test_id_gate(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; id q; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') q1 = cirq.NamedQubit('q_1') expected_circuit = Circuit() expected_circuit.append(cirq.IdentityGate(num_qubits=1)(q0)) expected_circuit.append(cirq.IdentityGate(num_qubits=1)(q1)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}
def test_non_identity_scale_2q(): """Tests that when scale factor = 1, the circuit is the same. """ qreg = LineQubit.range(2) circ = Circuit([ops.CNOT.on(qreg[0], qreg[1])]) np.random.seed(42) stretch = 2 base_noise = 0.001 noises = np.random.normal(loc=0.0, scale=np.sqrt((stretch - 1) * base_noise), size=(1, )) np.random.seed(42) scaled = scale_parameters(circ, scale_factor=stretch, sigma=base_noise, seed=42) result = [] for moment in scaled: for op in moment.operations: gate = deepcopy(op.gate) param = gate.exponent result.append(param * np.pi - np.pi) assert np.all(np.isclose(result - noises, 0))