def test_protocols(): t = sympy.Symbol('t') cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('Y')) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('Z')) cirq.testing.assert_implements_consistent_protocols( 1j * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( 2 * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( t * cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('XYIZ', coefficient=t + 2)) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.MutableDensePauliString('XYIZ', coefficient=-1)) # Unitarity and shape. assert cirq.has_unitary(1j * cirq.DensePauliString('X')) assert not cirq.has_unitary(2j * cirq.DensePauliString('X')) assert not cirq.has_unitary(cirq.DensePauliString('X') * t) p = -cirq.DensePauliString('XYIZ') assert cirq.num_qubits(p) == len(p) == 4 # Parameterization. x = cirq.DensePauliString('X') assert not cirq.is_parameterized(x) assert not cirq.is_parameterized(x * 2) assert cirq.is_parameterized(x * t) assert cirq.resolve_parameters(x * t, {'t': 2}) == x * 2 assert cirq.resolve_parameters(x * 3, {'t': 2}) == x * 3
def test_matrix(): for n in [1, 2, 3, 4, 0.0001, 3.9999]: assert cirq.has_unitary(CExpZinGate(n)) np.testing.assert_allclose(cirq.unitary(CExpZinGate(1)), np.diag([1, 1, 1j, -1j]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(CExpZinGate(2)), np.diag([1, 1, -1, -1]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(CExpZinGate(3)), np.diag([1, 1, -1j, 1j]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(CExpZinGate(4)), np.diag([1, 1, 1, 1]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(CExpZinGate(0.00001)), cirq.unitary(CExpZinGate(3.99999)), atol=1e-4) assert not np.allclose(cirq.unitary(CExpZinGate(0.00001)), cirq.unitary(CExpZinGate(1.99999)), atol=1e-4) assert not cirq.has_unitary(CExpZinGate(sympy.Symbol('a'))) assert cirq.unitary(CExpZinGate(sympy.Symbol('a')), None) is None np.testing.assert_allclose(cirq.unitary(ZGateDef(exponent=0)), np.eye(2), atol=1e-8) np.testing.assert_allclose(cirq.unitary(ZGateDef(exponent=1)), np.diag([1, -1]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(ZGateDef(exponent=0.5)), np.diag([1, 1j]), atol=1e-8) np.testing.assert_allclose(cirq.unitary( ZGateDef(exponent=1, global_shift=0.5)), np.diag([1j, -1j]), atol=1e-8) np.testing.assert_allclose( cirq.unitary(ZGateDef(exponent=0.5, global_shift=0.5)), np.diag([1 + 1j, -1 + 1j]) / np.sqrt(2), atol=1e-8, ) np.testing.assert_allclose( cirq.unitary(ZGateDef(exponent=0.5, global_shift=-0.5)), np.diag([1 - 1j, 1 + 1j]) / np.sqrt(2), atol=1e-8, )
def test_via_decompose(): class Yes1: def _decompose_(self): return [] class Yes2: def _decompose_(self): return [cirq.X(cirq.LineQubit(0))] class No1: def _decompose_(self): return [cirq.depolarize(0.5).on(cirq.LineQubit(0))] class No2: def _decompose_(self): return None class No3: def _decompose_(self): return NotImplemented assert cirq.has_unitary(Yes1()) assert cirq.has_unitary(Yes2()) assert not cirq.has_unitary(No1()) assert not cirq.has_unitary(No2()) assert not cirq.has_unitary(No3())
def test_protocols(): t = sympy.Symbol('t') cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('Y')) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('Z')) cirq.testing.assert_implements_consistent_protocols( 1j * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( 2 * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( t * cirq.DensePauliString('XYIZ'), ignore_decompose_to_default_gateset=True) cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('XYIZ', coefficient=t + 2), ignore_decompose_to_default_gateset=True) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.MutableDensePauliString('XYIZ', coefficient=-1)) # Unitarity and shape. assert cirq.has_unitary(1j * cirq.DensePauliString('X')) assert not cirq.has_unitary(2j * cirq.DensePauliString('X')) assert not cirq.has_unitary(cirq.DensePauliString('X') * t) p = -cirq.DensePauliString('XYIZ') assert cirq.num_qubits(p) == len(p) == 4
def test_unitary(): cxa = cirq.ControlledGate(cirq.X**cirq.Symbol('a')) assert not cirq.has_unitary(cxa) assert cirq.unitary(cxa, None) is None assert cirq.has_unitary(CY) assert cirq.has_unitary(CCH) np.testing.assert_allclose(cirq.unitary(CY), np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0], ]), atol=1e-8) np.testing.assert_allclose( cirq.unitary(CCH), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, np.sqrt(0.5), np.sqrt(0.5)], [0, 0, 0, 0, 0, 0, np.sqrt(0.5), -np.sqrt(0.5)], ]), atol=1e-8)
def test_inconclusive(): class No: pass assert not cirq.has_unitary(object()) assert not cirq.has_unitary('boo') assert not cirq.has_unitary(No())
def test_unitary(): m = np.array([[0, 1], [1, 0]]) d = np.array([]) class NoMethod: pass class ReturnsNotImplemented: def _has_unitary_(self): return NotImplemented def _unitary_(self): return NotImplemented class ReturnsMatrix: def _unitary_(self) -> np.ndarray: return m class FullyImplemented: def __init__(self, unitary_value): self.unitary_value = unitary_value def _has_unitary_(self) -> bool: return self.unitary_value def _unitary_(self) -> np.ndarray: return m with pytest.raises(TypeError, match='no _unitary_ method'): _ = cirq.unitary(NoMethod()) with pytest.raises(TypeError, match='returned NotImplemented'): _ = cirq.unitary(ReturnsNotImplemented()) assert cirq.unitary(ReturnsMatrix()) is m assert cirq.unitary(NoMethod(), None) is None assert cirq.unitary(ReturnsNotImplemented(), None) is None assert cirq.unitary(ReturnsMatrix(), None) is m assert cirq.unitary(NoMethod(), NotImplemented) is NotImplemented assert cirq.unitary(ReturnsNotImplemented(), NotImplemented) is NotImplemented assert cirq.unitary(ReturnsMatrix(), NotImplemented) is m assert cirq.unitary(NoMethod(), 1) == 1 assert cirq.unitary(ReturnsNotImplemented(), 1) == 1 assert cirq.unitary(ReturnsMatrix(), 1) is m assert cirq.unitary(NoMethod(), d) is d assert cirq.unitary(ReturnsNotImplemented(), d) is d assert cirq.unitary(ReturnsMatrix(), d) is m assert cirq.unitary(FullyImplemented(True), d) is m # Test _has_unitary_ assert not cirq.has_unitary(NoMethod()) assert not cirq.has_unitary(ReturnsNotImplemented()) assert cirq.has_unitary(ReturnsMatrix()) # Explicit function should override assert cirq.has_unitary(FullyImplemented(True)) assert not cirq.has_unitary(FullyImplemented(False))
def test_has_unitary(): assert not cirq.has_unitary(NoMethod()) assert not cirq.has_unitary(ReturnsNotImplemented()) assert cirq.has_unitary(ReturnsMatrix()) # Explicit function should override assert cirq.has_unitary(FullyImplemented(True)) assert not cirq.has_unitary(FullyImplemented(False))
def test_fail_fast_measure(measurement_gate): assert not cirq.has_unitary(measurement_gate) qubit = cirq.NamedQubit('q0') circuit = cirq.Circuit() circuit += measurement_gate(qubit) circuit += cirq.H(qubit) assert not cirq.has_unitary(circuit)
def test_parameterized_repeat(): q = cirq.LineQubit(0) op = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q))) ** sympy.Symbol('a') assert cirq.parameter_names(op) == {'a'} assert not cirq.has_unitary(op) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 0}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': -1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'): cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5}) with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'): cirq.Simulator().simulate(cirq.Circuit(op)) op = op**-1 assert cirq.parameter_names(op) == {'a'} assert not cirq.has_unitary(op) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 0}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': -1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'): cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5}) with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'): cirq.Simulator().simulate(cirq.Circuit(op)) op = op ** sympy.Symbol('b') assert cirq.parameter_names(op) == {'a', 'b'} assert not cirq.has_unitary(op) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2, 'b': 1}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 2}) assert np.allclose(result.state_vector(copy=False), [1, 0]) with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'): cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1}) with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'): cirq.Simulator().simulate(cirq.Circuit(op)) op = op**2.0 assert cirq.parameter_names(op) == {'a', 'b'} assert not cirq.has_unitary(op) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1}) assert np.allclose(result.state_vector(copy=False), [1, 0]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1}) assert np.allclose(result.state_vector(copy=False), [0, 1]) result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1.5}) assert np.allclose(result.state_vector(copy=False), [0, 1]) with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'): cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1.5}) with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'): cirq.Simulator().simulate(cirq.Circuit(op))
def test_matrix(): assert cirq.has_unitary(cirq.CCX) np.testing.assert_allclose(cirq.unitary(cirq.CCX), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCX**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCX**0.5), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0.5 + 0.5j, 0.5 - 0.5j], [0, 0, 0, 0, 0, 0, 0.5 - 0.5j, 0.5 + 0.5j], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ) np.testing.assert_allclose(cirq.unitary(cirq.CCZ), np.diag([1, 1, 1, 1, 1, 1, 1, -1]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCZ**0.5), np.diag([1, 1, 1, 1, 1, 1, 1, 1j]), atol=1e-8) assert cirq.has_unitary(cirq.CSWAP) np.testing.assert_allclose(cirq.unitary(cirq.CSWAP), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], ]), atol=1e-8) cirq.testing.assert_eigen_gate_has_consistent_apply_unitary( cirq.CCXPowGate) cirq.testing.assert_eigen_gate_has_consistent_apply_unitary( cirq.CCZPowGate) cirq.testing.assert_has_consistent_apply_unitary(cirq.CSWAP)
def test_order(): class Yes1(EmptyOp): def _has_unitary_(self): return True def _decompose_(self): assert False def _apply_unitary_(self, args): assert False def _unitary_(self): assert False class Yes2(EmptyOp): def _has_unitary_(self): return NotImplemented def _decompose_(self): return [] def _apply_unitary_(self, args): assert False def _unitary_(self): assert False class Yes3(EmptyOp): def _has_unitary_(self): return NotImplemented def _decompose_(self): return NotImplemented def _apply_unitary_(self, args): return args.target_tensor def _unitary_(self): assert False class Yes4(EmptyOp): def _has_unitary_(self): return NotImplemented def _decompose_(self): return NotImplemented def _apply_unitary_(self, args): return NotImplemented def _unitary_(self): return np.array([[1]]) assert cirq.has_unitary(Yes1()) assert cirq.has_unitary(Yes2()) assert cirq.has_unitary(Yes3()) assert cirq.has_unitary(Yes4())
def test_phase_gradient_symbolic(resolve_fn): a = cirq.PhaseGradientGate(num_qubits=2, exponent=0.5) b = cirq.PhaseGradientGate(num_qubits=2, exponent=sympy.Symbol('t')) assert not cirq.is_parameterized(a) assert cirq.is_parameterized(b) assert cirq.has_unitary(a) assert not cirq.has_unitary(b) assert resolve_fn(a, {'t': 0.25}) is a assert resolve_fn(b, {'t': 0.5}) == a assert resolve_fn(b, {'t': 0.25}) == cirq.PhaseGradientGate(num_qubits=2, exponent=0.25)
def test_matrix(): assert cirq.has_unitary(cirq.CCX) np.testing.assert_allclose(cirq.unitary(cirq.CCX), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCX**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCX**0.5), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0.5 + 0.5j, 0.5 - 0.5j], [0, 0, 0, 0, 0, 0, 0.5 - 0.5j, 0.5 + 0.5j], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ) np.testing.assert_allclose(cirq.unitary(cirq.CCZ), np.diag([1, 1, 1, 1, 1, 1, 1, -1]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCZ**0.5), np.diag([1, 1, 1, 1, 1, 1, 1, 1j]), atol=1e-8) assert cirq.has_unitary(cirq.CSWAP) np.testing.assert_allclose(cirq.unitary(cirq.CSWAP), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], ]), atol=1e-8) cirq.testing.assert_apply_unitary_to_tensor_is_consistent_with_unitary( cirq.CCZ, exponents=[1, 0.5, -0.25, cirq.Symbol('s')]) cirq.testing.assert_apply_unitary_to_tensor_is_consistent_with_unitary( cirq.CCX, exponents=[1, 0.5, -0.25, cirq.Symbol('s')]) cirq.testing.assert_apply_unitary_to_tensor_is_consistent_with_unitary( cirq.CSWAP)
def test_unitary(): assert cirq.has_unitary(cirq.CCX) np.testing.assert_allclose(cirq.unitary(cirq.CCX), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCX**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCX**0.5), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0.5 + 0.5j, 0.5 - 0.5j], [0, 0, 0, 0, 0, 0, 0.5 - 0.5j, 0.5 + 0.5j], ]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ) np.testing.assert_allclose(cirq.unitary(cirq.CCZ), np.diag([1, 1, 1, 1, 1, 1, 1, -1]), atol=1e-8) assert cirq.has_unitary(cirq.CCZ**0.5) np.testing.assert_allclose(cirq.unitary(cirq.CCZ**0.5), np.diag([1, 1, 1, 1, 1, 1, 1, 1j]), atol=1e-8) assert cirq.has_unitary(cirq.CSWAP) np.testing.assert_allclose(cirq.unitary(cirq.CSWAP), np.array([ [1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], ]), atol=1e-8)
def test_unitary_from_apply_unitary(): class ApplyGate(cirq.Gate): def num_qubits(self): return 1 def _apply_unitary_(self, args): return cirq.apply_unitary(cirq.X(cirq.LineQubit(0)), args) class UnknownType(): def _apply_unitary_(self, args): assert False class ApplyGateNotUnitary(cirq.Gate): def num_qubits(self): return 1 def _apply_unitary_(self, args): return None class ApplyOp(cirq.Operation): def __init__(self, q): self.q = q @property def qubits(self): return self.q, def with_qubits(self, *new_qubits): # coverage: ignore return ApplyOp(*new_qubits) def _apply_unitary_(self, args): return cirq.apply_unitary(cirq.X(self.q), args) assert cirq.has_unitary(ApplyGate()) assert cirq.has_unitary(ApplyOp(cirq.LineQubit(0))) assert not cirq.has_unitary(ApplyGateNotUnitary()) assert not cirq.has_unitary(UnknownType()) np.testing.assert_allclose(cirq.unitary(ApplyGate()), np.array([[0, 1], [1, 0]])) np.testing.assert_allclose(cirq.unitary(ApplyOp(cirq.LineQubit(0))), np.array([[0, 1], [1, 0]])) assert cirq.unitary(ApplyGateNotUnitary(), default=None) is None assert cirq.unitary(UnknownType(), default=None) is None
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, pre_opts: Iterable[cirq.OptimizationPass] = (cg.ConvertToXmonGates( ignore_failures=True), ), post_opts: Iterable[cirq.OptimizationPass] = (cg.ConvertToXmonGates( ignore_failures=True), cirq.DropEmptyMoments())): opt = cg.EjectZ() if cirq.has_unitary(before): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( before, expected, atol=1e-8) circuit = before.copy() for pre in pre_opts: pre.optimize_circuit(circuit) opt.optimize_circuit(circuit) for post in post_opts: post.optimize_circuit(circuit) post.optimize_circuit(expected) cirq.testing.assert_same_circuits(circuit, expected) # And it should be idempotent. opt.optimize_circuit(circuit) cirq.testing.assert_same_circuits(circuit, expected)
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, eject_parameterized: bool = False, *, with_context: bool = False, ): if cirq.has_unitary(before): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( before, expected, atol=1e-8) context = cirq.TransformerContext( tags_to_ignore=("nocompile", )) if with_context else None circuit = cirq.eject_z(before, eject_parameterized=eject_parameterized, context=context) expected = cirq.eject_z(expected, eject_parameterized=eject_parameterized, context=context) cirq.testing.assert_same_circuits(circuit, expected) # And it should be idempotent. circuit = cirq.eject_z(before, eject_parameterized=eject_parameterized, context=context) cirq.testing.assert_same_circuits(circuit, expected)
def test_via_unitary(): class No1: def _unitary_(self): return NotImplemented class No2: def _unitary_(self): return None class Yes: def _unitary_(self): return np.array([[1]]) assert not cirq.has_unitary(No1()) assert not cirq.has_unitary(No2()) assert cirq.has_unitary(Yes())
def test_unitary(): diagonal_angles = [2, 3, 5, 7] assert cirq.has_unitary(cirq.TwoQubitDiagonalGate(diagonal_angles)) np.testing.assert_allclose( cirq.unitary(cirq.TwoQubitDiagonalGate(diagonal_angles)), np.diag([np.exp(1j * angle) for angle in diagonal_angles]), atol=1e-8)
def test_assert_apply_unitary_works_when_axes_transposed_failure(): class BadOp: def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs): # Get a more convenient view of the data. a, b = args.axes rest = list(range(len(args.target_tensor.shape))) rest.remove(a) rest.remove(b) size = args.target_tensor.size view = args.target_tensor.transpose([a, b, *rest]) view = view.reshape((4, size // 4)) # Oops. Reshape might copy. # Apply phase gradient. view[1, ...] *= 1j view[2, ...] *= -1 view[3, ...] *= -1j return args.target_tensor def _num_qubits_(self): return 2 bad_op = BadOp() assert cirq.has_unitary(bad_op) # Appears to work. np.testing.assert_allclose(cirq.unitary(bad_op), np.diag([1, 1j, -1, -1j])) # But fails the more discerning test. with pytest.raises(AssertionError, match='acted differently on out-of-order axes'): for _ in range( 100): # Axis orders chosen at random. Brute force a hit. _assert_apply_unitary_works_when_axes_transposed(bad_op)
def known_2q_op_to_sycamore_operations( op: cirq.Operation) -> Optional[cirq.OP_TREE]: """Synthesizes a known two-qubit operation using `cirq_google.SYC` + single qubit rotations. This function dispatches to various known gate decompositions based on gate type. Currently, the following gates are known: 1. Adjacent `cirq.SWAP` and `cirq.ZPowGate` wrapped in a circuit operation of length 2. 2. `cirq.PhasedISwapPowGate` with exponent = 1 or phase_exponent = 0.25. 3. `cirq.SWAP`, `cirq.ISWAP`. 4. `cirq.CNotPowGate`, `cirq.CZPowGate`, `cirq.ZZPowGate`. Args: op: Operation to decompose. Returns: - A `cirq.OP_TREE` that implements the given known operation using only `cirq_google.SYC` + single qubit rotations OR - None if `op` is not a known operation. """ if not (cirq.has_unitary(op) and cirq.num_qubits(op) == 2): return None q0, q1 = op.qubits if isinstance(op.untagged, cirq.CircuitOperation): flattened_gates = [o.gate for o in cirq.decompose_once(op.untagged)] if len(flattened_gates) != 2: return None for g1, g2 in itertools.permutations(flattened_gates): if g1 == cirq.SWAP and isinstance(g2, cirq.ZZPowGate): return _swap_rzz(g2.exponent * np.pi / 2, q0, q1) gate = op.gate if isinstance(gate, cirq.PhasedISwapPowGate): if math.isclose(gate.exponent, 1) and isinstance( gate.phase_exponent, float): return _decompose_phased_iswap_into_syc(gate.phase_exponent, q0, q1) if math.isclose(gate.phase_exponent, 0.25): return _decompose_phased_iswap_into_syc_precomputed( gate.exponent * np.pi / 2, q0, q1) return None if isinstance(gate, cirq.CNotPowGate): return [ cirq.Y(q1)**-0.5, _decompose_cphase_into_syc(gate.exponent * np.pi, q0, q1), cirq.Y(q1)**0.5, ] if isinstance(gate, cirq.CZPowGate): return (_decompose_cz_into_syc(q0, q1) if math.isclose( gate.exponent, 1) else _decompose_cphase_into_syc( gate.exponent * np.pi, q0, q1)) if isinstance(gate, cirq.SwapPowGate) and math.isclose(gate.exponent, 1): return _decompose_swap_into_syc(q0, q1) if isinstance(gate, cirq.ISwapPowGate) and math.isclose(gate.exponent, 1): return _decompose_iswap_into_syc(q0, q1) if isinstance(gate, cirq.ZZPowGate): return _rzz(gate.exponent * np.pi / 2, q0, q1) return None
def test_via_has_unitary(): class No1: def _has_unitary_(self): return NotImplemented class No2: def _has_unitary_(self): return False class Yes: def _has_unitary_(self): return True assert not cirq.has_unitary(No1()) assert not cirq.has_unitary(No2()) assert cirq.has_unitary(Yes())
def test_unknown_two_qubit_op_decomposition(op): assert cg.known_2q_op_to_sycamore_operations(op) is None if cirq.has_unitary(op) and cirq.num_qubits(op) == 2: matrix_2q_circuit = cirq.Circuit( cg.two_qubit_matrix_to_sycamore_operations(q[0], q[1], cirq.unitary(op)) ) assert_implements(matrix_2q_circuit, op)
def decompose_to_device(operation: cirq.Operation, atol: float = 1e-8) -> cirq.OP_TREE: """Decompose operation to ionq native operations. Merges single qubit operations and decomposes two qubit operations into CZ gates. Args: operation: `cirq.Operation` to decompose. atol: absolute error tolerance to use when declaring two unitary operations equal. Returns: cirq.OP_TREE containing decomposed operations. Raises: ValueError: If supplied operation cannot be decomposed for the ionq device. """ if operation in _VALID_GATES: return operation assert cirq.has_unitary(operation), ( f'Operation {operation} is not available on the IonQ API nor does it have a ' 'unitary matrix to use to decompose it to the API.') num_qubits = len(operation.qubits) if num_qubits == 1: return _decompose_single_qubit(operation, atol) if num_qubits == 2: return _decompose_two_qubit(operation) raise ValueError(f'Operation {operation} not supported by IonQ API.')
def test_assert_specifies_has_unitary_if_unitary_pass(): class Good: def _has_unitary_(self): return True assert cirq.has_unitary(Good()) cirq.testing.assert_specifies_has_unitary_if_unitary(Good())
def test_unitary(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') assert not cirq.has_unitary(cirq.measure(a)) assert cirq.unitary(cirq.measure(a), None) is None np.testing.assert_allclose(cirq.unitary(cirq.X(a)), np.array([[0, 1], [1, 0]]), atol=1e-8) np.testing.assert_allclose(cirq.unitary(cirq.CNOT(a, b)), cirq.unitary(cirq.CNOT), atol=1e-8)
def test_unitary(n): diagonal_angles = _candidate_angles[: 2 ** n] assert cirq.has_unitary(cirq.DiagonalGate(diagonal_angles)) np.testing.assert_allclose( cirq.unitary(cirq.DiagonalGate(diagonal_angles)).diagonal(), [np.exp(1j * angle) for angle in diagonal_angles], atol=1e-8, )
def test_parameterization(): t = sympy.Symbol('t') gpt = cirq.GlobalPhaseGate(coefficient=t) assert cirq.is_parameterized(gpt) assert cirq.parameter_names(gpt) == {'t'} assert not cirq.has_unitary(gpt) assert gpt.coefficient == t assert (gpt**2).coefficient == t**2
def test_assert_specifies_has_unitary_if_unitary_from_matrix(): class Bad: def _unitary_(self): return np.array([[1]]) assert cirq.has_unitary(Bad()) with pytest.raises(AssertionError, match='specify a _has_unitary_ method'): cirq.testing.assert_specifies_has_unitary_if_unitary(Bad())