def _decompose(self, qubits): # qubits = [c1, c2, ..., cn, T] # Will "bootstrap" an ancilla yield ops.H(qubits[-1]) yield CnxLinearBorrowedBit(*(qubits[:-2] + [qubits[-1]] + [qubits[-2]])).default_decompose() yield ops.Z(qubits[-1])**-0.25 yield ops.CNOT(qubits[-2], qubits[-1]) yield ops.Z(qubits[-1])**0.25 yield CnxLinearBorrowedBit(*(qubits[:-2] + [qubits[-1]] + [qubits[-2]])).default_decompose() yield ops.Z(qubits[-1])**-0.25 yield ops.CNOT(qubits[-2], qubits[-1]) yield ops.Z(qubits[-1])**0.25 yield ops.H(qubits[-1]) # Perform a +1 Gate on all of the top bits with bottom bit as borrowed yield IncrementLinearWithBorrowedBitOp(*qubits) # Perform -rt Z gates for i in range(1, len(qubits) - 1): yield ops.Z(qubits[i])**(-1 * 1/(2**(len(qubits) - i))) # Perform a -1 Gate on the top bits for i in range(len(qubits) - 1): yield ops.X(qubits[i]) yield IncrementLinearWithBorrowedBitOp(*qubits) for i in range(len(qubits) - 1): yield ops.X(qubits[i]) # Perform rt Z gates for i in range(1, len(qubits) - 1): yield ops.Z(qubits[i])**(1/(2**(len(qubits) - i))) yield ops.Z(qubits[0])**(1/(2**(len(qubits) - 1)))
def test_two_qubit_state_tomography(): # Check that the density matrices of the four Bell states closely match # the ideal cases. simulator = sim.Simulator() q_0 = GridQubit(0, 0) q_1 = GridQubit(0, 1) circuit_00 = circuits.Circuit.from_ops(ops.H(q_0), ops.CNOT(q_0, q_1)) circuit_01 = circuits.Circuit.from_ops(ops.X(q_1), ops.H(q_0), ops.CNOT(q_0, q_1)) circuit_10 = circuits.Circuit.from_ops(ops.X(q_0), ops.H(q_0), ops.CNOT(q_0, q_1)) circuit_11 = circuits.Circuit.from_ops(ops.X(q_0), ops.X(q_1), ops.H(q_0), ops.CNOT(q_0, q_1)) act_rho_00 = two_qubit_state_tomography(simulator, q_0, q_1, circuit_00, 100000).data act_rho_01 = two_qubit_state_tomography(simulator, q_0, q_1, circuit_01, 100000).data act_rho_10 = two_qubit_state_tomography(simulator, q_0, q_1, circuit_10, 100000).data act_rho_11 = two_qubit_state_tomography(simulator, q_0, q_1, circuit_11, 100000).data tar_rho_00 = np.outer([1.0, 0, 0, 1.0], [1.0, 0, 0, 1.0]) / 2.0 tar_rho_01 = np.outer([0, 1.0, 1.0, 0], [0, 1.0, 1.0, 0]) / 2.0 tar_rho_10 = np.outer([1.0, 0, 0, -1.0], [1.0, 0, 0, -1.0]) / 2.0 tar_rho_11 = np.outer([0, 1.0, -1.0, 0], [0, 1.0, -1.0, 0]) / 2.0 np.testing.assert_almost_equal(act_rho_00, tar_rho_00, decimal=1) np.testing.assert_almost_equal(act_rho_01, tar_rho_01, decimal=1) np.testing.assert_almost_equal(act_rho_10, tar_rho_10, decimal=1) np.testing.assert_almost_equal(act_rho_11, tar_rho_11, decimal=1)
def test_teleportation_diagram(): ali = ops.NamedQubit('alice') car = ops.NamedQubit('carrier') bob = ops.NamedQubit('bob') circuit = Circuit.from_ops( ops.H(car), ops.CNOT(car, bob), ops.X(ali)**0.5, ops.CNOT(ali, car), ops.H(ali), [ops.measure(ali), ops.measure(car)], ops.CNOT(car, bob), ops.CZ(ali, bob)) diagram = circuit_to_latex_using_qcircuit( circuit, qubit_order=ops.QubitOrder.explicit([ali, car, bob])) assert diagram.strip() == """ \\Qcircuit @R=1em @C=0.75em { \\\\ \\lstick{\\text{alice}}& \\qw &\\qw & \\gate{\\text{X}^{0.5}} \\qw & \\control \\qw & \\gate{\\text{H}} \\qw & \\meter \\qw &\\qw & \\control \\qw &\\qw\\\\ \\lstick{\\text{carrier}}& \\qw & \\gate{\\text{H}} \\qw & \\control \\qw & \\targ \\qw \\qwx &\\qw & \\meter \\qw & \\control \\qw &\\qw \\qwx &\\qw\\\\ \\lstick{\\text{bob}}& \\qw &\\qw & \\targ \\qw \\qwx &\\qw &\\qw &\\qw & \\targ \\qw \\qwx & \\control \\qw \\qwx &\\qw \\\\ \\\\ } """.strip()
def test_query_overlapping_operations_inclusive(): q = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op1 = ScheduledOperation(zero, 2 * ps, ops.H(q)) op2 = ScheduledOperation(zero + ps, 2 * ps, ops.H(q)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op2, op1]) def query(t, d=Duration(), qubits=None): return schedule.query(time=t, duration=d, qubits=qubits, include_query_end_time=True, include_op_end_times=True) assert query(zero - 0.5 * ps, ps) == [op1] assert query(zero - 0.5 * ps, 2 * ps) == [op1, op2] assert query(zero, ps) == [op1, op2] assert query(zero + 0.5 * ps, ps) == [op1, op2] assert query(zero + ps, ps) == [op1, op2] assert query(zero + 1.5 * ps, ps) == [op1, op2] assert query(zero + 2.0 * ps, ps) == [op1, op2] assert query(zero + 2.5 * ps, ps) == [op2] assert query(zero + 3.0 * ps, ps) == [op2] assert query(zero + 3.5 * ps, ps) == []
def _xx_interaction_via_full_czs(q0: 'cirq.Qid', q1: 'cirq.Qid', x: float): a = x * -2 / np.pi yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.X(q0)**a yield ops.CZ(q0, q1) yield ops.H(q1)
def _xx_interaction_via_full_czs(q0: ops.QubitId, q1: ops.QubitId, x: float): a = x * -2 / np.pi yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.X(q0)**a yield ops.CZ(q0, q1) yield ops.H(q1)
def test_removes_identity_sequence(): q = ops.QubitId() assert_optimizes(before=circuits.Circuit([ circuits.Moment([ops.Z(q)]), circuits.Moment([ops.H(q)]), circuits.Moment([ops.X(q)]), circuits.Moment([ops.H(q)]), ]), after=circuits.Circuit())
def test_eq(): q0 = ops.QubitId() eq = EqualsTester() eq.make_equality_pair( lambda: ScheduledOperation(Timestamp(), Duration(), ops.H(q0))) eq.make_equality_pair( lambda: ScheduledOperation(Timestamp(picos=5), Duration(), ops.H(q0))) eq.make_equality_pair( lambda: ScheduledOperation(Timestamp(), Duration(picos=5), ops.H(q0))) eq.make_equality_pair( lambda: ScheduledOperation(Timestamp(), Duration(), ops.X(q0)))
def test_exclude(): q = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op = ScheduledOperation(zero, ps, ops.H(q)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op]) assert not schedule.exclude(ScheduledOperation(zero + ps, ps, ops.H(q))) assert not schedule.exclude(ScheduledOperation(zero, ps, ops.X(q))) assert schedule.query(time=zero, duration=ps * 10) == [op] assert schedule.exclude(ScheduledOperation(zero, ps, ops.H(q))) assert schedule.query(time=zero, duration=ps * 10) == [] assert not schedule.exclude(ScheduledOperation(zero, ps, ops.H(q)))
def _xx_yy_interaction_via_full_czs(q0: 'cirq.Qid', q1: 'cirq.Qid', x: float, y: float): a = x * -2 / np.pi b = y * -2 / np.pi yield ops.X(q0) ** 0.5 yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.H(q1) yield ops.X(q0) ** a yield ops.Y(q1) ** b yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.H(q1) yield ops.X(q0) ** -0.5
def test_moment_by_moment_schedule_moment_of_single_qubit_ops(): device = _TestDevice() qubits = device.qubits circuit = Circuit([ Moment(ops.H(q) for q in qubits), ]) schedule = moment_by_moment_schedule(device, circuit) zero_ns = cirq.Timestamp() assert set(schedule.scheduled_operations) == { ScheduledOperation.op_at_on(ops.H(q), zero_ns, device) for q in qubits }
def test_query_point_operation_exclusive(): q = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op = ScheduledOperation(zero, Duration(), ops.H(q)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op]) assert schedule.query(time=zero, include_query_end_time=False, include_op_end_times=False) == [] assert schedule.query(time=zero + ps, include_query_end_time=False, include_op_end_times=False) == [] assert schedule.query(time=zero - ps, include_query_end_time=False, include_op_end_times=False) == [] assert schedule.query(time=zero) == [] assert schedule.query(time=zero + ps) == [] assert schedule.query(time=zero - ps) == [] assert schedule.query(time=zero, qubits=[]) == [] assert schedule.query(time=zero, qubits=[q]) == [] assert schedule.query(time=zero, duration=ps) == [] assert schedule.query(time=zero - 0.5 * ps, duration=ps) == [op] assert schedule.query(time=zero - ps, duration=ps) == [] assert schedule.query(time=zero - 2 * ps, duration=ps) == [] assert schedule.query(time=zero - ps, duration=3 * ps) == [op] assert schedule.query(time=zero + ps, duration=ps) == []
def test_moment_by_moment_schedule_empty_moment_ignored(): device = _TestDevice() qubits = device.qubits circuit = Circuit( [Moment([ops.H(qubits[0])]), Moment([]), Moment([ops.H(qubits[0])])]) schedule = moment_by_moment_schedule(device, circuit) zero_ns = cirq.Timestamp() twenty_ns = cirq.Timestamp(nanos=20) assert set(schedule.scheduled_operations) == { ScheduledOperation.op_at_on(ops.H(qubits[0]), zero_ns, device), ScheduledOperation.op_at_on(ops.H(qubits[0]), twenty_ns, device), }
def test_query_point_operation_inclusive(): q = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op = ScheduledOperation(zero, Duration(), ops.H(q)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op]) def query(t, d=Duration(), qubits=None): return schedule.query(time=t, duration=d, qubits=qubits, include_query_end_time=True, include_op_end_times=True) assert query(zero) == [op] assert query(zero + ps) == [] assert query(zero - ps) == [] assert query(zero, qubits=[]) == [] assert query(zero, qubits=[q]) == [op] assert query(zero, ps) == [op] assert query(zero - 0.5 * ps, ps) == [op] assert query(zero - ps, ps) == [op] assert query(zero - 2 * ps, ps) == [] assert query(zero - ps, 3 * ps) == [op] assert query(zero + ps, ps) == []
def _H( q: int, args: sim.ActOnCliffordTableauArgs, operations: List[ops.Operation], qubits: List['cirq.Qid'], ): protocols.act_on(ops.H, args, qubits=[qubits[q]], allow_decompose=False) operations.append(ops.H(qubits[q]))
def default_decompose(self, qubits: Sequence[ops.QubitId]) -> ops.OP_TREE: qubit, = qubits if self == CliffordGate.H: return ops.H(qubit), rotations = self.decompose_rotation() pauli_gate_map = {Pauli.X: ops.X, Pauli.Y: ops.Y, Pauli.Z: ops.Z} return tuple( (pauli_gate_map[r](qubit)**(qt / 2) for r, qt in rotations))
def test_stopped_at_2qubit(): m = MergeRotations(0.000001) q = ops.QubitId() q2 = ops.QubitId() c = circuits.Circuit([ circuits.Moment([ops.Z(q)]), circuits.Moment([ops.H(q)]), circuits.Moment([ops.X(q)]), circuits.Moment([ops.H(q)]), circuits.Moment([ops.CZ(q, q2)]), circuits.Moment([ops.H(q)]), ]) assert (m.optimization_at(c, 0, c.operation_at( q, 0)) == circuits.PointOptimizationSummary(clear_span=4, clear_qubits=[q], new_operations=[]))
def test_include(): q0 = ops.QubitId() q1 = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) schedule = Schedule(device=UnconstrainedDevice) op0 = ScheduledOperation(zero, ps, ops.H(q0)) schedule.include(op0) with pytest.raises(ValueError): schedule.include(ScheduledOperation(zero, ps, ops.H(q0))) schedule.include(ScheduledOperation(zero + 0.5 * ps, ps, ops.H(q0))) op1 = ScheduledOperation(zero + 2 * ps, ps, ops.H(q0)) schedule.include(op1) op2 = ScheduledOperation(zero + 0.5 * ps, ps, ops.H(q1)) schedule.include(op2) assert schedule.query(time=zero, duration=ps * 10) == [op0, op2, op1]
def test_cnots_separated_by_single_gates_correct(): q0 = ops.QubitId() q1 = ops.QubitId() assert_optimization_not_broken( circuits.Circuit.from_ops( ops.CNOT(q0, q1), ops.H(q1), ops.CNOT(q0, q1), ))
def _apply_qft(register): """ applies the qft to the register according to https://arxiv.org/pdf/quant-ph/0008033.pdf """ rreg = register[::-1] for i, q in enumerate(rreg): yield ops.H(q) for j in range(i + 1, len(rreg)): yield ops.CZ(rreg[j], q)**(2 * 1 / (2**(j + 1)))
def simple_schedule(q, start_picos=0, duration_picos=1, num_ops=1): time_picos = start_picos scheduled_ops = [] for _ in range(num_ops): op = ScheduledOperation(Timestamp(picos=time_picos), Duration(picos=duration_picos), ops.H(q)) scheduled_ops.append(op) time_picos += duration_picos return Schedule(device=UnconstrainedDevice, scheduled_operations=scheduled_ops)
def test_query_overlapping_operations_exclusive(): q = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op1 = ScheduledOperation(zero, 2 * ps, ops.H(q)) op2 = ScheduledOperation(zero + ps, 2 * ps, ops.H(q)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op2, op1]) assert schedule.query(time=zero - 0.5 * ps, duration=ps) == [op1] assert schedule.query(time=zero - 0.5 * ps, duration=2 * ps) == [op1, op2] assert schedule.query(time=zero, duration=ps) == [op1] assert schedule.query(time=zero + 0.5 * ps, duration=ps) == [op1, op2] assert schedule.query(time=zero + ps, duration=ps) == [op1, op2] assert schedule.query(time=zero + 1.5 * ps, duration=ps) == [op1, op2] assert schedule.query(time=zero + 2.0 * ps, duration=ps) == [op2] assert schedule.query(time=zero + 2.5 * ps, duration=ps) == [op2] assert schedule.query(time=zero + 3.0 * ps, duration=ps) == [] assert schedule.query(time=zero + 3.5 * ps, duration=ps) == []
def _xx_yy_zz_interaction_via_full_czs(q0: 'cirq.Qid', q1: 'cirq.Qid', x: float, y: float, z: float): a = x * -2 / np.pi + 0.5 b = y * -2 / np.pi + 0.5 c = z * -2 / np.pi + 0.5 yield ops.X(q0)**0.5 yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.H(q1) yield ops.X(q0)**a yield ops.Y(q1)**b yield ops.H.on(q0) yield ops.CZ(q1, q0) yield ops.H(q0) yield ops.X(q1)**-0.5 yield ops.Z(q1)**c yield ops.H(q1) yield ops.CZ(q0, q1) yield ops.H(q1)
def test_moment_by_moment_schedule_max_duration(): device = _TestDevice() qubits = device.qubits circuit = Circuit([ Moment([ops.H(qubits[0]), ops.CZ(qubits[1], qubits[2])]), Moment([ops.H(qubits[0])]) ]) schedule = moment_by_moment_schedule(device, circuit) zero_ns = cirq.Timestamp() fourty_ns = cirq.Timestamp(nanos=40) assert set(schedule.scheduled_operations) == { ScheduledOperation.op_at_on(ops.H(qubits[0]), zero_ns, device), ScheduledOperation.op_at_on(ops.CZ(qubits[1], qubits[2]), zero_ns, device), ScheduledOperation.op_at_on(ops.H(qubits[0]), fourty_ns, device), }
def test_moment_by_moment_schedule_two_moments(): device = _TestDevice() qubits = device.qubits circuit = Circuit([ Moment(ops.H(q) for q in qubits), Moment((ops.CZ(qubits[i], qubits[i + 1]) for i in range(0, 9, 3))) ]) schedule = moment_by_moment_schedule(device, circuit) zero_ns = cirq.Timestamp() twenty_ns = cirq.Timestamp(nanos=20) expected_one_qubit = set( ScheduledOperation.op_at_on(ops.H(q), zero_ns, device) for q in qubits) expected_two_qubit = set( ScheduledOperation.op_at_on(ops.CZ(qubits[i], qubits[i + 1]), twenty_ns, device) for i in range(0, 9, 3)) expected = expected_one_qubit.union(expected_two_qubit) assert set(schedule.scheduled_operations) == expected
def test_text_diagrams(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') circuit = Circuit.from_ops(ops.SWAP(a, b), ops.X(a), ops.Y(a), ops.Z(a), ops.CZ(a, b), ops.CNOT(a, b), ops.CNOT(b, a), ops.H(a)) assert circuit.to_text_diagram().strip() == """ a: ───×───X───Y───Z───@───@───X───H─── │ │ │ │ b: ───×───────────────@───X───@─────── """.strip()
def test_inefficient_circuit_correct(): t = 0.1 v = 0.11 q0 = ops.QubitId() q1 = ops.QubitId() assert_optimization_not_broken( circuits.Circuit.from_ops( ops.H(q1), ops.CNOT(q0, q1), ops.H(q1), ops.CNOT(q0, q1), ops.CNOT(q1, q0), ops.H(q0), ops.CNOT(q0, q1), ops.Z(q0)**t, ops.Z(q1)**-t, ops.CNOT(q0, q1), ops.H(q0), ops.Z(q1)**v, ops.CNOT(q0, q1), ops.Z(q0)**-v, ops.Z(q1)**-v, ))
def test_slice_operations(): q0 = ops.QubitId() q1 = ops.QubitId() zero = Timestamp(picos=0) ps = Duration(picos=1) op1 = ScheduledOperation(zero, ps, ops.H(q0)) op2 = ScheduledOperation(zero + 2 * ps, 2 * ps, ops.CZ(q0, q1)) op3 = ScheduledOperation(zero + 10 * ps, ps, ops.H(q1)) schedule = Schedule(device=UnconstrainedDevice, scheduled_operations=[op1, op2, op3]) assert schedule[zero] == [op1] assert schedule[zero + ps*0.5] == [op1] assert schedule[zero:zero] == [] assert schedule[zero + ps*0.5:zero + ps*0.5] == [op1] assert schedule[zero:zero + ps] == [op1] assert schedule[zero:zero + 2 * ps] == [op1] assert schedule[zero:zero + 2.1 * ps] == [op1, op2] assert schedule[zero:zero + 20 * ps] == [op1, op2, op3] assert schedule[zero + 2.5 * ps:zero + 20 * ps] == [op2, op3] assert schedule[zero + 5 * ps:zero + 20 * ps] == [op3]
def test_works_with_basic_gates(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') basics = [ ops.X(a), ops.Y(a)**0.5, ops.Z(a), ops.CZ(a, b)**-0.25, ops.CNOT(a, b), ops.H(b), ops.SWAP(a, b) ] assert list(ops.inverse_of_invertible_op_tree(basics)) == [ ops.SWAP(a, b), ops.H(b), ops.CNOT(a, b), ops.CZ(a, b)**0.25, ops.Z(a), ops.Y(a)**-0.5, ops.X(a), ]
def _startdecompose(self, qubits): # qubits = [c1, c2, ..., cn, T] # Will "bootstrap" an ancilla CnXOneBorrow = CnXDirtyGate(num_controls=len(qubits[:-2]), num_ancilla=1) yield ops.H(qubits[-1]) yield CnXOneBorrow(*(qubits[:-2] + [qubits[-1]] + [qubits[-2]])) yield ops.Z(qubits[-1])**-0.25 yield ops.CNOT(qubits[-2], qubits[-1]) yield ops.Z(qubits[-1])**0.25 yield CnXOneBorrow(*(qubits[:-2] + [qubits[-1]] + [qubits[-2]])) yield ops.Z(qubits[-1])**-0.25 yield ops.CNOT(qubits[-2], qubits[-1]) yield ops.Z(qubits[-1])**0.25 yield ops.H(qubits[-1]) IncrementLinearWithBorrowedBitOp = IncrementLinearWithBorrowedBitGate( register_size=len(qubits) - 1) # Perform a +1 Gate on all of the top bits with bottom bit as borrowed yield IncrementLinearWithBorrowedBitOp(*qubits) # Perform -rt Z gates for i in range(1, len(qubits) - 1): yield ops.Z(qubits[i])**(-1 * 1 / (2**(len(qubits) - i))) # Perform a -1 Gate on the top bits for i in range(len(qubits) - 1): yield ops.X(qubits[i]) yield IncrementLinearWithBorrowedBitOp(*qubits) for i in range(len(qubits) - 1): yield ops.X(qubits[i]) # Perform rt Z gates for i in range(1, len(qubits) - 1): yield ops.Z(qubits[i])**(1 / (2**(len(qubits) - i))) yield ops.Z(qubits[0])**(1 / (2**(len(qubits) - 1)))