def test_post_clean_up(): class Marker(cirq.testing.TwoQubitGate): pass a, b = cirq.LineQubit.range(2) c_orig = cirq.Circuit( cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), ) circuit = cirq.Circuit(c_orig) def clean_up(operations): yield Marker()(a, b) yield operations yield Marker()(a, b) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): optimizer = cirq.MergeInteractions(allow_partial_czs=False, post_clean_up=clean_up) optimizer.optimize_circuit(circuit) circuit = cirq.drop_empty_moments(circuit) assert isinstance(circuit[0].operations[0].gate, Marker) assert isinstance(circuit[-1].operations[0].gate, Marker) u_before = c_orig.unitary() u_after = circuit[1:-1].unitary() cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)
def test_not_decompose_czs(): circuit = cirq.Circuit( cirq.CZPowGate(exponent=1, global_shift=-0.5).on(*cirq.LineQubit.range(2)) ) circ_orig = circuit.copy() cirq.MergeInteractions(allow_partial_czs=False).optimize_circuit(circuit) assert circ_orig == circuit
def test_post_clean_up(): class Marker(cirq.TwoQubitGate): pass a, b = cirq.LineQubit.range(2) c_orig = cirq.Circuit.from_ops( cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), cirq.CZ(a, b), ) circuit = cirq.Circuit(c_orig) def clean_up(operations): yield Marker()(a, b) yield operations yield Marker()(a, b) optimizer = cirq.MergeInteractions(allow_partial_czs=False, post_clean_up=clean_up) optimizer.optimize_circuit(circuit) cirq.DropEmptyMoments().optimize_circuit(circuit) assert isinstance(circuit[0].operations[0].gate, Marker) assert isinstance(circuit[-1].operations[0].gate, Marker) u_before = c_orig.unitary() u_after = circuit[1:-1].unitary() cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)
def test_optimizes_tagged_partial_cz(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit((cirq.CZ**0.5)(a, b).with_tags('mytag')) assert_optimization_not_broken(c) cirq.MergeInteractions(allow_partial_czs=False).optimize_circuit(c) assert (len([ 1 for op in c.all_operations() if len(op.qubits) == 2 ]) == 2), 'It should take 2 CZ gates to decompose a CZ**0.5 gate'
def assert_optimization_not_broken(circuit): """Check that the unitary matrix for the input circuit is the same (up to global phase and rounding error) as the unitary matrix of the optimized circuit.""" u_before = circuit.unitary() cirq.MergeInteractions().optimize_circuit(circuit) u_after = circuit.unitary() cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)
def test_optimizes_single_iswap(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.ISWAP(a, b)) assert_optimization_not_broken(c) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractions().optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 2
def test_decompose_partial_czs(circuit): optimizer = cirq.MergeInteractions(allow_partial_czs=False) optimizer.optimize_circuit(circuit) cz_gates = [op.gate for op in circuit.all_operations() if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)] num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) assert num_full_cz == 2 assert num_part_cz == 0
def test_optimizes_tagged_partial_cz(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit((cirq.CZ**0.5)(a, b).with_tags('mytag')) assert_optimization_not_broken(c) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractions(allow_partial_czs=False).optimize_circuit(c) assert (len([ 1 for op in c.all_operations() if len(op.qubits) == 2 ]) == 2), 'It should take 2 CZ gates to decompose a CZ**0.5 gate'
def test_not_decompose_czs(): circuit = cirq.Circuit( cirq.CZPowGate(exponent=1, global_shift=-0.5).on(*cirq.LineQubit.range(2))) circ_orig = circuit.copy() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractions( allow_partial_czs=False).optimize_circuit(circuit) assert circ_orig == circuit
def _get_xmon_optimizers_part_cz( tolerance: float, tabulation: Optional[GateTabulation] ) -> List[Callable[[cirq.Circuit], None]]: if tabulation is not None: # coverage: ignore raise ValueError("Gate tabulation not supported for xmon") return [ convert_to_xmon_gates.ConvertToXmonGates().optimize_circuit, cirq.MergeInteractions(tolerance=tolerance, allow_partial_czs=True).optimize_circuit, lambda c: cirq.merge_single_qubit_gates_into_phxz(c, tolerance), *_get_common_cleanup_optimizers(tolerance=tolerance), ]
def assert_optimization_not_broken(circuit): """Check that the unitary matrix for the input circuit is the same (up to global phase and rounding error) as the unitary matrix of the optimized circuit.""" u_before = circuit.unitary() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractions().optimize_circuit(circuit) u_after = circuit.unitary() cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)
def test_not_decompose_partial_czs(): circuit = cirq.Circuit.from_ops( cirq.CZPowGate(exponent=0.1)(*cirq.LineQubit.range(2)), ) optimizer = cirq.MergeInteractions(allow_partial_czs=True) optimizer.optimize_circuit(circuit) cz_gates = [op.gate for op in circuit.all_operations() if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)] num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) assert num_full_cz == 0 assert num_part_cz == 1
def test_decompose_partial_czs(circuit): with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): optimizer = cirq.MergeInteractions(allow_partial_czs=False) optimizer.optimize_circuit(circuit) cz_gates = [ op.gate for op in circuit.all_operations() if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) ] num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) assert num_full_cz == 2 assert num_part_cz == 0
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): actual = cirq.Circuit(before) opt = cirq.MergeInteractions() opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations: List[Callable[[cirq.Circuit], None]] = [ cirq.merge_single_qubit_gates_into_phased_x_z, cirq.EjectPhasedPaulis().optimize_circuit, cirq.EjectZ().optimize_circuit, cirq.DropNegligible().optimize_circuit, cirq.DropEmptyMoments().optimize_circuit, ] for post in followup_optimizations: post(actual) post(expected) assert actual == expected, f'ACTUAL {actual} : EXPECTED {expected}'
def test_not_decompose_partial_czs(): circuit = cirq.Circuit( cirq.CZPowGate(exponent=0.1, global_shift=-0.5)(*cirq.LineQubit.range(2)), ) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): optimizer = cirq.MergeInteractions(allow_partial_czs=True) optimizer.optimize_circuit(circuit) cz_gates = [ op.gate for op in circuit.all_operations() if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) ] num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) assert num_full_cz == 0 assert num_part_cz == 1
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): actual = cirq.Circuit(before) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): opt = cirq.MergeInteractions() opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_transformers: List[cirq.TRANSFORMER] = [ cirq.merge_single_qubit_gates_to_phased_x_and_z, cirq.eject_phased_paulis, cirq.eject_z, cirq.drop_negligible_operations, cirq.drop_empty_moments, ] for transform in followup_transformers: actual = transform(actual).unfreeze(copy=False) expected = transform(expected).unfreeze(copy=False) assert actual == expected, f'ACTUAL {actual} : EXPECTED {expected}'
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): actual = cirq.Circuit(before) opt = cirq.MergeInteractions() opt.optimize_circuit(actual) # Ignore differences that would be caught by follow-up optimizations. followup_optimizations = [ cg.MergeRotations(), cg.EjectFullW(), cg.EjectZ(), cirq.DropNegligible(), cirq.DropEmptyMoments() ] for post in followup_optimizations: post.optimize_circuit(actual) post.optimize_circuit(expected) if actual != expected: # coverage: ignore print('ACTUAL') print(actual) print('EXPECTED') print(expected) assert actual == expected
def test_optimizes_single_iswap(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit.from_ops(cirq.ISWAP(a, b)) assert_optimization_not_broken(c) cirq.MergeInteractions().optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 2