def test_validate_well_structured(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit([ cirq.Moment([cirq.PhasedXPowGate(phase_exponent=0).on(q0)]), cirq.Moment([ cirq.ZPowGate(exponent=0.5).on(q0), ]), cirq.Moment([cg.SYC(q0, q1)]), cirq.measure(q0, q1, key='z'), ]) validate_well_structured(circuit)
def test_zz_as_syc_2(): q1, q2 = cirq.LineQubit.range(2) zz = cirq.ZZPowGate(exponent=0.123) circuit = zz_as_syc(zz.exponent * np.pi / 2, q1, q2) assert len(circuit) == 3 * 2 + 2 validate_well_structured(circuit) cirq.testing.assert_has_diagram(circuit, """ 0: ───PhX(1)^0.483───Z^(1/12)─────SYC────────────────────────SYC───PhX(0.917)^0.483───Z^(1/12)─── │ │ 1: ───PhX(-0.583)────Z^(-11/12)───SYC───PhX(0)^0.873───Z^0───SYC───PhX(0)─────────────T^-1─────── """)
def test_validate_well_structured_non_term_meas(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit([ cirq.Moment([cirq.PhasedXPowGate(phase_exponent=0).on(q0)]), cirq.Moment([ cirq.PhasedXPowGate(phase_exponent=0.5).on(q0), ]), cirq.measure(q0, q1, key='z'), cirq.Moment([cg.SYC(q0, q1)]), ]) with pytest.raises(BadlyStructuredCircuitError) as e: validate_well_structured(circuit) assert e.match('Measurements must be terminal')
def test_validate_well_structured_too_many(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit([ cirq.Moment([cirq.PhasedXPowGate(phase_exponent=0).on(q0)]), cirq.Moment([ cirq.PhasedXPowGate(phase_exponent=0.5).on(q0), ]), cirq.Moment([cg.SYC(q0, q1)]), cirq.measure(q0, q1, key='z'), ]) with pytest.raises(BadlyStructuredCircuitError) as e: validate_well_structured(circuit) assert e.match('Too many PhX')
def test_compile_to_non_negligible(): qubits = cirq.LineQubit.range(2) circuit = cirq.Circuit(ZZSwap(zz_exponent=0.123).on(*qubits)) c1 = compile_to_syc(circuit) validate_well_structured(c1) assert len(c1) == 3 * 3 + 2 c2 = compile_to_non_negligible(c1) assert c1 != c2 # KAK instability (https://github.com/quantumlib/Cirq/issues/1647) # means the first layer of PhX gets removed on mpharrigan's machine # but not in docker / in CI. assert len(c2) in [9, 10]
def test_get_compiled_grid_model_circuit(): problem = _random_grid_model(2, 2, np.random.RandomState(0)) qubits = cirq.GridQubit.rect(2, 2) circuit, final_qubits = get_compiled_hardware_grid_circuit( problem, qubits, gammas=[np.pi / 2, np.pi / 4], betas=[np.pi / 2, np.pi / 4], ) assert final_qubits == qubits validate_well_structured(circuit) rc = get_routed_hardware_grid_circuit( problem.graph, qubits, problem.coordinates, gammas=[np.pi / 2, np.pi / 4], betas=[np.pi / 2, np.pi / 4], ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( rc + cirq.measure(*qubits), circuit, atol=1e-5)
def test_compile_to_syc(p): problem = nx.complete_graph(n=5) problem = random_plus_minus_1_weights(problem) qubits = cirq.LineQubit.range(5) c1 = cirq.Circuit(cirq.H.on_each(qubits), [[ ProblemUnitary(problem, gamma=np.random.random()).on(*qubits), DriverUnitary(5, beta=np.random.random()).on(*qubits) ] for _ in range(p)]) c2 = compile_problem_unitary_to_swap_network(c1) c3 = compile_swap_network_to_zzswap(c2) c4 = compile_driver_unitary_to_rx(c3) c5 = compile_to_syc(c4) validate_well_structured(c5, allow_terminal_permutations=True) np.testing.assert_allclose(c1.unitary(), c2.unitary()) np.testing.assert_allclose(c1.unitary(), c3.unitary()) np.testing.assert_allclose(c1.unitary(), c4.unitary()) # Single qubit throws out global phase cirq.testing.assert_allclose_up_to_global_phase(c1.unitary(), c5.unitary(), atol=1e-8)
def test_measure_with_final_permutation(p): problem = nx.complete_graph(n=5) problem = random_plus_minus_1_weights(problem) qubits = cirq.LineQubit.range(5) c1 = cirq.Circuit( cirq.H.on_each(qubits), [ [ ProblemUnitary(problem, gamma=np.random.random()).on(*qubits), DriverUnitary(5, beta=np.random.random()).on(*qubits) ] for _ in range(p) ] ) c2 = compile_problem_unitary_to_swap_network(c1) c3 = compile_swap_network_to_zzswap(c2) c4 = compile_driver_unitary_to_rx(c3) c5 = compile_to_syc(c4) validate_well_structured(c5, allow_terminal_permutations=True) c6, final_qubits = measure_with_final_permutation(c5, qubits) validate_well_structured(c6, allow_terminal_permutations=False) if p % 2 == 1: assert final_qubits == qubits[::-1] else: assert final_qubits == qubits permutation = [] for q in qubits: permutation.append(final_qubits.index(q)) c1_prime = ( c1 + QuirkQubitPermutationGate('', '', permutation).on(*qubits) + cirq.measure(*qubits, key='z') ) cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(c1_prime, c6, atol=1e-5)
def measure_with_final_permutation( circuit: cirq.Circuit, qubits: List[cirq.Qid], *, mutate=False) -> Tuple[cirq.Circuit, List[cirq.Qid]]: """Apply a measurement gate at the end of a circuit and classically permute qubit indices. If the circuit contains a permutation gate at its end, the input argument `qubits` will be permuted and returned as the second return value. Args: circuit: The circuit qubits: Which qubits to measure mutate: By default, return a copy of the circuit. Otherwise, mutate in place. Returns: circuit: The output circuit with measurement final_qubits: The input list of qubits permuted according to the final permutation gate. """ if mutate: c2 = circuit else: c2 = circuit.copy() mom_classes, stats = validate_well_structured( c2, allow_terminal_permutations=True) if stats.has_measurement: raise ValueError("Circuit already has measurements") mapping = {} if stats.has_permutation: for op in c2.moments[-1].operations: if cirq.op_gate_of_type(op, QuirkQubitPermutationGate): # do something with it permuted_qs = op.qubits gate = op.gate # type: QuirkQubitPermutationGate for i, q in enumerate(permuted_qs): mapping[q] = permuted_qs[gate.permutation[i]] c2.moments.pop(-1) final_qubits = [mapping.get(q, q) for q in qubits] c2.append(cirq.measure(*qubits, key='z')) return c2, final_qubits
def test_structured(): qubits = cirq.LineQubit.range(2) circuit = cirq.Circuit(ZZSwap(zz_exponent=0.123).on(*qubits)) circuit = compile_to_syc(circuit) validate_well_structured(circuit)