def test_query_timedelta(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ms = timedelta(microseconds=1000) op1 = cirq.ScheduledOperation(zero, 2 * ms, cirq.H(q)) op2 = cirq.ScheduledOperation(zero + ms, 2 * ms, cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[op2, op1]) def query(t, d=timedelta(), 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 * ms, ms) == [op1] assert query(zero - 0.5 * ms, 2 * ms) == [op1, op2] assert query(zero, ms) == [op1, op2] assert query(zero + 0.5 * ms, ms) == [op1, op2] assert query(zero + ms, ms) == [op1, op2] assert query(zero + 1.5 * ms, ms) == [op1, op2] assert query(zero + 2.0 * ms, ms) == [op1, op2] assert query(zero + 2.5 * ms, ms) == [op2] assert query(zero + 3.0 * ms, ms) == [op2] assert query(zero + 3.5 * ms, ms) == []
def test_query_overlapping_operations_inclusive(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op1 = cirq.ScheduledOperation(zero, 2 * ps, cirq.H(q)) op2 = cirq.ScheduledOperation(zero + ps, 2 * ps, cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[op2, op1]) def query(t, d=cirq.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 test_exclude(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op = cirq.ScheduledOperation(zero, ps, cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[op]) assert not schedule.exclude( cirq.ScheduledOperation(zero + ps, ps, cirq.H(q))) assert not schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.X(q))) assert schedule.query(time=zero, duration=ps * 10) == [op] assert schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.H(q))) assert schedule.query(time=zero, duration=ps * 10) == [] assert not schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.H(q)))
def test_exclude(): q = cirq.QubitId() zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op = cirq.ScheduledOperation(zero, ps, cirq.H(q)) schedule = cirq.Schedule(device=UnconstrainedDevice, scheduled_operations=[op]) assert not schedule.exclude( cirq.ScheduledOperation(zero + ps, ps, cirq.H(q))) assert not schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.X(q))) assert schedule.query(time=zero, duration=ps * 10) == [op] assert schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.H(q))) assert schedule.query(time=zero, duration=ps * 10) == [] assert not schedule.exclude(cirq.ScheduledOperation(zero, ps, cirq.H(q)))
def test_query_point_operation_exclusive(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op = cirq.ScheduledOperation(zero, cirq.Duration(), cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, 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_query_point_operation_inclusive(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op = cirq.ScheduledOperation(zero, cirq.Duration(), cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[op]) def query(t, d=cirq.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 test_validate_scheduled_operation_errors(): d = square_device(2, 2) s = cirq.Schedule(device=cirq.UnconstrainedDevice) q00 = cirq.GridQubit(0, 0) so = cirq.ScheduledOperation(cirq.Timestamp(), cirq.Duration(nanos=1), cirq.X.on(q00)) with pytest.raises(ValueError, match="Incompatible operation duration"): d.validate_scheduled_operation(s, so)
def test_query_overlapping_operations_exclusive(): q = cirq.QubitId() zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op1 = cirq.ScheduledOperation(zero, 2 * ps, cirq.H(q)) op2 = cirq.ScheduledOperation(zero + ps, 2 * ps, cirq.H(q)) schedule = cirq.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 test_schedule_device_validation_fails(build): scheduled_op = cirq.ScheduledOperation(time=None, duration=cirq.Duration(), operation=cirq.H.on( cirq.NamedQubit("dorothy"))) schedule = cirq.Schedule(device=cg.Foxtail, scheduled_operations=[scheduled_op]) with pytest.raises(ValueError): cg.Engine(project_id='project-id').run(program=schedule)
def test_schedule_device_validation_fails(build): scheduled_op = cirq.ScheduledOperation(time=None, duration=None, operation=cirq.H.on( cirq.NamedQubit("dorothy"))) schedule = cirq.Schedule(device=Foxtail, scheduled_operations=[scheduled_op]) with pytest.raises(ValueError): Engine(api_key="key").run(schedule, JobConfig('project-id'))
def test_unitary(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op = cirq.ScheduledOperation(zero, ps, cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[op]) cirq.testing.assert_has_consistent_apply_unitary(schedule, qubit_count=1) np.testing.assert_allclose(cirq.unitary(schedule), cirq.unitary(cirq.H)) assert cirq.has_unitary(schedule) schedule2 = cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=[ cirq.ScheduledOperation( zero, ps, cirq.depolarize(0.5).on(q)) ]) assert not cirq.has_unitary(schedule2)
def test_query_overlapping_operations_exclusive(): q = cirq.NamedQubit('q') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op1 = cirq.ScheduledOperation(zero, 2 * ps, cirq.H(q)) op2 = cirq.ScheduledOperation(zero + ps, 2 * ps, cirq.H(q)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, 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 test_schedule_and_device_both_not_supported(build): scheduled_op = cirq.ScheduledOperation(time=None, duration=None, operation=cirq.H.on( cirq.NamedQubit("dorothy"))) schedule = cirq.Schedule(device=Foxtail, scheduled_operations=[scheduled_op]) eng = Engine(api_key="key") with pytest.raises(ValueError, match='Device'): eng.run(schedule, JobConfig('project-id'), device=Foxtail)
def test_include(): q0 = cirq.QubitId() q1 = cirq.QubitId() zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) schedule = cirq.Schedule(device=UnconstrainedDevice) op0 = cirq.ScheduledOperation(zero, ps, cirq.H(q0)) schedule.include(op0) with pytest.raises(ValueError): schedule.include(cirq.ScheduledOperation(zero, ps, cirq.H(q0))) with pytest.raises(ValueError): schedule.include( cirq.ScheduledOperation(zero + 0.5 * ps, ps, cirq.H(q0))) op1 = cirq.ScheduledOperation(zero + 2 * ps, ps, cirq.H(q0)) schedule.include(op1) op2 = cirq.ScheduledOperation(zero + 0.5 * ps, ps, cirq.H(q1)) schedule.include(op2) assert schedule.query(time=zero, duration=ps * 10) == [op0, op2, op1]
def simple_schedule(q, start_picos=0, duration_micros=1, num_ops=1): time_picos = start_picos scheduled_ops = [] for _ in range(num_ops): op = cirq.ScheduledOperation( cirq.Timestamp(picos=time_picos), timedelta(microseconds=duration_micros), cirq.H(q)) scheduled_ops.append(op) time_picos += duration_micros * 10**6 return cirq.Schedule(device=UNCONSTRAINED_DEVICE, scheduled_operations=scheduled_ops)
def test_include(): q0 = cirq.NamedQubit('q0') q1 = cirq.NamedQubit('q1') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE) op0 = cirq.ScheduledOperation(zero, ps, cirq.H(q0)) schedule.include(op0) with pytest.raises(ValueError): schedule.include(cirq.ScheduledOperation(zero, ps, cirq.H(q0))) with pytest.raises(ValueError): schedule.include( cirq.ScheduledOperation(zero + 0.5 * ps, ps, cirq.H(q0))) op1 = cirq.ScheduledOperation(zero + 2 * ps, ps, cirq.H(q0)) schedule.include(op1) op2 = cirq.ScheduledOperation(zero + 0.5 * ps, ps, cirq.H(q1)) schedule.include(op2) assert schedule.query(time=zero, duration=ps * 10) == [op0, op2, op1]
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 = cirq.ScheduledOperation(cirq.Timestamp(picos=time_picos), cirq.Duration(picos=duration_picos), cirq.H(q)) scheduled_ops.append(op) time_picos += duration_picos return cirq.Schedule(device=UnconstrainedDevice, scheduled_operations=scheduled_ops)
def test_slice_operations(): q0 = cirq.QubitId() q1 = cirq.QubitId() zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op1 = cirq.ScheduledOperation(zero, ps, cirq.H(q0)) op2 = cirq.ScheduledOperation(zero + 2 * ps, 2 * ps, cirq.CZ(q0, q1)) op3 = cirq.ScheduledOperation(zero + 10 * ps, ps, cirq.H(q1)) schedule = cirq.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_slice_operations(): q0 = cirq.NamedQubit('q0') q1 = cirq.NamedQubit('q1') zero = cirq.Timestamp(picos=0) ps = cirq.Duration(picos=1) op1 = cirq.ScheduledOperation(zero, ps, cirq.H(q0)) op2 = cirq.ScheduledOperation(zero + 2 * ps, 2 * ps, cirq.CZ(q0, q1)) op3 = cirq.ScheduledOperation(zero + 10 * ps, ps, cirq.H(q1)) schedule = cirq.Schedule(device=UNCONSTRAINED_DEVICE, 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_validate_schedule_errors(): d = square_device(2, 2, max_controls=3) s = cirq.Schedule(device=cirq.UnconstrainedDevice) q00 = cirq.GridQubit(0, 0) q01 = cirq.GridQubit(0, 1) q10 = cirq.GridQubit(1, 0) q11 = cirq.GridQubit(1, 1) us = cirq.Duration(nanos=10**3) ms = cirq.Duration(nanos=10**6) msone = cirq.Timestamp(nanos=10**6) mstwo = cirq.Timestamp(nanos=2*10**6) msthree = cirq.Timestamp(nanos=3*10**6) for qubit in d.qubits: s.include(cirq.ScheduledOperation(cirq.Timestamp(nanos=0), 100*us, cirq.X.on(qubit))) s.include(cirq.ScheduledOperation(msone, 100*us, cirq.TOFFOLI.on(q00,q01,q10))) s.include(cirq.ScheduledOperation(mstwo, 100*us, cirq.ParallelGateOperation( cirq.X, [q00, q01]))) s.include(cirq.ScheduledOperation(mstwo, 100*us, cirq.ParallelGateOperation( cirq.Z, [q10, q11]))) for qubit in d.qubits: s.include(cirq.ScheduledOperation(msthree, 50*ms, cirq.GateOperation( cirq.MeasurementGate(1, qubit), [qubit]))) d.validate_schedule(s) s.include(cirq.ScheduledOperation(cirq.Timestamp(nanos=10**9), 100*us, cirq.X.on(q00))) with pytest.raises(ValueError, match="Non-measurement operation after " "measurement"): d.validate_schedule(s)
def test_find_measurements_simple_schedule(): schedule = cirq.Schedule( device=cirq.UNCONSTRAINED_DEVICE, scheduled_operations=[ cirq.ScheduledOperation( time=cirq.Timestamp(picos=10_000), duration=cirq.Duration(nanos=1000), operation=cirq.measure(q(0, 0), q(0, 1), q(0, 2), key='k'), ), ], ) measurements = v2.find_measurements(schedule) assert len(measurements) == 1 m = measurements[0] _check_measurement(m, 'k', [q(0, 0), q(0, 1), q(0, 2)], 10_000)
def convert_dds_to_cirq_schedule(dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, add_measurement=True, device=None): """Converts a Dynamic Decoupling Sequence into schedule as defined in cirq Parameters ---------- dynamic_decoupling_sequence : DynamicDecouplingSequence The dynamic decoupling sequence target_qubits : list, optional List of target qubits for the sequence operation; the qubits must be cirq.Qid type; defaults to None in which case a 1-D lattice of one qubit is used (indexed as 0). gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 add_measurement : bool, optional If True, the schedule contains a measurement operation for each of the target qubits. Measurement from each of the qubits is associated with a string as key. The string is formatted as 'qubit-X' where X is a number between 0 and len(target_qubits). device : cirq.Device, optional A cirq.Device that specifies hardware constraints for validating operations. If None, a unconstrained device is used. See `Cirq Documentation <https://cirq.readthedocs.io/en/stable/schedules.html/>` _. Returns ------- cirq.Schedule The schedule of sequence rotation operations. Raises ------ ArgumentsValueError If any of the input parameters result in an invalid operation. Notes ----- Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, pulses require time. Therefore, this method of converting an idealized sequence results to a schedule that is only an approximate implementation of the idealized sequence. In idealized definition of DDS, `offsets` represents the instances within sequence `duration` where a pulse occurs instantaneously. A series of appropriate rotation operations is placed in order to represent these pulses. In cirq.schedule, the active pulses are scheduled to be activated at a certain instant calculated from the start of the sequence and continues for a duration of gate_time. This does not require identity gates to be placed between offsets. Q-CTRL Open Controls support operation resulting in rotation around at most one axis at any offset. """ if dynamic_decoupling_sequence is None: raise ArgumentsValueError( 'No dynamic decoupling sequence provided.', {'dynamic_decoupling_sequence': dynamic_decoupling_sequence}) if not isinstance(dynamic_decoupling_sequence, DynamicDecouplingSequence): raise ArgumentsValueError( 'Dynamical decoupling sequence is not recognized.' 'Expected DynamicDecouplingSequence instance', { 'type(dynamic_decoupling_sequence)': type(dynamic_decoupling_sequence) }) if gate_time <= 0: raise ArgumentsValueError( 'Time delay of gates must be greater than zero.', {'gate_time': gate_time}) if target_qubits is None: target_qubits = [cirq.LineQubit(0)] if device is None: device = cirq.UnconstrainedDevice if not isinstance(device, cirq.Device): raise ArgumentsValueError('Device must be a cirq.Device type.', {'device': device}) # time in nano seconds gate_time = gate_time * 1e9 rabi_rotations = dynamic_decoupling_sequence.rabi_rotations azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles detuning_rotations = dynamic_decoupling_sequence.detuning_rotations if len(rabi_rotations.shape) == 1: rabi_rotations = rabi_rotations[np.newaxis, :] if len(azimuthal_angles.shape) == 1: azimuthal_angles = azimuthal_angles[np.newaxis, :] if len(detuning_rotations.shape) == 1: detuning_rotations = detuning_rotations[np.newaxis, :] operations = np.vstack( (rabi_rotations, azimuthal_angles, detuning_rotations)) offsets = dynamic_decoupling_sequence.offsets # offsets in nano seconds offsets = offsets * 1e9 scheduled_operations = [] offset_count = 0 for op_idx in range(operations.shape[1]): rabi_rotation = dynamic_decoupling_sequence.rabi_rotations[ offset_count] azimuthal_angle = dynamic_decoupling_sequence.azimuthal_angles[ offset_count] x_rotation = rabi_rotation * np.cos(azimuthal_angle) y_rotation = rabi_rotation * np.sin(azimuthal_angle) z_rotation = dynamic_decoupling_sequence.detuning_rotations[ offset_count] rotations = np.array([x_rotation, y_rotation, z_rotation]) zero_pulses = np.isclose(rotations, 0.0).astype(np.int) nonzero_pulse_counts = 3 - np.sum(zero_pulses) if nonzero_pulse_counts > 1: raise ArgumentsValueError( 'Open Controls support a sequence with one ' 'valid pulse at any offset. Found sequence ' 'with multiple rotation operations at an offset.', { 'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), 'offset': dynamic_decoupling_sequence.offsets[op_idx], 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[op_idx], 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[op_idx], 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[op_idx] }) for qubit in target_qubits: if nonzero_pulse_counts == 0: operation = cirq.ScheduledOperation( time=cirq.Timestamp(nanos=offsets[op_idx]), duration=cirq.Duration(nanos=gate_time), operation=cirq.I(qubit)) else: if not np.isclose(rotations[0], 0.0): operation = cirq.ScheduledOperation( time=cirq.Timestamp(nanos=offsets[op_idx]), duration=cirq.Duration(nanos=gate_time), operation=cirq.Rx(rotations[0])(qubit)) elif not np.isclose(rotations[1], 0.0): operation = cirq.ScheduledOperation( time=cirq.Timestamp(nanos=offsets[op_idx]), duration=cirq.Duration(nanos=gate_time), operation=cirq.Rx(rotations[1])(qubit)) elif not np.isclose(rotations[2], 0.): operation = cirq.ScheduledOperation( time=cirq.Timestamp(nanos=offsets[op_idx]), duration=cirq.Duration(nanos=gate_time), operation=cirq.Rx(rotations[2])(qubit)) offset_count += 1 scheduled_operations.append(operation) if add_measurement: for idx, qubit in enumerate(target_qubits): operation = cirq.ScheduledOperation( time=cirq.Timestamp(nanos=offsets[-1] + gate_time), duration=cirq.Duration(nanos=gate_time), operation=cirq.MeasurementGate( 1, key='qubit-{}'.format(idx))(qubit)) scheduled_operations.append(operation) schedule = cirq.Schedule(device=device, scheduled_operations=scheduled_operations) return schedule