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_three_qubit_depolarizing_representation_error(): q0, q1, q2 = LineQubit.range(3) with pytest.raises(ValueError): represent_operation_with_global_depolarizing_noise( Circuit(CCNOT(q0, q1, q2)), 0.05, )
def test_prepare_gaussian_state(n_qubits, conserves_particle_number, occupied_orbitals, initial_state, atol=1e-5): qubits = LineQubit.range(n_qubits) if isinstance(initial_state, list): initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state) # Initialize a random quadratic Hamiltonian quad_ham = random_quadratic_hamiltonian( n_qubits, conserves_particle_number, real=False) quad_ham_sparse = get_sparse_operator(quad_ham) # Compute the energy of the desired state if occupied_orbitals is None: energy = quad_ham.ground_energy() else: orbital_energies, _, constant = ( quad_ham.diagonalizing_bogoliubov_transform()) energy = sum(orbital_energies[i] for i in occupied_orbitals) + constant # Get the state using a circuit simulation circuit = cirq.Circuit.from_ops( prepare_gaussian_state( qubits, quad_ham, occupied_orbitals, initial_state=initial_state)) state = circuit.apply_unitary_effect_to_state(initial_state) # Check that the result is an eigenstate with the correct eigenvalue numpy.testing.assert_allclose( quad_ham_sparse.dot(state), energy * state, atol=atol)
def test_aqt_device_wrong_op_str(): circuit = Circuit() q0, q1 = LineQubit.range(2) circuit.append(CNOT(q0, q1)**1.0) for op in circuit.all_operations(): with pytest.raises(ValueError): _result = get_op_string(op)
def _try_decompose_into_operations_and_qubits( val: Any ) -> Tuple[Optional[List['cirq.Operation']], Sequence['cirq.Qid'], Tuple[int, ...]]: """Returns the value's decomposition (if any) and the qubits it applies to. """ from cirq.protocols.decompose import (decompose_once, decompose_once_with_qubits) from cirq import LineQubit, Gate, Operation if isinstance(val, Gate): # Gates don't specify qubits, and so must be handled specially. qid_shape = qid_shape_protocol.qid_shape(val) qubits = LineQubit.range(len(qid_shape)) # type: Sequence[cirq.Qid] return decompose_once_with_qubits(val, qubits, None), qubits, qid_shape if isinstance(val, Operation): qid_shape = qid_shape_protocol.qid_shape(val) return decompose_once(val, None), val.qubits, qid_shape result = decompose_once(val, None) if result is not None: qubit_set = set() qid_shape_dict = defaultdict(lambda: 1) # type: Dict[cirq.Qid, int] for op in result: for level, q in zip(qid_shape_protocol.qid_shape(op), op.qubits): qubit_set.add(q) qid_shape_dict[q] = max(qid_shape_dict[q], level) qubits = sorted(qubit_set) return result, qubits, tuple(qid_shape_dict[q] for q in qubits) return None, (), ()
def test_biased_noise_representation_with_choi( gate: Gate, epsilon: float, eta: 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_local_biased_noise( Circuit(gate.on(*qreg)), epsilon, eta ) choi_components = [] # Define biased noise channel a = 1 - epsilon b = epsilon * (3 * eta + 1) / (3 * (eta + 1)) c = epsilon / (3 * (eta + 1)) mix = [ (a, unitary(I)), (b, unitary(Z)), (c, unitary(X)), (c, unitary(Y)), ] 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. biased_op = ops.MixedUnitaryChannel(mix).on_each(*qreg) implementable_circ.append(biased_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 test_two_qubit_representation_norm(gate: Gate, epsilon: float, eta: float): qreg = LineQubit.range(2) optimal_norm = two_qubit_biased_noise_overhead(epsilon, eta) norm = represent_operation_with_local_biased_noise( Circuit(gate(*qreg)), epsilon, eta ).norm assert np.isclose(optimal_norm, norm)
def test_mitigated_execute_with_cdr(circuit_type, fit_function, kwargs, random_state): circuit = random_x_z_cnot_circuit( LineQubit.range(2), n_moments=5, random_state=random_state, ) circuit = convert_from_mitiq(circuit, circuit_type) obs = Observable(PauliString("XZ"), PauliString("YY")) true_value = obs.expectation(circuit, simulate) noisy_value = obs.expectation(circuit, execute) cdr_executor = mitigate_executor( executor=execute, observable=obs, simulator=simulate, num_training_circuits=20, fraction_non_clifford=0.5, fit_function=fit_function, random_state=random_state, **kwargs, ) cdr_mitigated = cdr_executor(circuit) assert abs(cdr_mitigated - true_value) <= abs(noisy_value - true_value)
def test_from_braket_non_parameterized_two_qubit_gates(): braket_circuit = BKCircuit() instructions = [ Instruction(braket_gates.CNot(), target=[2, 3]), Instruction(braket_gates.Swap(), target=[3, 4]), Instruction(braket_gates.ISwap(), target=[2, 3]), Instruction(braket_gates.CZ(), target=(3, 4)), Instruction(braket_gates.CY(), target=(2, 3)), ] for instr in instructions: braket_circuit.add_instruction(instr) cirq_circuit = from_braket(braket_circuit) qreg = LineQubit.range(2, 5) expected_cirq_circuit = Circuit( ops.CNOT(*qreg[:2]), ops.SWAP(*qreg[1:]), ops.ISWAP(*qreg[:2]), ops.CZ(*qreg[1:]), ops.ControlledGate(ops.Y).on(*qreg[:2]), ) assert np.allclose( protocols.unitary(cirq_circuit), protocols.unitary(expected_cirq_circuit), )
def test_gate_type(): qreg = LineQubit.range(3) allowed_op = ops.H.on(qreg[0]) _get_base_gate(allowed_op.gate) with pytest.raises(GateTypeException): forbidden_op = CSWAP(qreg[0], qreg[1], qreg[2]) _get_base_gate(forbidden_op)
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 test_simplify_circuit_exponents_controlled_gate(): circuit = Circuit( ControlledGate(CNOT, num_controls=1).on(*LineQubit.range(3))) copy = circuit.copy() _simplify_circuit_exponents(circuit) assert _equal(circuit, copy)
def test_ffft_text_diagram(): qubits = LineQubit.range(8) circuit = cirq.Circuit(ffft(qubits), strategy=cirq.InsertStrategy.EARLIEST) assert circuit.to_text_diagram(transpose=True) == """ 0 1 2 3 4 5 6 7 │ │ │ │ │ │ │ │ 0↦0─1↦4───2↦1─3↦5───4↦2─5↦6───6↦3─7↦7 │ │ │ │ │ │ │ │ 0↦0─1↦2───2↦1─3↦3 0↦0─1↦2───2↦1─3↦3 │ │ │ │ │ │ │ │ F₀──F₀ F₀──F₀ F₀──F₀ F₀──F₀ │ │ │ │ │ │ │ │ 0↦0─1↦2───2↦1─3↦3 0↦0─1↦2───2↦1─3↦3 │ │ │ │ │ │ │ │ │ ω^0_4 │ ω^1_4 │ ω^0_4 │ ω^1_4 │ │ │ │ │ │ │ │ F₀──F₀ F₀──F₀ F₀──F₀ F₀──F₀ │ │ │ │ │ │ │ │ 0↦0─1↦2───2↦1─3↦3 0↦0─1↦2───2↦1─3↦3 │ │ │ │ │ │ │ │ 0↦0─1↦2───2↦4─3↦6───4↦1─5↦3───6↦5─7↦7 │ │ │ │ │ │ │ │ │ ω^0_8 │ ω^1_8 │ ω^2_8 │ ω^3_8 │ │ │ │ │ │ │ │ F₀──F₀ F₀──F₀ F₀──F₀ F₀──F₀ │ │ │ │ │ │ │ │ 0↦0─1↦4───2↦1─3↦5───4↦2─5↦6───6↦3─7↦7 │ │ │ │ │ │ │ │ """.strip()
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_non_identity_scale_1q(): """Tests that when scale factor = 1, the circuit is the same. """ qreg = LineQubit.range(3) circ = Circuit([ops.rx(np.pi * 1.0).on_each(qreg)], [ops.ry(np.pi * 1.0).on(qreg[0])]) 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=(4, )) 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))
def test_TwiddleGate_text_diagram(): qubit = LineQubit.range(1) circuit = cirq.Circuit(_TwiddleGate(2, 8).on(*qubit)) assert circuit.to_text_diagram(use_unicode_characters=False).strip() == """ 0: ---w^2_8--- """.strip()
def test_pop_measurements_and_add_measurements(): """Tests popping measurements from a circuit..""" # 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])], ) copy = deepcopy(circ) measurements = _pop_measurements(copy) correct = Circuit( [ops.H.on_each(qreg)], [ops.T.on(qreg[0])], [ops.CNOT.on(qreg[0], qreg[2])], ) assert _equal(copy, correct) _append_measurements(copy, measurements) assert _equal(copy, circ)
def test_two_qubit_representation_norm(gate: Gate, noise: float): qreg = LineQubit.range(2) optimal_norm = two_qubit_depolarizing_overhead(noise) norm = represent_operation_with_global_depolarizing_noise( Circuit(gate(*qreg)), noise, ).norm assert np.isclose(optimal_norm, norm)
def test_represent_operations_in_circuit_with_measurements( circuit_type: str, rep_function, ): """Tests measurements in circuit are ignored (not represented).""" q0, q1 = LineQubit.range(2) circ_mitiq = Circuit( X(q1), MeasurementGate(num_qubits=1)(q0), X(q1), MeasurementGate(num_qubits=1)(q0), ) circ = convert_from_mitiq(circ_mitiq, circuit_type) reps = rep_function(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 if isinstance(op.gate, MeasurementGate): assert not found else: assert found # Number of unique gates excluding measurement gates assert len(reps) == 1
def test_TwiddleGate_text_unicode_diagram(): qubit = LineQubit.range(1) circuit = cirq.Circuit(_TwiddleGate(2, 8).on(*qubit)) assert circuit.to_text_diagram().strip() == """ 0: ───ω^2_8─── """.strip()
def test_simple_pauli_deco_dict_CNOT(): """Tests that the _simple_pauli_deco_dict function returns a decomposition dicitonary which is consistent with a local depolarizing noise model. The channel acting on the state each qubit is assumed to be: D(rho) = = (1 - epsilon) rho + epsilon I/2 = (1 - p) rho + p/3 (X rho X + Y rho Y^dag + Z rho Z) """ # Deduce epsilon from BASE_NOISE epsilon = BASE_NOISE * 4.0 / 3.0 c_neg = -(1 / 4) * epsilon / (1 - epsilon) c_pos = 1 - 3 * c_neg qreg = LineQubit.range(2) # Get the decomposition of a CNOT gate deco = DECO_DICT[CNOT.on(*qreg)] # The first term of 'deco' corresponds to no error occurring first_coefficient, first_imp_seq = deco[0] assert np.isclose(c_pos * c_pos, first_coefficient) assert first_imp_seq == [CNOT.on(*qreg)] # The second term corresponds to a Pauli X error on one qubit second_coefficient, second_imp_seq = deco[1] assert np.isclose(c_pos * c_neg, second_coefficient) assert second_imp_seq == [CNOT.on(*qreg), X.on(qreg[0])] # The last term corresponds to two Pauli Z errors on both qubits last_coefficient, last_imp_seq = deco[-1] assert np.isclose(c_neg * c_neg, last_coefficient) assert last_imp_seq == [CNOT.on(*qreg), Z.on(qreg[0]), Z.on(qreg[1])]
def test_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])]) scaled = scale_parameters(circ, scale_factor=1, sigma=0.001) assert _equal(circ, scaled)
def test_identity_scale_1q(): """Tests that when scale factor = 1, the circuit is the same. """ qreg = LineQubit.range(3) circ = Circuit([ops.X.on_each(qreg)], [ops.Y.on(qreg[0])]) scaled = scale_parameters(circ, scale_factor=1, sigma=0.001) assert _equal(circ, scaled)
def test_sample_sequence_types(gate: Gate): num_qubits = gate.num_qubits() qreg = LineQubit.range(num_qubits) for _ in range(1000): imp_seq, sign, norm = sample_sequence(gate.on(*qreg), DECO_DICT) assert all([isinstance(op, Operation) for op in imp_seq]) assert sign in {1, -1} assert norm > 1
def generate_rb_circuits( n_qubits: int, num_cliffords: int, trials: int = 1, return_type: Optional[str] = None, ) -> List[QPROGRAM]: """Returns a list of randomized benchmarking circuits, i.e. circuits that are equivalent to the identity. Args: n_qubits: The number of qubits. Can be either 1 or 2. num_cliffords: The number of Clifford group elements in the random circuits. This is proportional to the depth per circuit. trials: The number of random circuits at each num_cfd. return_type: String which specifies the type of the returned circuits. See the keys of ``mitiq.SUPPORTED_PROGRAM_TYPES`` for options. If ``None``, the returned circuits have type ``cirq.Circuit``. Returns: A list of randomized benchmarking circuits. """ if n_qubits not in (1, 2): raise ValueError( "Only generates RB circuits on one or two " f"qubits not {n_qubits}." ) qubits = LineQubit.range(n_qubits) cliffords = _single_qubit_cliffords() if n_qubits == 1: c1 = cliffords.c1_in_xy cfd_mat_1q = cast( np.ndarray, [_gate_seq_to_mats(gates) for gates in c1] ) circuits = [ _random_single_q_clifford(qubits[0], num_cliffords, c1, cfd_mat_1q) for _ in range(trials) ] else: cfd_matrices = _two_qubit_clifford_matrices( qubits[0], qubits[1], cliffords, ) circuits = [ _random_two_q_clifford( qubits[0], qubits[1], num_cliffords, cfd_matrices, cliffords, ) for _ in range(trials) ] return_type = "cirq" if not return_type else return_type return [convert_from_mitiq(circuit, return_type) for circuit in circuits]
def test_generate_parameter_calibration_circuit_failure(): """Tests that parameter calibration circuit generation fails because there are too many qubits""" n_qubits = 3 qubits = LineQubit.range(n_qubits) depth = 10 # Should raise exception because too many qubits with pytest.raises(CircuitMismatchException): _generate_parameter_calibration_circuit(qubits, depth, ZPowGate)
def test_F0Gate_text_unicode_diagram(): qubits = LineQubit.range(2) circuit = cirq.Circuit(_F0Gate().on(*qubits)) assert circuit.to_text_diagram().strip() == """ 0: ───F₀─── │ 1: ───F₀─── """.strip()
def test_F0Gate_text_diagram(): qubits = LineQubit.range(2) circuit = cirq.Circuit(_F0Gate().on(*qubits)) assert circuit.to_text_diagram(use_unicode_characters=False).strip() == """ 0: ---F0--- | 1: ---F0--- """.strip()
def test_range(): assert LineQubit.range(0) == [] assert LineQubit.range(1) == [LineQubit(0)] assert LineQubit.range(2) == [LineQubit(0), LineQubit(1)] assert LineQubit.range(5) == [ LineQubit(0), LineQubit(1), LineQubit(2), LineQubit(3), LineQubit(4), ] assert LineQubit.range(0, 0) == [] assert LineQubit.range(0, 1) == [LineQubit(0)] assert LineQubit.range(1, 4) == [LineQubit(1), LineQubit(2), LineQubit(3)] assert LineQubit.range(3, 1, -1) == [LineQubit(3), LineQubit(2)] assert LineQubit.range(3, 5, -1) == [] assert LineQubit.range(1, 5, 2) == [LineQubit(1), LineQubit(3)]
def test_ffft_multi_fermionic_mode(n, initial): initial_state = _multi_fermionic_mode_base_state(n, *initial) expected_state = _fourier_transform_multi_fermionic_mode(n, *initial) qubits = LineQubit.range(n) circuit = cirq.Circuit(ffft(qubits), strategy=cirq.InsertStrategy.EARLIEST) state = circuit.final_wavefunction(initial_state, qubits_that_should_be_present=qubits) assert np.allclose(state, expected_state, rtol=0.0)
def test_TwiddleGate_transform(k, n, qubit, initial, expected): qubits = LineQubit.range(2) initial_state = _single_fermionic_modes_state(initial) expected_state = _single_fermionic_modes_state(expected) circuit = cirq.Circuit(_TwiddleGate(k, n).on(qubits[qubit])) state = circuit.final_wavefunction(initial_state, qubits_that_should_be_present=qubits) assert np.allclose(state, expected_state, rtol=0.0)
from cirq import LineQubit print(LineQubit.range(6))