def _kraus_(self):
     return [
         cirq.unitary(cirq.S) * np.sqrt(1 / 3),
         cirq.unitary(cirq.X) * np.sqrt(2 / 3)
     ]
Пример #2
0
def test_fsim_unitary():
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=0)),
        np.array([
            [1, 0, 0, 0],
            [0, 1, 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1],
        ]),
        atol=1e-8,
    )

    # Theta
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=np.pi / 2, phi=0)),
        np.array([
            [1, 0, 0, 0],
            [0, 0, -1j, 0],
            [0, -1j, 0, 0],
            [0, 0, 0, 1],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=-np.pi / 2, phi=0)),
        np.array([
            [1, 0, 0, 0],
            [0, 0, 1j, 0],
            [0, 1j, 0, 0],
            [0, 0, 0, 1],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=np.pi, phi=0)),
        np.array([
            [1, 0, 0, 0],
            [0, -1, 0, 0],
            [0, 0, -1, 0],
            [0, 0, 0, 1],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=2*np.pi, phi=0)),
        cirq.unitary(cirq.FSimGate(theta=0, phi=0)),
        atol=1e-8)
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=-np.pi/2, phi=0)),
        cirq.unitary(cirq.FSimGate(theta=3/2*np.pi, phi=0)),
        atol=1e-8)

    # Phi
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=np.pi / 2)),
        np.array([
            [1, 0, 0, 0],
            [0, 1, 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, -1j],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=-np.pi / 2)),
        np.array([
            [1, 0, 0, 0],
            [0, 1, 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 1j],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=np.pi)),
        np.array([
            [1, 0, 0, 0],
            [0, 1, 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, -1],
        ]),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=0)),
        cirq.unitary(cirq.FSimGate(theta=0, phi=2*np.pi)),
        atol=1e-8)
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=0, phi=-np.pi/2)),
        cirq.unitary(cirq.FSimGate(theta=0, phi=3/2*np.pi)),
        atol=1e-8)

    # Both.
    s = np.sqrt(0.5)
    np.testing.assert_allclose(
        cirq.unitary(cirq.FSimGate(theta=np.pi / 4, phi=np.pi / 3)),
        np.array([
            [1, 0, 0, 0],
            [0, s, -1j * s, 0],
            [0, -1j * s, s, 0],
            [0, 0, 0, 0.5 - 1j * np.sqrt(0.75)],
        ]),
        atol=1e-8,
    )
Пример #3
0
def test_controlled_mixture():
    c_yes = cirq.ControlledGate(sub_gate=cirq.phase_flip(0.25), num_controls=1)
    assert cirq.has_mixture(c_yes)
    assert cirq.approx_eq(cirq.mixture(c_yes), [(0.75, np.eye(4)),
                                                (0.25, cirq.unitary(cirq.CZ))])
Пример #4
0
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(cirq.Symbol('a')))
    assert cirq.unitary(CExpZinGate(cirq.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)
Пример #5
0
 def _channel_(self):
     return [cirq.unitary(op) for _, op, in self._prob_op_pairs]
Пример #6
0
 def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
     if cirq.is_parameterized(self):
         return NotImplemented
     z = cirq.unitary(cirq.Z**self.phase_exponent)
     x = cirq.unitary(cirq.X**self.exponent)
     return np.dot(np.dot(z, x), np.conj(z))
Пример #7
0
 def _channel_(self):
     return [
         cirq.unitary(cirq.X) * np.sqrt(0.999),
         np.eye(2) * 0,
     ]
Пример #8
0
 def _wrap_in_matrix_gate(ops: cirq.OP_TREE):
     op = _wrap_in_cop(ops, 'temp')
     return cirq.MatrixGate(cirq.unitary(op)).on(*op.qubits)
Пример #9
0
def test_tagged_operation_forwards_protocols():
    """The results of all protocols applied to an operation with a tag should
    be equivalent to the result without tags.
    """
    q1 = cirq.GridQubit(1, 1)
    q2 = cirq.GridQubit(1, 2)
    h = cirq.H(q1)
    tag = 'tag1'
    tagged_h = cirq.H(q1).with_tags(tag)

    np.testing.assert_equal(cirq.unitary(tagged_h), cirq.unitary(h))
    assert cirq.has_unitary(tagged_h)
    assert cirq.decompose(tagged_h) == cirq.decompose(h)
    assert cirq.pauli_expansion(tagged_h) == cirq.pauli_expansion(h)
    assert cirq.equal_up_to_global_phase(h, tagged_h)
    assert np.isclose(cirq.kraus(h), cirq.kraus(tagged_h)).all()

    assert cirq.measurement_key_name(
        cirq.measure(q1, key='blah').with_tags(tag)) == 'blah'

    parameterized_op = cirq.XPowGate(
        exponent=sympy.Symbol('t'))(q1).with_tags(tag)
    assert cirq.is_parameterized(parameterized_op)
    resolver = cirq.study.ParamResolver({'t': 0.25})
    assert cirq.resolve_parameters(
        parameterized_op,
        resolver) == cirq.XPowGate(exponent=0.25)(q1).with_tags(tag)
    assert cirq.resolve_parameters_once(
        parameterized_op,
        resolver) == cirq.XPowGate(exponent=0.25)(q1).with_tags(tag)

    y = cirq.Y(q1)
    tagged_y = cirq.Y(q1).with_tags(tag)
    assert tagged_y**0.5 == cirq.YPowGate(exponent=0.5)(q1)
    assert tagged_y * 2 == (y * 2)
    assert 3 * tagged_y == (3 * y)
    assert cirq.phase_by(y, 0.125, 0) == cirq.phase_by(tagged_y, 0.125, 0)
    controlled_y = tagged_y.controlled_by(q2)
    assert controlled_y.qubits == (
        q2,
        q1,
    )
    assert isinstance(controlled_y, cirq.Operation)
    assert not isinstance(controlled_y, cirq.TaggedOperation)

    clifford_x = cirq.SingleQubitCliffordGate.X(q1)
    tagged_x = cirq.SingleQubitCliffordGate.X(q1).with_tags(tag)
    assert cirq.commutes(clifford_x, clifford_x)
    assert cirq.commutes(tagged_x, clifford_x)
    assert cirq.commutes(clifford_x, tagged_x)
    assert cirq.commutes(tagged_x, tagged_x)

    assert cirq.trace_distance_bound(y**0.001) == cirq.trace_distance_bound(
        (y**0.001).with_tags(tag))

    flip = cirq.bit_flip(0.5)(q1)
    tagged_flip = cirq.bit_flip(0.5)(q1).with_tags(tag)
    assert cirq.has_mixture(tagged_flip)
    assert cirq.has_kraus(tagged_flip)

    flip_mixture = cirq.mixture(flip)
    tagged_mixture = cirq.mixture(tagged_flip)
    assert len(tagged_mixture) == 2
    assert len(tagged_mixture[0]) == 2
    assert len(tagged_mixture[1]) == 2
    assert tagged_mixture[0][0] == flip_mixture[0][0]
    assert np.isclose(tagged_mixture[0][1], flip_mixture[0][1]).all()
    assert tagged_mixture[1][0] == flip_mixture[1][0]
    assert np.isclose(tagged_mixture[1][1], flip_mixture[1][1]).all()

    qubit_map = {q1: 'q1'}
    qasm_args = cirq.QasmArgs(qubit_id_map=qubit_map)
    assert cirq.qasm(h, args=qasm_args) == cirq.qasm(tagged_h, args=qasm_args)

    cirq.testing.assert_has_consistent_apply_unitary(tagged_h)
Пример #10
0
def test_canonicalization():
    def f(x, z, a):
        return cirq.PhasedXZGate(x_exponent=x, z_exponent=z, axis_phase_exponent=a)

    # Canonicalizations are equivalent.
    eq = cirq.testing.EqualsTester()
    eq.add_equality_group(f(-1, 0, 0), f(-3, 0, 0), f(1, 1, 0.5))
    """
    # Canonicalize X exponent (-1, +1].
    if isinstance(x, numbers.Real):
        x %= 2
        if x > 1:
            x -= 2
    # Axis phase exponent is irrelevant if there is no X exponent.
    # Canonicalize Z exponent (-1, +1].
    if isinstance(z, numbers.Real):
        z %= 2
        if z > 1:
            z -= 2

    # Canonicalize axis phase exponent into (-0.5, +0.5].
    if isinstance(a, numbers.Real):
        a %= 2
        if a > 1:
            a -= 2
        if a <= -0.5:
            a += 1
            x = -x
        elif a > 0.5:
            a -= 1
            x = -x
    """

    # X rotation gets canonicalized.
    t = f(3, 0, 0)._canonical()
    assert t.x_exponent == 1
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == 0
    t = f(1.5, 0, 0)._canonical()
    assert t.x_exponent == -0.5
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == 0

    # Z rotation gets canonicalized.
    t = f(0, 3, 0)._canonical()
    assert t.x_exponent == 0
    assert t.z_exponent == 1
    assert t.axis_phase_exponent == 0
    t = f(0, 1.5, 0)._canonical()
    assert t.x_exponent == 0
    assert t.z_exponent == -0.5
    assert t.axis_phase_exponent == 0

    # Axis phase gets canonicalized.
    t = f(0.5, 0, 2.25)._canonical()
    assert t.x_exponent == 0.5
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == 0.25
    t = f(0.5, 0, 1.25)._canonical()
    assert t.x_exponent == -0.5
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == 0.25
    t = f(0.5, 0, 0.75)._canonical()
    assert t.x_exponent == -0.5
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == -0.25

    # 180 degree rotations don't need a virtual Z.
    t = f(1, 1, 0.5)._canonical()
    assert t.x_exponent == 1
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == 0
    t = f(1, 0.25, 0.5)._canonical()
    assert t.x_exponent == 1
    assert t.z_exponent == 0
    assert t.axis_phase_exponent == -0.375
    cirq.testing.assert_allclose_up_to_global_phase(
        cirq.unitary(t), cirq.unitary(f(1, 0.25, 0.5)), atol=1e-8
    )

    # Axis phase is irrelevant when not rotating.
    t = f(0, 0.25, 0.5)._canonical()
    assert t.x_exponent == 0
    assert t.z_exponent == 0.25
    assert t.axis_phase_exponent == 0
def test_decompose_specific_matrices():
    for gate in [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.I, cirq.T, cirq.S]:
        for controls_count in range(0, 7):
            _test_decompose(cirq.unitary(gate), controls_count)
Пример #12
0
def test_from_matrix_close_unitary(unitary: np.ndarray):
    cirq.testing.assert_allclose_up_to_global_phase(
        cirq.unitary(cirq.PhasedXZGate.from_matrix(unitary)), unitary, atol=1e-8
    )
Пример #13
0
def test_from_matrix():
    # Axis rotations.
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.X ** 0.1)),
        cirq.PhasedXZGate(x_exponent=0.1, z_exponent=0, axis_phase_exponent=0),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.X ** -0.1)),
        cirq.PhasedXZGate(x_exponent=-0.1, z_exponent=0, axis_phase_exponent=0),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Y ** 0.1)),
        cirq.PhasedXZGate(x_exponent=0.1, z_exponent=0, axis_phase_exponent=0.5),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Y ** -0.1)),
        cirq.PhasedXZGate(x_exponent=-0.1, z_exponent=0, axis_phase_exponent=0.5),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Z ** -0.1)),
        cirq.PhasedXZGate(x_exponent=0, z_exponent=-0.1, axis_phase_exponent=0),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Z ** 0.1)),
        cirq.PhasedXZGate(x_exponent=0, z_exponent=0.1, axis_phase_exponent=0),
        atol=1e-8,
    )

    # Pauli matrices.
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(np.eye(2)),
        cirq.PhasedXZGate(x_exponent=0, z_exponent=0, axis_phase_exponent=0),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.X)),
        cirq.PhasedXZGate(x_exponent=1, z_exponent=0, axis_phase_exponent=0),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Y)),
        cirq.PhasedXZGate(x_exponent=1, z_exponent=0, axis_phase_exponent=0.5),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.PhasedXZGate.from_matrix(cirq.unitary(cirq.Z)),
        cirq.PhasedXZGate(x_exponent=0, z_exponent=1, axis_phase_exponent=0),
        atol=1e-8,
    )

    # Round trips.
    a = random.random()
    b = random.random()
    c = random.random()
    g = cirq.PhasedXZGate(x_exponent=a, z_exponent=b, axis_phase_exponent=c)
    assert cirq.approx_eq(cirq.PhasedXZGate.from_matrix(cirq.unitary(g)), g, atol=1e-8)
 def _kraus_(self):
     return [cirq.unitary(cirq.X) * np.sqrt(0.999), np.eye(2) * 0]
Пример #15
0
def random_single_qubit_unitary():
    a, b, c = np.random.random(3) * 2 * np.pi
    circuit = cirq.unitary(cirq.rz(a)) @ cirq.unitary(
        cirq.ry(b)) @ cirq.unitary(cirq.rz(c))
    assert np.allclose(circuit.conj().T @ circuit, np.eye(2))
    return circuit
Пример #16
0
 def extract_entangling_error(match_id: noise_utils.OpIdentifier):
     """Gets the entangling error component of depol_errors[match_id]."""
     unitary_err = cirq.unitary(self.fsim_errors[match_id])
     fid = gate_tabulation_math_utils.unitary_entanglement_fidelity(unitary_err, np.eye(4))
     return 1 - fid
Пример #17
0
 def _unitary_(self) -> np.array:
     """Implements Cirq's `unitary` protocol for this object."""
     p = np.exp(-np.pi * 1j * self.phase_exponent)
     return (np.diag([1, p, 1 / p, 1]) @ cirq.unitary(self.engine_gate)
             @ np.diag([1, 1 / p, p, 1]))
Пример #18
0
 def ideal_unitary(self) -> np.ndarray:
     return cirq.unitary(self._circuit)
Пример #19
0
 def random_clifford_gate():
     matrix = np.eye(2)
     for _ in range(10):
         matrix = matrix @ cirq.unitary(np.random.choice((cirq.H, cirq.S)))
     matrix *= np.exp(1j * np.random.uniform(0, 2 * np.pi))
     return cirq.MatrixGate(matrix)
Пример #20
0
def test_single_qubit_init():
    m = np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5)
    x2 = cirq.SingleQubitMatrixGate(m)
    assert np.alltrue(cirq.unitary(x2) == m)
Пример #21
0
 def _channel_(self):
     return [
         cirq.unitary(cirq.S) * np.sqrt(1 / 3),
         cirq.unitary(cirq.X) * np.sqrt(2 / 3),
     ]
Пример #22
0
def test_two_qubit_init():
    x2 = cirq.TwoQubitMatrixGate(QFT2)
    assert np.alltrue(cirq.unitary(x2) == QFT2)
Пример #23
0
def test_matrix_is_exact_for_quarter_turn():
    np.testing.assert_equal(cirq.unitary(CExpZinGate(1)),
                            np.diag([1, 1, 1j, -1j]))
Пример #24
0
"""Tests for gate_compilation.py"""
import numpy as np
import pytest

import cirq
from cirq import value
from cirq_google.optimizers.two_qubit_gates.gate_compilation import (
    gate_product_tabulation,
    GateTabulation,
)
from cirq_google.optimizers.two_qubit_gates.math_utils import unitary_entanglement_fidelity
from cirq.testing import random_special_unitary, assert_equivalent_repr

_rng = value.parse_random_state(11)  # for determinism

sycamore_tabulation = gate_product_tabulation(cirq.unitary(
    cirq.FSimGate(np.pi / 2, np.pi / 6)),
                                              0.2,
                                              random_state=_rng)

sqrt_iswap_tabulation = gate_product_tabulation(cirq.unitary(
    cirq.FSimGate(np.pi / 4, np.pi / 24)),
                                                0.1,
                                                random_state=_rng)

_random_2Q_unitaries = np.array(
    [random_special_unitary(4, random_state=_rng) for _ in range(100)])


@pytest.mark.parametrize('tabulation',
                         [sycamore_tabulation, sqrt_iswap_tabulation])
@pytest.mark.parametrize('target', _random_2Q_unitaries)
Пример #25
0
 def _mixture_(self):
     return [(prob, cirq.unitary(op)) for prob, op, in self._prob_op_pairs]
Пример #26
0
def test_unitary():
    np.testing.assert_equal(cirq.unitary(cirq.X), cirq.unitary(cirq.X))
    np.testing.assert_equal(cirq.unitary(cirq.Y), cirq.unitary(cirq.Y))
    np.testing.assert_equal(cirq.unitary(cirq.Z), cirq.unitary(cirq.Z))
Пример #27
0
        (cirq.SWAP, True),
        (cirq.CCZ, True),
        (cirq.ControlledGate(cirq.ControlledGate(cirq.CCZ)), True),
        (GateUsingWorkspaceForApplyUnitary(), True),
        (GateAllocatingNewSpaceForResult(), True),
        (cirq.IdentityGate(qid_shape=(3, 4)), True),
        (
            cirq.ControlledGate(
                cirq.XXPowGate(exponent=0.25, global_shift=-0.5),
                num_controls=2,
                control_values=(1, (1, 0)),
            ),
            True,
        ),
        # Single qudit gate with dimension 4.
        (cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H), ) * 2),
                         qid_shape=(4, )), False),
        (cirq.MatrixGate(cirq.testing.random_unitary(
            4, random_state=1234)), False),
        (cirq.XX**sympy.Symbol("s"), True),
        (cirq.CZ**sympy.Symbol("s"), True),
    ],
)
def test_controlled_gate_is_consistent(gate: cirq.Gate,
                                       should_decompose_to_target):
    cgate = cirq.ControlledGate(gate)
    cirq.testing.assert_implements_consistent_protocols(cgate)
    cirq.testing.assert_decompose_ends_at_default_gateset(
        cgate, ignore_known_gates=not should_decompose_to_target)

Пример #28
0
                                                    cirq.unitary(decomposed),
                                                    atol=1e-8)

    # Should have decomposed into two Sycamores.
    multi_qubit_ops = [
        e for e in decomposed.all_operations() if len(e.qubits) > 1
    ]
    assert len(multi_qubit_ops) == 2
    assert all(
        isinstance(e.gate, cirq_google.SycamoreGate) for e in multi_qubit_ops)


@pytest.mark.parametrize(
    'gate',
    [
        cirq.MatrixGate(cirq.unitary(cirq.CX), qid_shape=(2, 2)),
        cirq.ISWAP,
        cirq.SWAP,
        cirq.CNOT,
        cirq.CZ,
        cirq.PhasedISwapPowGate(exponent=1.0),
        cirq.PhasedISwapPowGate(exponent=1.0, phase_exponent=0.33),
        cirq.PhasedISwapPowGate(exponent=0.66, phase_exponent=0.25),
        *[cirq.givens(theta) for theta in np.linspace(0, 2 * np.pi, 30)],
        *[
            cirq.ZZPowGate(exponent=2 * phi / np.pi)
            for phi in np.linspace(0, 2 * np.pi, 30)
        ],
        *[
            cirq.CZPowGate(exponent=phi / np.pi)
            for phi in np.linspace(0, 2 * np.pi, 30)
 def _mixture_(self):
     return [(1 / len(self.gate_options), cirq.unitary(g))
             for g in self.gate_options]
Пример #30
0
def assert_gates_implement_unitary(gates: List[cirq.SingleQubitGate],
                                   intended_effect: np.ndarray):
    actual_effect = cirq.dot(*[cirq.unitary(g) for g in reversed(gates)])
    assert cirq.allclose_up_to_global_phase(actual_effect, intended_effect)