def assert_optimization_not_broken(circuit: cirq.Circuit, **kwargs): """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(sorted(circuit.all_qubits())) c_sqrt_iswap = circuit.copy() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractionsToSqrtIswap( **kwargs).optimize_circuit(c_sqrt_iswap) u_after = c_sqrt_iswap.unitary(sorted(circuit.all_qubits())) # Not 1e-8 because of some unaccounted accumulated error in some of Cirq's linalg functions cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-6) # Also test optimization with SQRT_ISWAP_INV c_sqrt_iswap_inv = circuit.copy() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractionsToSqrtIswap( use_sqrt_iswap_inv=True).optimize_circuit(c_sqrt_iswap_inv) u_after2 = c_sqrt_iswap_inv.unitary(sorted(circuit.all_qubits())) cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after2, atol=1e-6)
def test_optimizes_single_inv_sqrt_iswap_require3(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.SQRT_ISWAP_INV(a, b)) assert_optimization_not_broken(c, required_sqrt_iswap_count=3) cirq.MergeInteractionsToSqrtIswap( required_sqrt_iswap_count=3).optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 3
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit, **kwargs): """Check that optimizing the circuit ``before`` produces the circuit ``expected``. The optimized circuit is cleaned up with follow up optimizations to make the comparison more robust to extra moments or extra gates nearly equal to identity that don't matter. Args: before: The input circuit to optimize. expected: The expected result of optimization to compare against. **kwargs: Any extra arguments to pass to the ``MergeInteractionsToSqrtIswap`` constructor. """ actual = before.copy() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): opt = cirq.MergeInteractionsToSqrtIswap(**kwargs) 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 test_optimizes_single_iswap_require0(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CNOT(a, b), cirq.CNOT(a, b)) # Minimum 0 sqrt-iSWAP assert_optimization_not_broken(c, required_sqrt_iswap_count=0) cirq.MergeInteractionsToSqrtIswap( required_sqrt_iswap_count=0).optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 0
def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit, **kwargs): """Check that optimizing the circuit ``before`` produces the circuit ``expected``. The optimized circuit is cleaned up with follow up optimizations to make the comparison more robust to extra moments or extra gates nearly equal to identity that don't matter. Args: before: The input circuit to optimize. expected: The expected result of optimization to compare against. kwargs: Any extra arguments to pass to the ``MergeInteractionsToSqrtIswap`` constructor. """ actual = before.copy() opt = cirq.MergeInteractionsToSqrtIswap(**kwargs) 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_optimizes_single_iswap_require2_raises(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.SWAP(a, b)) # Minimum 3 sqrt-iSWAP with pytest.raises( ValueError, match='cannot be decomposed into exactly 2 sqrt-iSWAP gates'): cirq.MergeInteractionsToSqrtIswap( required_sqrt_iswap_count=2).optimize_circuit(c)
def test_optimizes_single_iswap_require2_raises(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.SWAP(a, b)) # Minimum 3 sqrt-iSWAP with pytest.raises(ValueError, match='cannot be decomposed into exactly 2 sqrt-iSWAP gates'): with cirq.testing.assert_deprecated( "Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2 ): cirq.MergeInteractionsToSqrtIswap(required_sqrt_iswap_count=2).optimize_circuit(c)
def test_optimizes_single_inv_sqrt_iswap(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.SQRT_ISWAP_INV(a, b)) assert_optimization_not_broken(c) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractionsToSqrtIswap().optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 1
def test_optimizes_single_iswap_require3(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.ISWAP(a, b)) # Minimum 2 sqrt-iSWAP but 3 possible assert_optimization_not_broken(c, required_sqrt_iswap_count=3) with cirq.testing.assert_deprecated( "Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2 ): cirq.MergeInteractionsToSqrtIswap(required_sqrt_iswap_count=3).optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 3
def test_init_raises(): with pytest.raises(ValueError, match='must be 0, 1, 2, or 3'): with cirq.testing.assert_deprecated( "Use cirq.optimize_for_target_gateset", deadline='v1.0', count=2): cirq.MergeInteractionsToSqrtIswap(required_sqrt_iswap_count=4)
def test_init_raises(): with pytest.raises(ValueError, match='must be 0, 1, 2, or 3'): cirq.MergeInteractionsToSqrtIswap(required_sqrt_iswap_count=4)
def test_optimizes_single_iswap(): a, b = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.ISWAP(a, b)) assert_optimization_not_broken(c) cirq.MergeInteractionsToSqrtIswap().optimize_circuit(c) assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 2