def test_transform_qregs_two_qubit_ops(new_reg_sizes): nqubits = sum(new_reg_sizes) circ = to_qiskit( cirq.testing.random_circuit( nqubits, n_moments=5, op_density=1, random_state=1 ) ) orig = circ.copy() new_qregs = [qiskit.QuantumRegister(s) for s in new_reg_sizes] _transform_registers(circ, new_qregs=new_qregs) assert circ.qregs == new_qregs assert circ.cregs == orig.cregs assert _equal(from_qiskit(circ), from_qiskit(orig))
def test_add_qiskit_noisy_operations(): qreg = qiskit.QuantumRegister(1) ideal = qiskit.QuantumCircuit(qreg) _ = ideal.x(qreg) real = np.random.rand(4, 4) noisy_op1 = NoisyOperation(ideal, real) noisy_op2 = NoisyOperation(ideal, real) noisy_op = noisy_op1 + noisy_op2 correct = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))] * 2) assert _equal(noisy_op._ideal, correct, require_qubit_equality=False) assert np.allclose(noisy_op.ideal_unitary, np.identity(2)) assert np.allclose(noisy_op.real_matrix, real @ real)
def test_extend_to_single_qubit(real): qbit, qreg = cirq.LineQubit(0), cirq.LineQubit.range(1, 10) ideal = cirq.Z.on(qbit) noisy_op_on_one_qubit = NoisyOperation.from_cirq(ideal, real) noisy_ops_on_all_qubits = noisy_op_on_one_qubit.extend_to(qreg) assert isinstance(noisy_ops_on_all_qubits, list) assert len(noisy_ops_on_all_qubits) == 10 for op in noisy_ops_on_all_qubits: assert _equal(op.ideal_circuit(), cirq.Circuit(ideal)) assert np.allclose(op.ideal_unitary, cirq.unitary(ideal)) if real is not None: assert np.allclose(op.real_matrix, real)
def test_circuit_equality_equal_measurement_keys_terminal_measurements( require_measurement_equality, ): base_circuit = cirq.testing.random_circuit( qubits=5, n_moments=10, op_density=0.99, random_state=1 ) qreg = list(base_circuit.all_qubits()) circ1 = deepcopy(base_circuit) circ1.append(cirq.measure(q, key="z") for q in qreg) circ2 = deepcopy(base_circuit) circ2.append(cirq.measure(q, key="z") for q in qreg) assert _equal( circ1, circ2, require_measurement_equality=require_measurement_equality )
def test_transform_cregs(nbits, with_ops, measure): qreg = qiskit.QuantumRegister(nbits) creg = qiskit.ClassicalRegister(nbits) circ = qiskit.QuantumCircuit(qreg, creg) if with_ops: circ.h(qreg) if measure: circ.measure(qreg, creg) orig = circ.copy() new_cregs = [qiskit.ClassicalRegister(1) for _ in range(nbits)] _transform_registers(circ, new_cregs=new_cregs) assert circ.cregs == new_cregs assert circ.qregs == orig.qregs assert _equal(from_qiskit(circ), from_qiskit(orig))
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_init_with_op_tree(): qreg = cirq.LineQubit.range(2) ideal_ops = [cirq.H.on(qreg[0]), cirq.CNOT.on(*qreg)] real = np.zeros(shape=(16, 16)) noisy_op = NoisyOperation.from_cirq(ideal_ops, real) assert isinstance(noisy_op._circuit, cirq.Circuit) assert _equal( noisy_op.circuit(), cirq.Circuit(ideal_ops), require_qubit_equality=True, ) assert set(noisy_op.qubits) == set(qreg) assert np.allclose(noisy_op.ideal_unitary, cirq.unitary(cirq.Circuit(ideal_ops))) assert np.allclose(noisy_op.channel_matrix, real) assert noisy_op.channel_matrix is not real
def test_sample_circuit_random_state(seed, seed_type): decomposition = _simple_pauli_deco_dict(0.5) if isinstance(seed_type, np.random.RandomState): seed = np.random.RandomState(seed) circuit, sign, norm = sample_circuit(twoq_circ, decomposition, random_state=seed) for _ in range(20): if isinstance(seed_type, np.random.RandomState): seed = np.random.RandomState(seed) new_circuit, new_sign, new_norm = sample_circuit(twoq_circ, decomposition, random_state=seed) assert _equal(new_circuit, circuit) assert new_sign == sign assert np.isclose(new_norm, norm)
def test_init_with_pyquil_program(): circ = pyquil.Program(pyquil.gates.H(0), pyquil.gates.CNOT(0, 1)) cirq_qreg = cirq.LineQubit.range(2) cirq_circ = cirq.Circuit(cirq.H.on(cirq_qreg[0]), cirq.CNOT.on(*cirq_qreg)) real = np.zeros(shape=(16, 16)) noisy_op = NoisyOperation(circ, real) assert isinstance(noisy_op._ideal, cirq.Circuit) assert _equal(noisy_op._ideal, cirq_circ) assert noisy_op.ideal_circuit() == circ assert noisy_op._native_ideal == circ assert noisy_op._native_type == "pyquil" assert np.allclose(noisy_op.ideal_unitary, cirq.unitary(cirq_circ)) assert np.allclose(noisy_op.real_matrix, real) assert noisy_op.real_matrix is not real
def test_add_simple(): circuit1 = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))]) circuit2 = cirq.Circuit([cirq.Y.on(cirq.NamedQubit("Q"))]) super_op1 = np.random.rand(4, 4) super_op2 = np.random.rand(4, 4) noisy_op1 = NoisyOperation(circuit1, super_op1) noisy_op2 = NoisyOperation(circuit2, super_op2) noisy_op = noisy_op1 + noisy_op2 correct = cirq.Circuit( [cirq.X.on(cirq.NamedQubit("Q")), cirq.Y.on(cirq.NamedQubit("Q"))], ) assert _equal(noisy_op._circuit, correct, require_qubit_equality=True) assert np.allclose(noisy_op.channel_matrix, super_op2 @ super_op1)
def test_transform_qregs_random_circuit(new_reg_sizes, measure): nbits = sum(new_reg_sizes) circ = to_qiskit( cirq.testing.random_circuit( nbits, n_moments=5, op_density=1, random_state=10 ) ) creg = qiskit.ClassicalRegister(nbits) circ.add_register(creg) if measure: circ.measure(circ.qregs[0], creg) orig = circ.copy() new_qregs = [qiskit.QuantumRegister(s) for s in new_reg_sizes] _transform_registers(circ, new_qregs=new_qregs) assert circ.qregs == new_qregs assert _equal(from_qiskit(circ), from_qiskit(orig))
def test_observable_measure_in_needs_one_circuit_x(): pauli1 = PauliString(spec="XI") pauli2 = PauliString(spec="IX") pauli3 = PauliString(spec="XX") obs = Observable(pauli1, pauli2, pauli3) qubits = cirq.LineQubit.range(2) circuit = cirq.testing.random_circuit(qubits, 3, 1, random_state=1) measures_obs_circuits = obs.measure_in(circuit) assert len(measures_obs_circuits) == 1 expected = circuit + xrotation.on_each(*qubits) + cirq.measure(*qubits) assert _equal( measures_obs_circuits[0], expected, require_qubit_equality=True, require_measurement_equality=True, )
def test_convert_with_multiple_barriers(as_qasm): """Tests converting a Qiskit circuit with barriers to a Cirq circuit.""" n = 1 num_ops = 10 qreg = qiskit.QuantumRegister(n) qiskit_circuit = qiskit.QuantumCircuit(qreg) for _ in range(num_ops): qiskit_circuit.h(qreg) qiskit_circuit.barrier() if as_qasm: cirq_circuit = from_qasm(qiskit_circuit.qasm()) else: cirq_circuit = from_qiskit(qiskit_circuit) qbit = cirq.LineQubit(0) correct = cirq.Circuit(cirq.ops.H.on(qbit) for _ in range(num_ops)) assert _equal(cirq_circuit, correct)
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 test_mirror_circuit_seeding(seed): nlayers = 5 two_qubit_gate_prob = 0.4 connectivity_graph = nx.complete_graph(5) circuit, _ = mirror_circuits.generate_mirror_circuit(nlayers, two_qubit_gate_prob, connectivity_graph, seed=seed) for _ in range(5): circ, _ = mirror_circuits.generate_mirror_circuit(nlayers, two_qubit_gate_prob, connectivity_graph, seed=seed) assert _equal( circuit, circ, require_qubit_equality=True, require_measurement_equality=True, )
def test_sample_sequence_cirq_random_state(seed): circuit = cirq.Circuit(cirq.H.on(cirq.LineQubit(0))) rep = OperationRepresentation( ideal=circuit, basis_expansion={ NoisyOperation.from_cirq(circuit=cirq.X): 0.5, NoisyOperation.from_cirq(circuit=cirq.Z): -0.5, }, ) sequences, signs, norm = sample_sequence( circuit, [rep], random_state=np.random.RandomState(seed)) for _ in range(20): new_sequences, new_signs, new_norm = sample_sequence( circuit, [rep], random_state=np.random.RandomState(seed)) assert _equal(new_sequences[0], sequences[0]) assert new_signs[0] == signs[0] assert np.isclose(new_norm, norm)
def test_observable_measure_in_needs_two_circuits(): obs = Observable(PauliString(spec="X"), PauliString(spec="Z")) q = cirq.LineQubit(0) circuit = cirq.Circuit(cirq.H.on(q)) measures_obs_circuits = sorted(obs.measure_in(circuit), key=len) assert len(measures_obs_circuits) == 2 expected_circuits = [ circuit + cirq.measure(q), circuit + xrotation.on(q) + cirq.measure(q), ] for expected, measured in zip(expected_circuits, measures_obs_circuits): assert _equal( measured, expected, require_qubit_equality=True, require_measurement_equality=True, )
def test_unknown_real_matrix(): qreg = qiskit.QuantumRegister(2) circ = qiskit.QuantumCircuit(qreg) _ = circ.h(qreg[0]) _ = circ.cnot(*qreg) cirq_qreg = cirq.LineQubit.range(2) cirq_circ = cirq.Circuit(cirq.H.on(cirq_qreg[0]), cirq.CNOT.on(*cirq_qreg)) noisy_op = NoisyOperation(circ) assert isinstance(noisy_op._ideal, cirq.Circuit) assert _equal(noisy_op._ideal, cirq_circ) assert noisy_op.ideal_circuit() == circ assert noisy_op._native_ideal == circ assert noisy_op._native_type == "qiskit" assert np.allclose(noisy_op.ideal_unitary, cirq.unitary(cirq_circ)) with pytest.raises(ValueError, match="Real matrix is unknown."): _ = noisy_op.real_matrix
def test_init_with_qiskit_circuit(): qreg = qiskit.QuantumRegister(2) circ = qiskit.QuantumCircuit(qreg) _ = circ.h(qreg[0]) _ = circ.cnot(*qreg) cirq_qreg = cirq.LineQubit.range(2) cirq_circ = cirq.Circuit(cirq.H.on(cirq_qreg[0]), cirq.CNOT.on(*cirq_qreg)) real = np.zeros(shape=(16, 16)) noisy_op = NoisyOperation(circ, real) assert isinstance(noisy_op._ideal, cirq.Circuit) assert _equal(noisy_op._ideal, cirq_circ) assert noisy_op.ideal_circuit() == circ assert noisy_op._native_ideal == circ assert noisy_op._native_type == "qiskit" assert np.allclose(noisy_op.ideal_unitary, cirq.unitary(cirq_circ)) assert np.allclose(noisy_op.real_matrix, real) assert noisy_op.real_matrix is not real
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 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 test_sample_circuit_with_seed(): circ = cirq.Circuit([cirq.X.on(cirq.LineQubit(0)) for _ in range(10)]) rep = OperationRepresentation( ideal=cirq.Circuit(cirq.X.on(cirq.LineQubit(0))), basis_expansion={ NoisyOperation.from_cirq(cirq.Z): 1.0, NoisyOperation.from_cirq(cirq.X): -1.0, }, ) expected_circuits, expected_signs, expected_norm = sample_circuit( circ, [rep], random_state=4) # Check we're not sampling the same operation every call to sample_sequence assert len(set(expected_circuits[0].all_operations())) > 1 for _ in range(10): sampled_circuits, sampled_signs, sampled_norm = sample_circuit( circ, [rep], random_state=4) assert _equal(sampled_circuits[0], expected_circuits[0]) assert sampled_signs[0] == expected_signs[0] assert sampled_norm == expected_norm
def test_pauli_measure_in_circuit(support, circuit_type): pauli = PauliString(spec="XYZ", support=support, coeff=-0.5) names = ("0th", "1st", "2nd", "3rd", "4th", "5th") qreg = [cirq.NamedQubit(name) for name in names] base_circuit = cirq.Circuit(cirq.H.on_each(qreg)) if circuit_type == "cirq": def convert(circ): return circ elif circuit_type == "qiskit": convert = mitiq_qiskit.to_qiskit elif circuit_type == "pyquil": convert = mitiq_pyquil.to_pyquil circuit = convert(base_circuit) measured = pauli.measure_in(circuit) qreg = [cirq.NamedQubit(name) for name in names] expected = cirq.Circuit( # Original circuit. base_circuit.all_operations(), # Basis rotations. xrotation.on(qreg[support[0]]), yrotation.on(qreg[support[1]]), # Measurements. cirq.measure(*[qreg[s] for s in support]), ) if circuit_type == "cirq": assert _equal(measured, expected, require_qubit_equality=True) else: expected = convert(expected) if circuit_type == "pyquil": # Special case with basis rotation order. assert set(measured) == set(expected) else: assert measured == expected
def test_from_mitiq(to_type): converted_circuit = convert_from_mitiq(cirq_circuit, to_type) circuit, input_type = convert_to_mitiq(converted_circuit) assert _equal(circuit, cirq_circuit) assert input_type == to_type
def test_to_mitiq(circuit): converted_circuit, input_type = convert_to_mitiq(circuit) assert _equal(converted_circuit, cirq_circuit) assert input_type in circuit.__module__
def test_exact_sequences(slack_length, rule, sequence): sequence_to_test = rule(slack_length) assert _equal(sequence_to_test, sequence)
def test_to_from_braket_bell_circuit(qreg): cirq_circuit = Circuit(ops.H(qreg[0]), ops.CNOT(*qreg)) test_circuit = from_braket(to_braket(cirq_circuit)) assert _equal(test_circuit, cirq_circuit, require_qubit_equality=True)
def test_to_from_pennylane_cnot_same_gates(): qreg = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.CNOT(*qreg)) converted = from_pennylane(to_pennylane(circuit)) assert _equal(circuit, converted, require_qubit_equality=False)
def test_circuit_equality_identical_qubits(require_qubit_equality): qreg = cirq.NamedQubit.range(5, prefix="q_") circA = cirq.Circuit(cirq.ops.H.on_each(*qreg)) circB = cirq.Circuit(cirq.ops.H.on_each(*qreg)) assert circA is not circB assert _equal(circA, circB, require_qubit_equality=require_qubit_equality)
def sample_sequence( ideal_operation: QPROGRAM, representations: Sequence[OperationRepresentation], random_state: Optional[Union[int, np.random.RandomState]] = None, num_samples: int = 1, ) -> Tuple[List[QPROGRAM], List[int], float]: """Samples a list of implementable sequences from the quasi-probability representation of the input ideal operation. Returns the list of sequences, the corresponding list of signs and the one-norm of the quasi-probability representation (of the input operation). For example, if the ideal operation is U with representation U = a A + b B, then this function returns A with probability :math:`|a| / (|a| + |b|)` and B with probability :math:`|b| / (|a| + |b|)`. Also returns sign(a) (sign(b)) and :math:`|a| + |b|` if A (B) is sampled. Note that the ideal operation can be a sequence of operations (circuit), for instance U = V W, as long as a representation is known. Similarly, A and B can be sequences of operations (circuits) or just single operations. Args: ideal_operation: The ideal operation from which an implementable sequence is sampled. representations: A list of representations of ideal operations in a noisy basis. If no representation is found for `ideal_operation`, a ValueError is raised. random_state: Seed for sampling. num_samples: The number of samples. Returns: The tuple (``sequences``, ``signs``, ``norm``) where ``sequences`` are the sampled sequences, ``signs`` are the signs associated to the sampled ``sequences`` and ``norm`` is the one-norm of the quasi-probability distribution. Raises: ValueError: If no representation is found for `ideal_operation`. """ # Grab the representation for the given ideal operation. ideal, _ = convert_to_mitiq(ideal_operation) operation_representation = None for representation in representations: if _equal(representation._ideal, ideal, require_qubit_equality=True): operation_representation = representation break if operation_representation is None: warnings.warn( UserWarning(f"No representation found for \n\n{ideal_operation}.")) return ( [ideal_operation] * num_samples, [1] * num_samples, 1.0, ) # Sample from this representation. norm = operation_representation.norm sequences = [] signs = [] for _ in range(num_samples): noisy_op, sign, _ = operation_representation.sample(random_state) sequences.append(noisy_op.circuit()) signs.append(sign) return sequences, signs, norm