def test_pass_operations_over_double(shift, t_or_f1, t_or_f2, neg): q0, q1, q2 = _make_qubits(3) X, Y, Z = (pauli + shift for pauli in cirq.Pauli.XYZ) op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q2: Y}, neg) ps_after = cirq.PauliString({q0: Z, q2: Y}, neg) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q2: Y}, neg) ps_after = cirq.PauliString({q0: Z, q2: Y, q1: X}, neg) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, neg) ps_after = cirq.PauliString({q1: Y}, neg) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, neg) ps_after = cirq.PauliString({q0: X, q1: Z}, neg ^ t_or_f1 ^ t_or_f2) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(X, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, neg) ps_after = cirq.PauliString({q0: Y, q1: Z}, not neg ^ t_or_f1 ^ t_or_f2) _assert_pass_over([op0], ps_before, ps_after)
def test_pass_operations_over_double(shift, t_or_f1, t_or_f2, neg): sign = -1 if neg else +1 q0, q1, q2 = _make_qubits(3) X, Y, Z = (cirq.Pauli.by_relative_index(pauli, shift) for pauli in (cirq.X, cirq.Y, cirq.Z)) op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q2: Y}, sign) ps_after = cirq.PauliString({q0: Z, q2: Y}, sign) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q2: Y}, sign) ps_after = cirq.PauliString({q0: Z, q2: Y, q1: X}, sign) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, sign) ps_after = cirq.PauliString({q1: Y}, sign) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, sign) ps_after = cirq.PauliString({q0: X, q1: Z}, -1 if neg ^ t_or_f1 ^ t_or_f2 else +1) _assert_pass_over([op0], ps_before, ps_after) op0 = cirq.PauliInteractionGate(X, t_or_f1, X, t_or_f2)(q0, q1) ps_before = cirq.PauliString({q0: Z, q1: Y}, sign) ps_after = cirq.PauliString({q0: Y, q1: Z}, +1 if neg ^ t_or_f1 ^ t_or_f2 else -1) _assert_pass_over([op0], ps_before, ps_after)
def test_text_diagrams(): q0, q1 = cirq.NamedQubit('q0'), cirq.NamedQubit('q1') circuit = cirq.Circuit.from_ops( cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, True)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, True)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.Y, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Y, False, cirq.Pauli.Z, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Y, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Y, True, cirq.Pauli.Z, True)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, True, cirq.Pauli.Y, True)(q0, q1)) assert circuit.to_text_diagram().strip() == """ q0: ───X───(-X)───X──────(-X)───X───Y───@───(-Y)───(-@)─── │ │ │ │ │ │ │ │ │ q1: ───X───X──────(-X)───(-X)───Y───@───Y───(-@)───(-Y)─── """.strip()
def test_exponent_shifts_are_equal(): eq = cirq.testing.EqualsTester() eq.add_equality_group( cirq.PauliInteractionGate(cirq.X, False, cirq.X, False, exponent=e) for e in [0.1, 0.1, 2.1, -1.9, 4.1]) eq.add_equality_group( cirq.PauliInteractionGate(cirq.X, True, cirq.X, False, exponent=e) for e in [0.1, 0.1, 2.1, -1.9, 4.1]) eq.add_equality_group( cirq.PauliInteractionGate(cirq.Y, False, cirq.Z, False, exponent=e) for e in [0.1, 0.1, 2.1, -1.9, 4.1]) eq.add_equality_group( cirq.PauliInteractionGate(cirq.Z, False, cirq.Y, True, exponent=e) for e in [0.1, 0.1, 2.1, -1.9, 4.1])
def test_repr_consistent(): assert repr(cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, False)) == ( 'cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, False)' ) assert repr(cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.Y, True)**0.5) == ( '(cirq.PauliInteractionGate(cirq.Pauli.X, False, ' 'cirq.Pauli.Y, True)**0.5)' ) g = cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.Y, True) cirq.testing.assert_equivalent_repr(g) cirq.testing.assert_equivalent_repr(g**0.1) cirq.testing.assert_equivalent_repr(g**5)
def test_decomposes_despite_symbol(): q0, q1 = cirq.NamedQubit('q0'), cirq.NamedQubit('q1') gate = cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.X, False, half_turns=cirq.Symbol('x')) op_tree = gate.default_decompose([q0, q1]) ops = tuple(cirq.flatten_op_tree(op_tree)) assert ops
def _all_interaction_gates(half_turns_list=(1,)): for pauli0, invert0, pauli1, invert1, half_turns in itertools.product( cirq.Pauli.XYZ, _bools, cirq.Pauli.XYZ, _bools, half_turns_list): yield cirq.PauliInteractionGate(pauli0, invert0, pauli1, invert1, half_turns=half_turns)
def test_decomposes_despite_symbol(): q0, q1 = cirq.NamedQubit('q0'), cirq.NamedQubit('q1') gate = cirq.PauliInteractionGate(cirq.Z, False, cirq.X, False, exponent=sympy.Symbol('x')) assert cirq.decompose_once_with_qubits(gate, [q0, q1])
def test_eq_ne_and_hash(): eq = EqualsTester() for pauli0, invert0, pauli1, invert1, half_turns in itertools.product( cirq.Pauli.XYZ, _bools, cirq.Pauli.XYZ, _bools, (0.1, -0.25, 1)): gate_gen = lambda offset: cirq.PauliInteractionGate( pauli0, invert0, pauli1, invert1, half_turns=half_turns + offset) eq.add_equality_group(gate_gen(0), gate_gen(0), gate_gen(2), gate_gen(-4), gate_gen(-2))
def _all_interaction_gates(exponents=(1,)): for pauli0, invert0, pauli1, invert1, e in itertools.product( cirq.Pauli.XYZ, _bools, cirq.Pauli.XYZ, _bools, exponents): yield cirq.PauliInteractionGate(pauli0, invert0, pauli1, invert1, exponent=e)
def test_eq_ne_and_hash(): eq = cirq.testing.EqualsTester() for pauli0, invert0, pauli1, invert1, e in itertools.product( _paulis, _bools, _paulis, _bools, (0.125, -0.25, 1)): eq.add_equality_group( cirq.PauliInteractionGate(pauli0, invert0, pauli1, invert1, exponent=e))
def test_exponent(): cnot = cirq.PauliInteractionGate(cirq.Z, False, cirq.X, False) np.testing.assert_almost_equal( cirq.unitary(cnot**0.5), np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0.5+0.5j, 0.5-0.5j], [0, 0, 0.5-0.5j, 0.5+0.5j], ]))
def test_exponent(): cnot = cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.X, False) np.testing.assert_almost_equal( cirq.unitary(cnot**0.5), np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0.5+0.5j, 0.5-0.5j], [0, 0, 0.5-0.5j, 0.5+0.5j], ])) cirq.testing.assert_decompose_is_consistent_with_unitary(cnot) cirq.testing.assert_decompose_is_consistent_with_unitary(cnot**0.25)
def test_setters_deprecated(): gate = cirq.PauliInteractionGate(cirq.X, False, cirq.X, False) with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): gate.pauli0 = cirq.Y assert gate.pauli0 == cirq.Y with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): gate.pauli1 = cirq.Y assert gate.pauli1 == cirq.Y with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): gate.invert0 = True assert gate.invert0 with cirq.testing.assert_deprecated('mutators', deadline='v0.15'): gate.invert1 = True assert gate.invert1
def test_exponent(): cnot = cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.X, False) np.testing.assert_almost_equal( (cnot**0.5).matrix(), np.array([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0.5+0.5j, 0.5-0.5j], [0, 0, 0.5-0.5j, 0.5+0.5j], ])) # Matrix must be consistent with decomposition. q0, q1 = cirq.NamedQubit('q0'), cirq.NamedQubit('q1') g = cnot**0.25 cirq.testing.assert_allclose_up_to_global_phase( g.matrix(), cirq.Circuit.from_ops(g.default_decompose([q0, q1]) ).to_unitary_matrix(), rtol=1e-7, atol=1e-7)
cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Y, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Y, True, cirq.Pauli.Z, True)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, True, cirq.Pauli.Y, True)(q0, q1)) assert circuit.to_text_diagram().strip() == """ q0: ───X───(-X)───X──────(-X)───X───Y───@───(-Y)───(-@)─── │ │ │ │ │ │ │ │ │ q1: ───X───X──────(-X)───(-X)───Y───@───Y───(-@)───(-Y)─── """.strip() @pytest.mark.parametrize( 'gate,gate_repr', ((cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, False), 'PauliInteractionGate(+X, +X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, False), 'PauliInteractionGate(-X, +X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, True), 'PauliInteractionGate(+X, -X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, True), 'PauliInteractionGate(-X, -X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.Y, False), 'PauliInteractionGate(+X, +Y)'), (cirq.PauliInteractionGate(cirq.Pauli.Y, False, cirq.Pauli.Z, False), 'PauliInteractionGate(+Y, +Z)'), (cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Y, False), 'PauliInteractionGate(+Z, +Y)'), (cirq.PauliInteractionGate(cirq.Pauli.Y, True, cirq.Pauli.Z, True), 'PauliInteractionGate(-Y, -Z)'), (cirq.PauliInteractionGate(cirq.Pauli.Z, True, cirq.Pauli.Y,
def gate_gen(offset): return cirq.PauliInteractionGate( pauli0, invert0, pauli1, invert1, exponent=e + offset)
def stim_to_cirq_gate_table( ) -> Dict[str, Union[Tuple, cirq.Gate, Callable[[float], cirq.Gate]]]: return { "R": cirq.ResetChannel(), "I": cirq.I, "X": cirq.X, "Y": cirq.Y, "Z": cirq.Z, "H_XY": cirq.SingleQubitCliffordGate.from_xz_map(x_to=(cirq.Y, False), z_to=(cirq.Z, True)), "H": cirq.H, "H_YZ": cirq.SingleQubitCliffordGate.from_xz_map(x_to=(cirq.X, True), z_to=(cirq.Y, False)), "SQRT_X": cirq.X**0.5, "SQRT_X_DAG": cirq.X**-0.5, "SQRT_Y": cirq.Y**0.5, "SQRT_Y_DAG": cirq.Y**-0.5, "S": cirq.S, "S_DAG": cirq.S**-1, "SWAP": cirq.SWAP, "ISWAP": cirq.ISWAP, "ISWAP_DAG": cirq.ISWAP**-1, "XCX": cirq.PauliInteractionGate(cirq.X, False, cirq.X, False), "XCY": cirq.PauliInteractionGate(cirq.X, False, cirq.Y, False), "XCZ": cirq.PauliInteractionGate(cirq.X, False, cirq.Z, False), "YCX": cirq.PauliInteractionGate(cirq.Y, False, cirq.X, False), "YCY": cirq.PauliInteractionGate(cirq.Y, False, cirq.Y, False), "YCZ": cirq.PauliInteractionGate(cirq.Y, False, cirq.Z, False), "CX": cirq.CNOT, "CY": cirq.Y.controlled(1), "CZ": cirq.CZ, "DEPOLARIZE1": lambda arg: cirq.DepolarizingChannel(arg, 1), "DEPOLARIZE2": lambda arg: cirq.DepolarizingChannel(arg, 2), "X_ERROR": lambda arg: cirq.X.with_probability(arg), "Y_ERROR": lambda arg: cirq.Y.with_probability(arg), "Z_ERROR": lambda arg: cirq.Z.with_probability(arg), "DETECTOR": (), "OBSERVABLE_INCLUDE": (), "TICK": (), }
def test_repr(): cnot = cirq.PauliInteractionGate(cirq.Z, False, cirq.X, False) cirq.testing.assert_equivalent_repr(cnot)
cirq.PauliInteractionGate(cirq.Pauli.Y, False, cirq.Pauli.Z, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Y, False)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Y, True, cirq.Pauli.Z, True)(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, True, cirq.Pauli.Y, True)(q0, q1)) assert circuit.to_text_diagram().strip() == """ q0: ───X───(-X)───X──────(-X)───X───Y───@───(-Y)───(-@)─── │ │ │ │ │ │ │ │ │ q1: ───X───X──────(-X)───(-X)───Y───@───Y───(-@)───(-Y)─── """.strip() @pytest.mark.parametrize('gate,gate_repr', ( (cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, False), 'cirq.PauliInteractionGate(+X, +X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, False), 'cirq.PauliInteractionGate(-X, +X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.X, True ), 'cirq.PauliInteractionGate(+X, -X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, True, cirq.Pauli.X, True ), 'cirq.PauliInteractionGate(-X, -X)'), (cirq.PauliInteractionGate(cirq.Pauli.X, False, cirq.Pauli.Y, False), 'cirq.PauliInteractionGate(+X, +Y)'), (cirq.PauliInteractionGate(cirq.Pauli.Y, False, cirq.Pauli.Z, False), 'cirq.PauliInteractionGate(+Y, +Z)'), (cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Y, False), 'cirq.PauliInteractionGate(+Z, +Y)'), (cirq.PauliInteractionGate(cirq.Pauli.Y, True, cirq.Pauli.Z, True ), 'cirq.PauliInteractionGate(-Y, -Z)'),
(cirq.Z(q0), cirq.CliffordGate.Z(q0)), (cirq.X(q0)**0.5, cirq.CliffordGate.X_sqrt(q0)), (cirq.Y(q0)**0.5, cirq.CliffordGate.Y_sqrt(q0)), (cirq.Z(q0)**0.5, cirq.CliffordGate.Z_sqrt(q0)), (cirq.X(q0)**-0.5, cirq.CliffordGate.X_nsqrt(q0)), (cirq.Y(q0)**-0.5, cirq.CliffordGate.Y_nsqrt(q0)), (cirq.Z(q0)**-0.5, cirq.CliffordGate.Z_nsqrt(q0)), (cirq.X(q0)**0.25, PauliStringPhasor(cirq.PauliString.from_single(q0, cirq.Pauli.X))**0.25), (cirq.Y(q0)**0.25, PauliStringPhasor(cirq.PauliString.from_single(q0, cirq.Pauli.Y))**0.25), (cirq.Z(q0)**0.25, PauliStringPhasor(cirq.PauliString.from_single(q0, cirq.Pauli.Z))**0.25), (cirq.X(q0)**0, ()), (cirq.CZ(q0, q1), cirq.PauliInteractionGate(cirq.Pauli.Z, False, cirq.Pauli.Z, False) (q0, q1)), (cirq.MeasurementGate('key')(q0, q1), cirq.MeasurementGate('key')(q0, q1)), ))(cirq.LineQubit(0), cirq.LineQubit(1))) def test_converts_various_ops(op, expected_ops): before = cirq.Circuit.from_ops(op) expected = cirq.Circuit.from_ops(expected_ops, strategy=cirq.InsertStrategy.EARLIEST) after = converted_gate_set(before) assert after == expected cirq.testing.assert_allclose_up_to_global_phase( before.to_unitary_matrix(), after.to_unitary_matrix(qubits_that_should_be_present=op.qubits), atol=1e-7) cirq.testing.assert_allclose_up_to_global_phase( after.to_unitary_matrix(qubits_that_should_be_present=op.qubits),
def gate_to_stim_append_func( ) -> Dict[cirq.Gate, Callable[[stim.Circuit, List[int]], None]]: """A dictionary mapping specific gate instances to stim circuit appending functions.""" x = (cirq.X, False) y = (cirq.Y, False) z = (cirq.Z, False) nx = (cirq.X, True) ny = (cirq.Y, True) nz = (cirq.Z, True) def do_nothing(c, t): pass def use( *gates: str, individuals: Sequence[Tuple[str, int]] = () ) -> Callable[[stim.Circuit, List[int]], None]: if len(gates) == 1 and not individuals: (g, ) = gates return lambda c, t: c.append_operation(g, t) if not individuals: def do(c, t): for g in gates: c.append_operation(g, t) else: def do(c, t): for g in gates: c.append_operation(g, t) for g, k in individuals: c.append_operation(g, [t[k]]) return do sqcg = cirq.SingleQubitCliffordGate.from_xz_map paulis = cast(List[cirq.Pauli], [cirq.X, cirq.Y, cirq.Z]) return { cirq.ResetChannel(): use("R"), # Identities. cirq.I: do_nothing, cirq.H**0: do_nothing, cirq.X**0: do_nothing, cirq.Y**0: do_nothing, cirq.Z**0: do_nothing, cirq.ISWAP**0: do_nothing, cirq.SWAP**0: do_nothing, # Common named gates. cirq.H: use("H"), cirq.X: use("X"), cirq.Y: use("Y"), cirq.Z: use("Z"), cirq.X**0.5: use("SQRT_X"), cirq.X**-0.5: use("SQRT_X_DAG"), cirq.Y**0.5: use("SQRT_Y"), cirq.Y**-0.5: use("SQRT_Y_DAG"), cirq.Z**0.5: use("SQRT_Z"), cirq.Z**-0.5: use("SQRT_Z_DAG"), cirq.CNOT: use("CNOT"), cirq.CZ: use("CZ"), cirq.ISWAP: use("ISWAP"), cirq.ISWAP**-1: use("ISWAP_DAG"), cirq.ISWAP**2: use("Z"), cirq.SWAP: use("SWAP"), cirq.X.controlled(1): use("CX"), cirq.Y.controlled(1): use("CY"), cirq.Z.controlled(1): use("CZ"), # All 24 cirq.SingleQubitCliffordGate instances. sqcg(x, y): use("SQRT_X_DAG"), sqcg(x, ny): use("SQRT_X"), sqcg(nx, y): use("H_YZ"), sqcg(nx, ny): use("H_YZ", "X"), sqcg(x, z): do_nothing, sqcg(x, nz): use("X"), sqcg(nx, z): use("Z"), sqcg(nx, nz): use("Y"), sqcg(y, x): use("S", "SQRT_Y"), sqcg(y, nx): use("S", "SQRT_Y_DAG"), sqcg(ny, x): use("S_DAG", "SQRT_Y"), sqcg(ny, nx): use("S_DAG", "SQRT_Y_DAG"), sqcg(y, z): use("S"), sqcg(y, nz): use("H_XY"), sqcg(ny, z): use("S_DAG"), sqcg(ny, nz): use("H_XY", "Z"), sqcg(z, x): use("H"), sqcg(z, nx): use("SQRT_Y_DAG"), sqcg(nz, x): use("SQRT_Y"), sqcg(nz, nx): use("H", "Y"), sqcg(z, y): use("SQRT_Y_DAG", "S_DAG"), sqcg(z, ny): use("SQRT_Y_DAG", "S"), sqcg(nz, y): use("SQRT_Y", "S"), sqcg(nz, ny): use("SQRT_Y", "S_DAG"), # All 36 cirq.PauliInteractionGate instances. **{ cirq.PauliInteractionGate(p0, s0, p1, s1): use(f"{p0}C{p1}", individuals=[(str(p1), 1)] * s0 + [(str(p0), 0)] * s1) for p0, s0, p1, s1 in itertools.product(paulis, [False, True], repeat=2) }, }