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_moment_by_moment_schedule_device_validation_fails(): device = _TestDevice() qubits = device.qubits circuit = Circuit( [Moment([ops.CZ(qubits[0], qubits[1]), ops.CZ(qubits[2], qubits[3])])]) with pytest.raises(ValueError, match="Adjacent CZ"): _ = moment_by_moment_schedule(device, circuit)
def test_ignores_2qubit_target(): m = MergeRotations(0.000001) q = ops.QubitId() q2 = ops.QubitId() c = circuits.Circuit([ circuits.Moment([ops.CZ(q, q2)]), ]) m.optimization_at(c, 0, c.operation_at(q, 0)) assert c == circuits.Circuit([circuits.Moment([ops.CZ(q, q2)])])
def test_czs_separated_by_single_gates_correct(): q0 = ops.QubitId() q1 = ops.QubitId() assert_optimization_not_broken( circuits.Circuit.from_ops( ops.CZ(q0, q1), ops.X(q1), ops.X(q1), ops.X(q1), ops.CZ(q0, q1), ))
def test_moment_by_moment_schedule_moment_of_two_qubit_ops(): device = _TestDevice() qubits = device.qubits circuit = Circuit( [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() expected = set( ScheduledOperation.op_at_on(ops.CZ(qubits[i], qubits[i + 1]), zero_ns, device) for i in range(0, 9, 3)) assert set(schedule.scheduled_operations) == expected
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_interchangeable_qubit_eq(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') c = ops.NamedQubit('c') eq = EqualsTester() eq.add_equality_group(ops.SWAP(a, b), ops.SWAP(b, a)) eq.add_equality_group(ops.SWAP(a, c)) eq.add_equality_group(ops.CZ(a, b), ops.CZ(b, a)) eq.add_equality_group(ops.CZ(a, c)) eq.add_equality_group(ops.CNOT(a, b)) eq.add_equality_group(ops.CNOT(b, a)) eq.add_equality_group(ops.CNOT(a, c))
def xmon_op_from_proto(proto: operations_pb2.Operation) -> 'cirq.Operation': """Convert the proto to the corresponding operation. See protos in api/google/v1 for specification of the protos. Args: proto: Operation proto. Returns: The operation. """ param = _parameterized_value_from_proto qubit = _qubit_from_proto if proto.HasField('exp_w'): exp_w = proto.exp_w return ops.PhasedXPowGate( exponent=param(exp_w.half_turns), phase_exponent=param(exp_w.axis_half_turns), ).on(qubit(exp_w.target)) if proto.HasField('exp_z'): exp_z = proto.exp_z return ops.Z(qubit(exp_z.target))**param(exp_z.half_turns) if proto.HasField('exp_11'): exp_11 = proto.exp_11 return ops.CZ(qubit(exp_11.target1), qubit(exp_11.target2))**param(exp_11.half_turns) if proto.HasField('measurement'): meas = proto.measurement return ops.MeasurementGate(num_qubits=len(meas.targets), key=meas.key, invert_mask=tuple(meas.invert_mask)).on( *[qubit(q) for q in meas.targets]) raise ValueError(f'invalid operation: {proto}')
def controlled_op_to_operations(control: ops.QubitId, target: ops.QubitId, operation: np.ndarray, tolerance: float = 0.0) -> List[ops.Operation]: """Decomposes a controlled single-qubit operation into Z/XY/CZ gates. Args: control: The control qubit. target: The qubit to apply an operation to, when the control is on. operation: The single-qubit operation being controlled. tolerance: A limit on the amount of error introduced by the construction. Returns: A list of Operations that apply the controlled operation. """ u, z_phase, global_phase = single_qubit_op_to_framed_phase_form(operation) if abs(z_phase - 1) <= tolerance: return [] u_gates = single_qubit_matrix_to_gates(u, tolerance) if u_gates and isinstance(u_gates[-1], ops.ZPowGate): # Don't keep border operations that commute with CZ. del u_gates[-1] ops_before = [gate(target) for gate in u_gates] ops_after = protocols.inverse(ops_before) effect = ops.CZ(control, target)**(cmath.phase(z_phase) / math.pi) kickback = ops.Z(control)**(cmath.phase(global_phase) / math.pi) return list( ops.flatten_op_tree( (ops_before, effect, kickback if abs(global_phase - 1) > tolerance else [], ops_after)))
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 _decompose_(self, qubits): """ Implements the decomposition of Draper provided in https://arxiv.org/pdf/quant-ph/0008033.pdf Args: qubits: |qubits| = 2 * self.size_of_inputs, in order a0 a1 ... an b0 b1 ... bn """ # For slicing qubits = list(qubits) assert len( qubits ) == 2 * self._size_of_inputs, f'A and B must be of the same length.' # A and B register appear in order A = qubits[:self._size_of_inputs] B = qubits[self._size_of_inputs:][::-1] yield self._apply_qft(A) A = A[::-1] for i in range(self._size_of_inputs): for j in range(i, self._size_of_inputs): yield ops.CZ(B[j], A[j - i])**(2 * 1 / (2**(i + 1))) A = A[::-1] yield cirq.inverse(self._apply_qft(A))
def test_from_braket_non_parameterized_two_qubit_gates(): braket_circuit = BKCircuit() instructions = [ Instruction(braket_gates.CNot(), target=[2, 3]), Instruction(braket_gates.Swap(), target=[3, 4]), Instruction(braket_gates.ISwap(), target=[2, 3]), Instruction(braket_gates.CZ(), target=(3, 4)), Instruction(braket_gates.CY(), target=(2, 3)), ] for instr in instructions: braket_circuit.add_instruction(instr) cirq_circuit = from_braket(braket_circuit) qreg = LineQubit.range(2, 5) expected_cirq_circuit = Circuit( ops.CNOT(*qreg[:2]), ops.SWAP(*qreg[1:]), ops.ISWAP(*qreg[:2]), ops.CZ(*qreg[1:]), ops.ControlledGate(ops.Y).on(*qreg[:2]), ) assert np.allclose( protocols.unitary(cirq_circuit), protocols.unitary(expected_cirq_circuit), )
def test_controlled_op_to_gates_omits_negligible_global_phase(): qc = ops.QubitId() qt = ops.QubitId() operations = decompositions.controlled_op_to_native_gates( control=qc, target=qt, operation=ops.H.matrix(), tolerance=0.0001) assert operations == [ops.Y(qt)**-0.25, ops.CZ(qc, qt), ops.Y(qt)**0.25]
def test_qubits(): a = ops.QubitId() b = ops.QubitId() assert Moment([ops.X(a), ops.X(b)]).qubits == {a , b} assert Moment([ops.X(a)]).qubits == {a} assert Moment([ops.CZ(a, b)]).qubits == {a, b}
def test_copy(): a = ops.QubitId() b = ops.QubitId() original = Moment([ops.CZ(a, b)]) copy = original.__copy__() assert original == copy assert id(original) != id(copy)
def _parity_interaction(q0: 'cirq.Qid', q1: 'cirq.Qid', rads: float, atol: float, gate: Optional[ops.Gate] = None): """Yields a ZZ interaction framed by the given operation.""" if abs(rads) < atol: return h = rads * -2 / np.pi if gate is not None: g = cast(ops.Gate, gate) yield g.on(q0), g.on(q1) # If rads is ±pi/4 radians within tolerance, single full-CZ suffices. if _is_trivial_angle(rads, atol): yield ops.CZ.on(q0, q1) else: yield ops.CZ(q0, q1)**(-2 * h) yield ops.Z(q0)**h yield ops.Z(q1)**h if gate is not None: g = protocols.inverse(gate) yield g.on(q0), g.on(q1)
def test_ignores_czs_separated_by_parameterized(): q0 = ops.QubitId() q1 = ops.QubitId() assert_optimizes( before=circuits.Circuit([ circuits.Moment([ops.CZ(q0, q1)]), circuits.Moment([ExpZGate( half_turns=Symbol('boo'))(q0)]), circuits.Moment([ops.CZ(q0, q1)]), ]), after=circuits.Circuit([ circuits.Moment([ops.CZ(q0, q1)]), circuits.Moment([ExpZGate( half_turns=Symbol('boo'))(q0)]), circuits.Moment([ops.CZ(q0, q1)]), ]))
def _parity_interaction(q0: ops.QubitId, q1: ops.QubitId, rads: float, tolerance: float, gate: Optional[ops.ReversibleEffect] = None): """Yields a ZZ interaction framed by the given operation.""" if abs(rads) < tolerance: return h = rads * -2 / np.pi if gate is not None: g = cast(ops.Gate, gate) yield g.on(q0), g.on(q1) # If rads is ±pi/4 radians within tolerance, single full-CZ suffices. if _is_trivial_angle(rads, tolerance): yield ops.CZ.on(q0, q1) else: yield ops.CZ(q0, q1)**(-2 * h) yield ops.Z(q0)**h yield ops.Z(q1)**h if gate is not None: g = cast(ops.Gate, gate.inverse()) yield g.on(q0), g.on(q1)
def xmon_op_from_proto_dict(proto_dict: Dict) -> 'cirq.Operation': """Convert the proto dictionary to the corresponding operation. See protos in api/google/v1 for specification of the protos. Args: proto_dict: Dictionary representing the proto. Keys are always strings, but values may be types correspond to a raw proto type or another dictionary (for messages). Returns: The operation. Raises: ValueError if the dictionary does not contain required values corresponding to the proto. """ def raise_missing_fields(gate_name: str): raise ValueError('{} missing required fields: {}'.format( gate_name, proto_dict)) param = _parameterized_value_from_proto_dict qubit = _qubit_from_proto_dict if 'exp_w' in proto_dict: exp_w = proto_dict['exp_w'] if ('half_turns' not in exp_w or 'axis_half_turns' not in exp_w or 'target' not in exp_w): raise_missing_fields('ExpW') return ops.PhasedXPowGate( exponent=param(exp_w['half_turns']), phase_exponent=param(exp_w['axis_half_turns']), ).on(qubit(exp_w['target'])) if 'exp_z' in proto_dict: exp_z = proto_dict['exp_z'] if 'half_turns' not in exp_z or 'target' not in exp_z: raise_missing_fields('ExpZ') return ops.Z(qubit(exp_z['target']))**param(exp_z['half_turns']) if 'exp_11' in proto_dict: exp_11 = proto_dict['exp_11'] if ('half_turns' not in exp_11 or 'target1' not in exp_11 or 'target2' not in exp_11): raise_missing_fields('Exp11') return ops.CZ(qubit(exp_11['target1']), qubit(exp_11['target2']))**param(exp_11['half_turns']) if 'measurement' in proto_dict: meas = proto_dict['measurement'] invert_mask = cast(Tuple[Any, ...], ()) if 'invert_mask' in meas: invert_mask = tuple( _load_json_bool(x) for x in meas['invert_mask']) if 'key' not in meas or 'targets' not in meas: raise_missing_fields('Measurement') return ops.MeasurementGate( num_qubits=len(meas['targets']), key=meas['key'], invert_mask=invert_mask).on(*[qubit(q) for q in meas['targets']]) raise ValueError('invalid operation: {}'.format(proto_dict))
def test_operates_on(): a = ops.QubitId() b = ops.QubitId() c = ops.QubitId() # Empty case. assert not Moment().operates_on([]) assert not Moment().operates_on([a]) assert not Moment().operates_on([b]) assert not Moment().operates_on([a, b]) # One-qubit operation case. assert not Moment([ops.X(a)]).operates_on([]) assert Moment([ops.X(a)]).operates_on([a]) assert not Moment([ops.X(a)]).operates_on([b]) assert Moment([ops.X(a)]).operates_on([a, b]) # Two-qubit operation case. assert not Moment([ops.CZ(a, b)]).operates_on([]) assert Moment([ops.CZ(a, b)]).operates_on([a]) assert Moment([ops.CZ(a, b)]).operates_on([b]) assert Moment([ops.CZ(a, b)]).operates_on([a, b]) assert not Moment([ops.CZ(a, b)]).operates_on([c]) assert Moment([ops.CZ(a, b)]).operates_on([a, c]) assert Moment([ops.CZ(a, b)]).operates_on([a, b, c]) # Multiple operations case. assert not Moment([ops.X(a), ops.X(b)]).operates_on([]) assert Moment([ops.X(a), ops.X(b)]).operates_on([a]) assert Moment([ops.X(a), ops.X(b)]).operates_on([b]) assert Moment([ops.X(a), ops.X(b)]).operates_on([a, b]) assert not Moment([ops.X(a), ops.X(b)]).operates_on([c]) assert Moment([ops.X(a), ops.X(b)]).operates_on([a, c]) assert Moment([ops.X(a), ops.X(b)]).operates_on([a, b, c])
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 _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 decompose_keep_func(self, op: ops.Operation) -> bool: # Keep CZs. if len(op.qubits) == 2 and op == ops.CZ(*op.qubits): return True # Keep within-group operation with a known unitary if self.all_in_same_group(*op.qubits): if protocols.unitary(op, None) is not None: return True return False
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 _easy_direction_partial_cz(q0: ops.QubitId, q1: ops.QubitId, t: float): """The actual hardware can only do CZs that phase counter-clockwise. This method replaces clockwise phase(t) to counter-clockwise. Args: q0: The first qubit being operated on. q1: The other qubit being operated on. t: The parameter to describe partial-CZ(CZ^t). Yields: Yields an equivalent circuit for CZ^t with counter-clock phased CZs. """ if t >= 0: yield ops.CZ(q0, q1)**t return yield ops.Z(q0)**t yield ops.X(q1) yield ops.CZ(q0, q1)**(-t) yield ops.X(q1)
def test_validation(): a = ops.QubitId() b = ops.QubitId() c = ops.QubitId() d = ops.QubitId() _ = Moment([]) _ = Moment([ops.X(a)]) _ = Moment([ops.CZ(a, b)]) _ = Moment([ops.CZ(b, d)]) _ = Moment([ops.CZ(a, b), ops.CZ(c, d)]) _ = Moment([ops.CZ(a, c), ops.CZ(b, d)]) _ = Moment([ops.CZ(a, c), ops.X(b)]) with pytest.raises(ValueError): _ = Moment([ops.X(a), ops.X(a)]) with pytest.raises(ValueError): _ = Moment([ops.CZ(a, c), ops.X(c)]) with pytest.raises(ValueError): _ = Moment([ops.CZ(a, c), ops.CZ(c, d)])
def test_clears_known_empties_even_at_zero_tolerance(): m = circuits.DropNegligible(0.001) q = ops.QubitId() q2 = ops.QubitId() c = circuits.Circuit.from_ops( ops.Z(q)**0, ops.Y(q)**0.0000001, ops.X(q)**-0.0000001, ops.CZ(q, q2)**0) m.optimize_circuit(c) assert c == circuits.Circuit([circuits.Moment()] * 4)