def test_invalid_subspaces(): with pytest.raises(ValueError, match='Subspace specified does not exist in axis'): _ = cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((2,), dtype=np.complex64), available_buffer=cirq.eye_tensor((2,), dtype=np.complex64), axes=(0,), subspaces=[(1, 2)], ) with pytest.raises(ValueError, match='Subspace count does not match axis count'): _ = cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((2,), dtype=np.complex64), available_buffer=cirq.eye_tensor((2,), dtype=np.complex64), axes=(0,), subspaces=[(0, 1), (0, 1)], ) with pytest.raises(ValueError, match='has zero dimensions'): _ = cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((2,), dtype=np.complex64), available_buffer=cirq.eye_tensor((2,), dtype=np.complex64), axes=(0,), subspaces=[()], ) with pytest.raises(ValueError, match='does not have consistent step size'): _ = cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(0, 2, 1)], )
def test_incorporate_result_not_view(): tensor = np.zeros((2, 2)) tensor2 = np.zeros((2, 2)) buffer = np.empty_like(tensor) args = cirq.ApplyUnitaryArgs(tensor, buffer, [0]) not_sub_args = cirq.ApplyUnitaryArgs(tensor2, buffer, [0]) with pytest.raises(ValueError, match='view'): _incorporate_result_into_target(args, not_sub_args, tensor2)
def test_identity_apply_unitary(): v = np.array([1, 0]) result = cirq.apply_unitary( cirq.I, cirq.ApplyUnitaryArgs(v, np.array([0, 1]), (0, ))) assert result is v v = np.array([1, 0, 0]) result = cirq.apply_unitary( cirq.IdentityGate(1, (3, )), cirq.ApplyUnitaryArgs(v, np.array([0, 1, 2]), (0, ))) assert result is v
def test_big_endian_subspace_index(): state = np.zeros(shape=(2, 3, 4, 5, 1, 6, 1, 1)) args = cirq.ApplyUnitaryArgs(state, np.empty_like(state), [1, 3]) s = slice(None) assert args.subspace_index(little_endian_bits_int=1) == (s, 1, s, 0, s, s, s, s) assert args.subspace_index(big_endian_bits_int=1) == (s, 0, s, 1, s, s, s, s)
def assert_works(val): expected_outputs = [ np.array([1, 1, -1, -1]).reshape((2, 2)), np.array([1, -1, 1, -1]).reshape((2, 2)), ] for axis in range(2): result = cirq.apply_unitary(val, cirq.ApplyUnitaryArgs(make_input(), buf, [axis])) np.testing.assert_allclose(result, expected_outputs[axis])
def test_cast_to_complex(): y0 = cirq.PauliString({cirq.LineQubit(0): cirq.Y}) state = 0.5 * np.eye(2) args = cirq.ApplyUnitaryArgs( target_tensor=state, available_buffer=np.zeros_like(state), axes=(0,) ) with pytest.raises( np.ComplexWarning, match='Casting complex values to real discards the imaginary part' ): cirq.apply_unitary(y0, args)
def test_apply_unitary_args_with_axes_transposed_to_start(): target = np.zeros((2, 3, 4, 5)) buffer = np.zeros((2, 3, 4, 5)) args = cirq.ApplyUnitaryArgs(target, buffer, [1, 3]) new_args = args.with_axes_transposed_to_start() assert new_args.target_tensor.shape == (3, 5, 2, 4) assert new_args.available_buffer.shape == (3, 5, 2, 4) # Confirm aliasing. new_args.target_tensor[2, 4, 1, 3] = 1 assert args.target_tensor[1, 2, 3, 4] == 1 new_args.available_buffer[2, 4, 1, 3] = 2 assert args.available_buffer[1, 2, 3, 4] == 2
def assert_is_swap(val: cirq.SupportsConsistentApplyUnitary) -> None: qid_shape = (1, 2, 4, 2) op_indices = [1, 3] state = np.arange(2 * (1 * 3 * 4 * 5), dtype=np.complex64).reshape( (1, 2, 1, 5, 3, 1, 4)) expected = state.copy() buf = expected[..., 0, 1, :, :].copy() expected[..., 0, 1, :, :] = expected[..., 1, 0, :, :] expected[..., 1, 0, :, :] = buf expected[..., :2, :2, :, :] *= 1j args = cirq.ApplyUnitaryArgs(state, np.empty_like(state), [5, 4, 6, 3]) sub_args = args._for_operation_with_qid_shape( op_indices, tuple(qid_shape[i] for i in op_indices)) sub_result = val._apply_unitary_(sub_args) result = _incorporate_result_into_target(args, sub_args, sub_result) np.testing.assert_allclose(result, expected, atol=1e-8, verbose=True)
def assert_is_swap_simple( val: cirq.SupportsConsistentApplyUnitary) -> None: qid_shape = (2, 2) op_indices = [0, 1] state = np.arange(3 * 3, dtype=np.complex64).reshape((1, 3, 3)) expected = state.copy() buf = expected[..., 0, 1].copy() expected[..., 0, 1] = expected[..., 1, 0] expected[..., 1, 0] = buf expected[..., :2, :2] *= 1j args = cirq.ApplyUnitaryArgs(state, np.empty_like(state), [1, 2]) sub_args = args._for_operation_with_qid_shape( op_indices, tuple(qid_shape[i] for i in op_indices)) sub_result = val._apply_unitary_(sub_args) result = _incorporate_result_into_target(args, sub_args, sub_result) np.testing.assert_allclose(result, expected, atol=1e-8)
def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs'): transposed_args = args.with_axes_transposed_to_start() target_axes = transposed_args.axes[:len(self.base_operation.qubits)] control_axes = transposed_args.axes[len(self.base_operation.qubits):] control_max = np.product([q.dimension for q in self.register]).item() for i in range(control_max): operation = self.base_operation**(self.exponent_sign * i / control_max) control_index = linalg.slice_for_qubits_equal_to( control_axes, big_endian_qureg_value=i) sub_args = cirq.ApplyUnitaryArgs( transposed_args.target_tensor[control_index], transposed_args.available_buffer[control_index], target_axes) sub_result = cirq.apply_unitary(operation, sub_args) if sub_result is not sub_args.target_tensor: sub_args.target_tensor[...] = sub_result return args.target_tensor
def test_apply_unitaries_mixed_qid_shapes(): class PlusOneMod3Gate(cirq.SingleQubitGate): def _qid_shape_(self): return (3, ) def _unitary_(self): return np.array([[0, 0, 1], [1, 0, 0], [0, 1, 0]]) # yapf: disable class PlusOneMod4Gate(cirq.SingleQubitGate): def _qid_shape_(self): return (4, ) def _unitary_(self): return np.array( [[0, 0, 0, 1], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]] ) # yapf: disable a, b = cirq.LineQid.for_qid_shape((3, 4)) result = cirq.apply_unitaries( unitary_values=[ PlusOneMod3Gate().on(a.with_dimension(3)), cirq.X(a.with_dimension(2)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), cirq.X(a.with_dimension(2)), PlusOneMod3Gate().on(a.with_dimension(3)), PlusOneMod3Gate().on(a.with_dimension(3)), ], qubits=[a, b], ) np.testing.assert_allclose(result.reshape(12), [1] + [0] * 11, atol=1e-8) result = cirq.apply_unitaries( unitary_values=[ PlusOneMod3Gate().on(a.with_dimension(3)), cirq.X(a.with_dimension(2)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), cirq.X(a.with_dimension(2)), PlusOneMod3Gate().on(a.with_dimension(3)), PlusOneMod3Gate().on(a.with_dimension(3)), ], qubits=[a, b], args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3, 4), dtype=np.complex64), available_buffer=cirq.eye_tensor((3, 4), dtype=np.complex64), axes=(0, 1), ), ) np.testing.assert_allclose(result.reshape(12, 12), np.eye(12), atol=1e-8) result = cirq.apply_unitaries( unitary_values=[ PlusOneMod3Gate().on(a.with_dimension(3)), cirq.X(a.with_dimension(2)), PlusOneMod4Gate().on(b.with_dimension(4)), PlusOneMod4Gate().on(b.with_dimension(4)), cirq.X(b.with_dimension(2)), PlusOneMod4Gate().on(b.with_dimension(4)), PlusOneMod4Gate().on(b.with_dimension(4)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), PlusOneMod4Gate().on(b.with_dimension(4)), cirq.X(b.with_dimension(2)), cirq.CNOT(a.with_dimension(2), b.with_dimension(2)), cirq.X(a.with_dimension(2)), PlusOneMod3Gate().on(a.with_dimension(3)), PlusOneMod3Gate().on(a.with_dimension(3)), ], qubits=[a, b], args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3, 4), dtype=np.complex64), available_buffer=cirq.eye_tensor((3, 4), dtype=np.complex64), axes=(0, 1), ), ) np.testing.assert_allclose( result.reshape(12, 12), np.array([ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], ]), atol=1e-8, )
def test_apply_unitary_presence_absence(): m = np.diag([1, -1]) class NoUnitaryEffect: pass class HasUnitary: def _unitary_(self) -> np.ndarray: return m class HasApplyReturnsNotImplemented: def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs): return NotImplemented class HasApplyReturnsNotImplementedButHasUnitary: def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs): return NotImplemented def _unitary_(self) -> np.ndarray: return m class HasApplyOutputInBuffer: def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray: zero = args.subspace_index(0) one = args.subspace_index(1) args.available_buffer[zero] = args.target_tensor[zero] args.available_buffer[one] = -args.target_tensor[one] return args.available_buffer class HasApplyMutateInline: def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray: one = args.subspace_index(1) args.target_tensor[one] *= -1 return args.target_tensor fails = [ NoUnitaryEffect(), HasApplyReturnsNotImplemented(), ] passes = [ HasUnitary(), HasApplyReturnsNotImplementedButHasUnitary(), HasApplyOutputInBuffer(), HasApplyMutateInline(), ] def make_input(): return np.ones((2, 2)) def assert_works(val): expected_outputs = [ np.array([1, 1, -1, -1]).reshape((2, 2)), np.array([1, -1, 1, -1]).reshape((2, 2)), ] for axis in range(2): result = cirq.apply_unitary( val, cirq.ApplyUnitaryArgs(make_input(), buf, [axis])) np.testing.assert_allclose(result, expected_outputs[axis]) buf = np.empty(shape=(2, 2), dtype=np.complex128) for f in fails: with pytest.raises(TypeError, match='failed to satisfy'): _ = cirq.apply_unitary( f, cirq.ApplyUnitaryArgs(make_input(), buf, [0])) assert (cirq.apply_unitary( f, cirq.ApplyUnitaryArgs(make_input(), buf, [0]), default=None) is None) assert (cirq.apply_unitary(f, cirq.ApplyUnitaryArgs( make_input(), buf, [0]), default=NotImplemented) is NotImplemented) assert cirq.apply_unitary(f, cirq.ApplyUnitaryArgs( make_input(), buf, [0]), default=1) == 1 for s in passes: assert_works(s) assert (cirq.apply_unitary(s, cirq.ApplyUnitaryArgs( make_input(), buf, [0]), default=None) is not None)
def test_subspaces_size_1(): phase_gate = cirq.MatrixGate(np.array([[1j]])) result = cirq.apply_unitary( unitary_value=phase_gate, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((2,), dtype=np.complex64), available_buffer=cirq.eye_tensor((2,), dtype=np.complex64), axes=(0,), subspaces=[(0,)], ), ) np.testing.assert_allclose( result, np.array( [ [1j, 0], [0, 1], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=phase_gate, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((2,), dtype=np.complex64), available_buffer=cirq.eye_tensor((2,), dtype=np.complex64), axes=(0,), subspaces=[(1,)], ), ) np.testing.assert_allclose( result, np.array( [ [1, 0], [0, 1j], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=phase_gate, args=cirq.ApplyUnitaryArgs( target_tensor=np.array([[0, 1], [1, 0]], dtype=np.complex64), available_buffer=np.zeros((2, 2), dtype=np.complex64), axes=(0,), subspaces=[(1,)], ), ) np.testing.assert_allclose( result, np.array( [ [0, 1], [1j, 0], ] ), atol=1e-8, )
def test_subspaces_size_3(): plus_one_mod_3_gate = cirq.XPowGate(dimension=3) result = cirq.apply_unitary( unitary_value=plus_one_mod_3_gate, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(0, 1, 2)], ), ) np.testing.assert_allclose( result, np.array( [ [0, 0, 1], [1, 0, 0], [0, 1, 0], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=plus_one_mod_3_gate, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(2, 1, 0)], ), ) np.testing.assert_allclose( result, np.array( [ [0, 1, 0], [0, 0, 1], [1, 0, 0], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=plus_one_mod_3_gate, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((4,), dtype=np.complex64), available_buffer=cirq.eye_tensor((4,), dtype=np.complex64), axes=(0,), subspaces=[(1, 2, 3)], ), ) np.testing.assert_allclose( result, np.array( [ [1, 0, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], ] ), atol=1e-8, )
def test_subspace_size_2(): result = cirq.apply_unitary( unitary_value=cirq.X, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(0, 1)], ), ) np.testing.assert_allclose( result, np.array( [ [0, 1, 0], [1, 0, 0], [0, 0, 1], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=cirq.X, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(0, 2)], ), ) np.testing.assert_allclose( result, np.array( [ [0, 0, 1], [0, 1, 0], [1, 0, 0], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=cirq.X, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((3,), dtype=np.complex64), available_buffer=cirq.eye_tensor((3,), dtype=np.complex64), axes=(0,), subspaces=[(1, 2)], ), ) np.testing.assert_allclose( result, np.array( [ [1, 0, 0], [0, 0, 1], [0, 1, 0], ] ), atol=1e-8, ) result = cirq.apply_unitary( unitary_value=cirq.X, args=cirq.ApplyUnitaryArgs( target_tensor=cirq.eye_tensor((4,), dtype=np.complex64), available_buffer=cirq.eye_tensor((4,), dtype=np.complex64), axes=(0,), subspaces=[(1, 2)], ), ) np.testing.assert_allclose( result, np.array( [ [1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1], ] ), atol=1e-8, )