def build_sample_pulse_schedule(number_of_unique_pulses, number_of_channels): rng = np.random.RandomState(42) sched = Schedule() for _ in range(number_of_unique_pulses): for channel in range(number_of_channels): sched.append(Play(Waveform(rng.random(50)), DriveChannel(channel))) return sched
def test_assemble_with_individual_kernels(self): """Test that assembly works with individual kernels.""" disc_one = Kernel('disc_one', test_params=True) disc_two = Kernel('disc_two', test_params=False) schedule = Schedule() schedule = schedule.append( Acquire(5, AcquireChannel(0), MemorySlot(0), kernel=disc_one), ) schedule = schedule.append( Acquire(5, AcquireChannel(1), MemorySlot(1), kernel=disc_two), ) qobj = assemble(schedule, qubit_lo_freq=self.default_qubit_lo_freq, meas_lo_freq=self.default_meas_lo_freq, meas_map=[[0, 1]]) validate_qobj_against_schema(qobj) qobj_kernels = qobj.experiments[0].instructions[0].kernels self.assertEqual(len(qobj_kernels), 2) self.assertEqual(qobj_kernels[0].name, 'disc_one') self.assertEqual(qobj_kernels[0].params['test_params'], True) self.assertEqual(qobj_kernels[1].name, 'disc_two') self.assertEqual(qobj_kernels[1].params['test_params'], False)
def test_get_gate(self): """Test `get`.""" sched = Schedule() sched.append(Play(Waveform(np.ones(5)), DriveChannel(0))) inst_map = InstructionScheduleMap() inst_map.add(XGate(), 0, sched) self.assertEqual(sched, inst_map.get(XGate(), (0, )))
def build_parametric_pulse_schedule(number_of_unique_pulses, number_of_channels): sched = Schedule() for _ in range(number_of_unique_pulses): for channel in range(number_of_channels): sched.append( Play(Gaussian(duration=25, sigma=4, amp=0.5j), DriveChannel(channel))) return sched
def test_get(self): """Test `get`.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(DriveChannel(0))) inst_map = InstructionScheduleMap() inst_map.add('u1', 0, sched) self.assertEqual(sched, inst_map.get('u1', (0, )))
def test_pop(self): """Test pop with default.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(self.config.drive(0))) cmd_def = CmdDef() cmd_def.add('tmp', 0, sched) cmd_def.pop('tmp', 0) self.assertFalse(cmd_def.has('tmp', 0)) with self.assertRaises(PulseError): cmd_def.pop('not_there', (0, ))
def test_add(self): """Test `add`, `has`, `get`, `cmdss`.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(self.config.drive(0))) cmd_def = CmdDef() cmd_def.add('tmp', 1, sched) cmd_def.add('tmp', 0, sched) self.assertEqual(sched.instructions, cmd_def.get('tmp', (0,)).instructions) self.assertIn('tmp', cmd_def.cmds()) self.assertEqual(cmd_def.cmd_qubits('tmp'), [(0,), (1,)])
def test_add(self): """Test add, and that errors are raised when expected.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(DriveChannel(0))) inst_map = InstructionScheduleMap() inst_map.add('u1', 1, sched) inst_map.add('u1', 0, sched) self.assertIn('u1', inst_map.instructions) self.assertEqual(inst_map.qubits_with_instruction('u1'), [0, 1]) self.assertTrue('u1' in inst_map.qubit_instructions(0)) with self.assertRaises(PulseError): inst_map.add('u1', (), sched) with self.assertRaises(PulseError): inst_map.add('u1', 1, "not a schedule")
def test_add(self): """Test add, and that errors are raised when expected.""" sched = Schedule() sched.append(Play(Waveform(np.ones(5)), DriveChannel(0)), inplace=True) inst_map = InstructionScheduleMap() inst_map.add("u1", 1, sched) inst_map.add("u1", 0, sched) self.assertIn("u1", inst_map.instructions) self.assertEqual(inst_map.qubits_with_instruction("u1"), [0, 1]) self.assertTrue("u1" in inst_map.qubit_instructions(0)) with self.assertRaises(PulseError): inst_map.add("u1", (), sched) with self.assertRaises(PulseError): inst_map.add("u1", 1, "not a schedule")
def test_assemble_with_single_discriminators(self): """Test that assembly works with both a single discriminator.""" disc_one = Discriminator('disc_one', test_params=True) schedule = Schedule() schedule = schedule.append( Acquire(5, AcquireChannel(0), MemorySlot(0), discriminator=disc_one), ) schedule = schedule.append( Acquire(5, AcquireChannel(1), MemorySlot(1)), ) qobj = assemble(schedule, qubit_lo_freq=self.default_qubit_lo_freq, meas_lo_freq=self.default_meas_lo_freq, meas_map=[[0, 1]]) validate_qobj_against_schema(qobj) qobj_discriminators = qobj.experiments[0].instructions[0].discriminators self.assertEqual(len(qobj_discriminators), 1) self.assertEqual(qobj_discriminators[0].name, 'disc_one') self.assertEqual(qobj_discriminators[0].params['test_params'], True)
def test_repr(self): """Test repr.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(self.config.drive(0))) cmd_def = CmdDef({('tmp', 0): sched}) repr(cmd_def)
def test_init(self): """Test `init`, `has`.""" sched = Schedule() sched.append(SamplePulse(np.ones(5))(self.config.drive(0))) cmd_def = CmdDef({('tmp', 0): sched}) self.assertTrue(cmd_def.has('tmp', 0))
def get_calibration(self, params: List, qubits: List) -> Schedule: """ Args: params: Parameters of the RZXGate(theta). I.e. params[0] is theta. qubits: List of qubits for which to get the schedules. The first qubit is the control and the second is the target. Returns: schedule: The calibration schedule for the RZXGate(theta). Raises: QiskitError: if the control and target qubits cannot be identified or the backend does not support cx between the qubits. """ theta = params[0] q1, q2 = qubits[0], qubits[1] if not self._inst_map.has('cx', qubits): raise QiskitError( 'This transpilation pass requires the backend to support cx ' 'between qubits %i and %i.' % (q1, q2)) cx_sched = self._inst_map.get('cx', qubits=(q1, q2)) rzx_theta = Schedule(name='rzx(%.3f)' % theta) if theta == 0.0: return rzx_theta crs, comp_tones, shift_phases = [], [], [] control, target = None, None for time, inst in cx_sched.instructions: if isinstance(inst, ShiftPhase) and time == 0: shift_phases.append(ShiftPhase(-theta, inst.channel)) # Identify the CR pulses. if isinstance(inst, Play) and not isinstance(inst, ShiftPhase): if isinstance(inst.channel, ControlChannel): crs.append((time, inst)) # Identify the compensation tones. if isinstance(inst.channel, DriveChannel) and not isinstance(inst, ShiftPhase): if isinstance(inst.pulse, GaussianSquare): comp_tones.append((time, inst)) target = inst.channel.index control = q1 if target == q2 else q2 if control is None: raise QiskitError('Control qubit is None.') if target is None: raise QiskitError('Target qubit is None.') echo_x = self._inst_map.get('x', qubits=control) # Build the schedule for inst in shift_phases: rzx_theta = rzx_theta.insert(0, inst) # Stretch/compress the CR gates and compensation tones cr1 = self.rescale_cr_inst(crs[0][1], theta) cr2 = self.rescale_cr_inst(crs[1][1], theta) if len(comp_tones) == 0: comp1, comp2 = None, None elif len(comp_tones) == 2: comp1 = self.rescale_cr_inst(comp_tones[0][1], theta) comp2 = self.rescale_cr_inst(comp_tones[1][1], theta) else: raise QiskitError( 'CX must have either 0 or 2 rotary tones between qubits %i and %i ' 'but %i were found.' % (control, target, len(comp_tones))) # Build the schedule for the RZXGate rzx_theta = rzx_theta.insert(0, cr1) if comp1 is not None: rzx_theta = rzx_theta.insert(0, comp1) rzx_theta = rzx_theta.insert(comp1.duration, echo_x) time = comp1.duration + echo_x.duration rzx_theta = rzx_theta.insert(time, cr2) if comp2 is not None: rzx_theta = rzx_theta.insert(time, comp2) time = 2 * comp1.duration + echo_x.duration rzx_theta = rzx_theta.insert(time, echo_x) # Reverse direction of the ZX with Hadamard gates if control == qubits[0]: return rzx_theta else: rzc = self._inst_map.get('rz', [control], np.pi / 2) sxc = self._inst_map.get('sx', [control]) rzt = self._inst_map.get('rz', [target], np.pi / 2) sxt = self._inst_map.get('sx', [target]) h_sched = Schedule(name='hadamards') h_sched = h_sched.insert(0, rzc) h_sched = h_sched.insert(0, sxc) h_sched = h_sched.insert(sxc.duration, rzc) h_sched = h_sched.insert(0, rzt) h_sched = h_sched.insert(0, sxt) h_sched = h_sched.insert(sxc.duration, rzt) rzx_theta = h_sched.append(rzx_theta) return rzx_theta.append(h_sched)
def get_calibration(self, node_op: CircuitInst, qubits: List) -> Union[Schedule, ScheduleBlock]: """Builds the calibration schedule for the RZXGate(theta) with echos. Args: node_op: Instruction of the RZXGate(theta). I.e. params[0] is theta. qubits: List of qubits for which to get the schedules. The first qubit is the control and the second is the target. Returns: schedule: The calibration schedule for the RZXGate(theta). Raises: QiskitError: If the control and target qubits cannot be identified. CalibrationNotAvailable: RZX schedule cannot be built for input node. """ theta = node_op.params[0] rzx_theta = Schedule(name="rzx(%.3f)" % theta) rzx_theta.metadata["publisher"] = CalibrationPublisher.QISKIT if np.isclose(theta, 0.0): return rzx_theta cx_sched = self._inst_map.get("cx", qubits=qubits) cal_type, cr_tones, comp_tones = _check_calibration_type(cx_sched) if cal_type != CXCalType.ECR: if self._verbose: warnings.warn( f"CX instruction for qubits {qubits} is likely {cal_type.value} sequence. " "Pulse stretch for this calibration is not currently implemented. " "RZX schedule is not generated for this qubit pair.", UserWarning, ) raise CalibrationNotAvailable if len(comp_tones) == 0: raise QiskitError( f"{repr(cx_sched)} has no target compensation tones. " "Native CR direction cannot be determined.") # Determine native direction, assuming only single drive channel per qubit. # This guarantees channel and qubit index equality. is_native = comp_tones[0].channel.index == qubits[1] stretched_cr_tones = list( map(lambda p: self.rescale_cr_inst(p, theta), cr_tones)) stretched_comp_tones = list( map(lambda p: self.rescale_cr_inst(p, theta), comp_tones)) if is_native: xgate = self._inst_map.get("x", qubits[0]) for cr, comp in zip(stretched_cr_tones, stretched_comp_tones): current_dur = rzx_theta.duration rzx_theta.insert(current_dur, cr, inplace=True) rzx_theta.insert(current_dur, comp, inplace=True) rzx_theta.append(xgate, inplace=True) else: # Add hadamard gate to flip xgate = self._inst_map.get("x", qubits[1]) szc = self._inst_map.get("rz", qubits[1], np.pi / 2) sxc = self._inst_map.get("sx", qubits[1]) szt = self._inst_map.get("rz", qubits[0], np.pi / 2) sxt = self._inst_map.get("sx", qubits[0]) # Hadamard to control rzx_theta.insert(0, szc, inplace=True) rzx_theta.insert(0, sxc, inplace=True) rzx_theta.insert(sxc.duration, szc, inplace=True) # Hadamard to target rzx_theta.insert(0, szt, inplace=True) rzx_theta.insert(0, sxt, inplace=True) rzx_theta.insert(sxt.duration, szt, inplace=True) for cr, comp in zip(stretched_cr_tones, stretched_comp_tones): current_dur = rzx_theta.duration rzx_theta.insert(current_dur, cr, inplace=True) rzx_theta.insert(current_dur, comp, inplace=True) rzx_theta.append(xgate, inplace=True) current_dur = rzx_theta.duration # Hadamard to control rzx_theta.insert(current_dur, szc, inplace=True) rzx_theta.insert(current_dur, sxc, inplace=True) rzx_theta.insert(current_dur + sxc.duration, szc, inplace=True) # Hadamard to target rzx_theta.insert(current_dur, szt, inplace=True) rzx_theta.insert(current_dur, sxt, inplace=True) rzx_theta.insert(current_dur + sxt.duration, szt, inplace=True) return rzx_theta
def get_calibration(self, node_op: CircuitInst, qubits: List) -> Union[Schedule, ScheduleBlock]: """Builds the calibration schedule for the RZXGate(theta) with echos. Args: node_op: Instruction of the RZXGate(theta). I.e. params[0] is theta. qubits: List of qubits for which to get the schedules. The first qubit is the control and the second is the target. Returns: schedule: The calibration schedule for the RZXGate(theta). Raises: QiskitError: if the control and target qubits cannot be identified or the backend does not support cx between the qubits. """ theta = node_op.params[0] q1, q2 = qubits[0], qubits[1] if not self._inst_map.has("cx", qubits): raise QiskitError( "This transpilation pass requires the backend to support cx " "between qubits %i and %i." % (q1, q2)) cx_sched = self._inst_map.get("cx", qubits=(q1, q2)) rzx_theta = Schedule(name="rzx(%.3f)" % theta) rzx_theta.metadata["publisher"] = CalibrationPublisher.QISKIT if theta == 0.0: return rzx_theta crs, comp_tones = [], [] control, target = None, None for time, inst in cx_sched.instructions: # Identify the CR pulses. if isinstance(inst, Play) and not isinstance(inst, ShiftPhase): if isinstance(inst.channel, ControlChannel): crs.append((time, inst)) # Identify the compensation tones. if isinstance(inst.channel, DriveChannel) and not isinstance(inst, ShiftPhase): if isinstance(inst.pulse, GaussianSquare): comp_tones.append((time, inst)) target = inst.channel.index control = q1 if target == q2 else q2 if control is None: raise QiskitError("Control qubit is None.") if target is None: raise QiskitError("Target qubit is None.") echo_x = self._inst_map.get("x", qubits=control) # Build the schedule # Stretch/compress the CR gates and compensation tones cr1 = self.rescale_cr_inst(crs[0][1], theta) cr2 = self.rescale_cr_inst(crs[1][1], theta) if len(comp_tones) == 0: comp1, comp2 = None, None elif len(comp_tones) == 2: comp1 = self.rescale_cr_inst(comp_tones[0][1], theta) comp2 = self.rescale_cr_inst(comp_tones[1][1], theta) else: raise QiskitError( "CX must have either 0 or 2 rotary tones between qubits %i and %i " "but %i were found." % (control, target, len(comp_tones))) # Build the schedule for the RZXGate rzx_theta = rzx_theta.insert(0, cr1) if comp1 is not None: rzx_theta = rzx_theta.insert(0, comp1) rzx_theta = rzx_theta.insert(comp1.duration, echo_x) time = comp1.duration + echo_x.duration rzx_theta = rzx_theta.insert(time, cr2) if comp2 is not None: rzx_theta = rzx_theta.insert(time, comp2) time = 2 * comp1.duration + echo_x.duration rzx_theta = rzx_theta.insert(time, echo_x) # Reverse direction of the ZX with Hadamard gates if control == qubits[0]: return rzx_theta else: rzc = self._inst_map.get("rz", [control], np.pi / 2) sxc = self._inst_map.get("sx", [control]) rzt = self._inst_map.get("rz", [target], np.pi / 2) sxt = self._inst_map.get("sx", [target]) h_sched = Schedule(name="hadamards") h_sched = h_sched.insert(0, rzc) h_sched = h_sched.insert(0, sxc) h_sched = h_sched.insert(sxc.duration, rzc) h_sched = h_sched.insert(0, rzt) h_sched = h_sched.insert(0, sxt) h_sched = h_sched.insert(sxc.duration, rzt) rzx_theta = h_sched.append(rzx_theta) return rzx_theta.append(h_sched)