예제 #1
0
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
예제 #2
0
    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)
예제 #3
0
    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, )))
예제 #4
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
예제 #5
0
    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, )))
예제 #6
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, ))
예제 #7
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,)])
예제 #8
0
    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")
예제 #10
0
    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)
예제 #11
0
 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)
예제 #12
0
 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)
예제 #14
0
    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
예제 #15
0
    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)