Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ShiftFrequency instruction to pulse #4390

Merged
merged 22 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion qiskit/pulse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@
from .configuration import LoConfig, LoRange, Kernel, Discriminator
from .exceptions import PulseError
from .instruction_schedule_map import InstructionScheduleMap
from .instructions import Acquire, Instruction, Delay, Play, ShiftPhase, Snapshot, SetFrequency
from .instructions import (Acquire, Instruction, Delay, Play, ShiftPhase, Snapshot,
SetFrequency, ShiftFrequency)
from .interfaces import ScheduleComponent
from .pulse_lib import (SamplePulse, Gaussian, GaussianSquare, Drag,
Constant, ConstantPulse, ParametricPulse)
Expand Down
3 changes: 2 additions & 1 deletion qiskit/pulse/instructions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
Delay
Play
SetFrequency
ShiftFrequency
ShiftPhase
Snapshot

Expand All @@ -53,7 +54,7 @@
from .acquire import Acquire
from .delay import Delay
from .instruction import Instruction
from .frequency import SetFrequency
from .frequency import SetFrequency, ShiftFrequency
from .phase import ShiftPhase
from .play import Play
from .snapshot import Snapshot
30 changes: 30 additions & 0 deletions qiskit/pulse/instructions/frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,33 @@ def channel(self) -> PulseChannel:
scheduled on.
"""
return self._channel


class ShiftFrequency(Instruction):
"""Shift the channel frequency away from the set frequency."""
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, frequency: float,
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
channel: PulseChannel,
name: Optional[str] = None):
"""Creates a new shift frequency instruction.

Args:
frequency: Frequency shift of the channel in Hz.
channel: The channel this instruction operates on.
name: Name of this set channel frequency command.
"""
self._frequency = float(frequency)
self._channel = channel
super().__init__((frequency, channel), 0, (channel,), name=name)

@property
def frequency(self) -> float:
"""Frequency shift from the set frequency."""
return self._frequency

@property
def channel(self) -> PulseChannel:
"""Return the :py:class:`~qiskit.pulse.channels.Channel` that this instruction is
scheduled on.
"""
return self._channel
44 changes: 44 additions & 0 deletions qiskit/qobj/converters/pulse_instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,25 @@ def convert_set_frequency(self, shift, instruction):
}
return self._qobj_model(**command_dict)

@bind_instruction(instructions.ShiftFrequency)
def convert_shift_frequency(self, shift, instruction):
"""Return converted `ShiftFrequency`.

Args:
shift (int): Offset time.
instruction (ShiftFrequency): Shift frequency instruction.

Returns:
dict: Dictionary of required parameters.
"""
command_dict = {
'name': 'shiftf',
't0': shift+instruction.start_time,
'ch': instruction.channel.name,
'frequency': instruction.frequency
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
}
return self._qobj_model(**command_dict)
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved

@bind_instruction(instructions.ShiftPhase)
def convert_shift_phase(self, shift, instruction):
"""Return converted `ShiftPhase`.
Expand Down Expand Up @@ -545,6 +564,31 @@ def gen_sf_schedule(*args, **kwargs):

return instructions.SetFrequency(frequency, channel) << t0

@bind_name('shiftf')
def convert_shift_frequency(self, instruction):
"""Return converted `ShiftFrequency`.

Args:
instruction (PulseQobjInstruction): Shift frequency qobj instruction.

Returns:
Schedule: Converted and scheduled Instruction
"""
t0 = instruction.t0
channel = self.get_channel(instruction.ch)
frequency = instruction.frequency
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved

if isinstance(frequency, str):
frequency_expr = parse_string_expr(frequency, partial_binding=False)

def gen_sf_schedule(*args, **kwargs):
_frequency = frequency_expr(*args, **kwargs)
return instructions.ShiftFrequency(_frequency, channel) << t0

return ParameterizedSchedule(gen_sf_schedule, parameters=frequency_expr.params)

return instructions.ShiftFrequency(frequency, channel) << t0

@bind_name('delay')
def convert_delay(self, instruction):
"""Return converted `Delay`.
Expand Down
12 changes: 11 additions & 1 deletion qiskit/visualization/pulse/matplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from qiskit.pulse.commands import FrameChangeInstruction
from qiskit.pulse import (SamplePulse, FrameChange, PersistentValue, Snapshot, Play,
Acquire, PulseError, ParametricPulse, SetFrequency, ShiftPhase,
Instruction, ScheduleComponent)
Instruction, ScheduleComponent, ShiftFrequency)


class EventsOutputChannels:
Expand Down Expand Up @@ -105,6 +105,14 @@ def frequencychanges(self) -> Dict[int, SetFrequency]:

return self._trim(self._frequencychanges)

@property
def frequencyshift(self) -> Dict[int, ShiftFrequency]:
"""Set the frequency changes."""
if self._frequencychanges is None:
self._build_waveform()

return self._trim(self._frequencychanges)

@property
def conditionals(self) -> Dict[int, str]:
"""Get conditionals."""
Expand Down Expand Up @@ -194,6 +202,8 @@ def _build_waveform(self):
pv[time:] = 0
elif isinstance(command, SetFrequency):
tmp_sf = command.frequency
elif isinstance(command, ShiftFrequency):
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
tmp_sf = command.frequency
elif isinstance(command, Snapshot):
self._snapshots[time] = command.name
if tmp_fc != 0:
Expand Down
24 changes: 17 additions & 7 deletions test/python/pulse/test_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from qiskit.pulse import (Play, SamplePulse, ShiftPhase, Instruction, SetFrequency, Acquire,
pulse_lib, Snapshot, Delay, Gaussian, Drag, GaussianSquare, Constant,
functional_pulse)
functional_pulse, ShiftFrequency)
from qiskit.pulse.channels import (MemorySlot, RegisterSlot, DriveChannel, AcquireChannel,
SnapshotChannel, MeasureChannel)
from qiskit.pulse.commands import PersistentValue, PulseInstruction
Expand Down Expand Up @@ -653,6 +653,7 @@ def test_filter_inst_types(self):
sched = sched.insert(10, Play(lp0, self.config.drive(1)))
sched = sched.insert(30, ShiftPhase(-1.57, self.config.drive(0)))
sched = sched.insert(40, SetFrequency(8.0, self.config.drive(0)))
sched = sched.insert(50, ShiftFrequency(4.0, self.config.drive(0)))
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
for i in range(2):
sched = sched.insert(60, Acquire(5, self.config.acquire(i), MemorySlot(i)))
sched = sched.insert(90, Play(lp0, self.config.drive(0)))
Expand All @@ -674,22 +675,31 @@ def test_filter_inst_types(self):
for _, inst in no_pulse_and_fc.instructions:
self.assertFalse(isinstance(inst, (Play, ShiftPhase)))
self.assertEqual(len(only_pulse_and_fc.instructions), 4)
self.assertEqual(len(no_pulse_and_fc.instructions), 3)
self.assertEqual(len(no_pulse_and_fc.instructions), 4)

# test on ShiftPhase
only_fc, no_fc = \
self._filter_and_test_consistency(sched, instruction_types={ShiftPhase})
self.assertEqual(len(only_fc.instructions), 1)
self.assertEqual(len(no_fc.instructions), 6)
self.assertEqual(len(no_fc.instructions), 7)

# test on SetFrequency
only_sf, no_sf = \
only_setf, no_setf = \
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
self._filter_and_test_consistency(sched,
instruction_types=[SetFrequency])
for _, inst in only_sf.instructions:
for _, inst in only_setf.instructions:
self.assertTrue(isinstance(inst, SetFrequency))
self.assertEqual(len(only_sf.instructions), 1)
self.assertEqual(len(no_sf.instructions), 6)
self.assertEqual(len(only_setf.instructions), 1)
self.assertEqual(len(no_setf.instructions), 7)

# test on ShiftFrequency
only_shiftf, no_shiftf = \
self._filter_and_test_consistency(sched,
instruction_types=[ShiftFrequency])
for _, inst in only_shiftf.instructions:
self.assertTrue(isinstance(inst, ShiftFrequency))
self.assertEqual(len(only_shiftf.instructions), 1)
self.assertEqual(len(no_shiftf.instructions), 7)

def test_filter_intervals(self):
"""Test filtering on intervals."""
Expand Down
30 changes: 28 additions & 2 deletions test/python/qobj/test_pulse_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
LoConfigConverter)
from qiskit.pulse.commands import (SamplePulse, FrameChange, PersistentValue, Snapshot, Acquire,
Gaussian, GaussianSquare, Constant, Drag)
from qiskit.pulse.instructions import ShiftPhase, SetFrequency, Play, Delay
from qiskit.pulse.instructions import ShiftPhase, SetFrequency, Play, Delay, ShiftFrequency
from qiskit.pulse.channels import (DriveChannel, ControlChannel, MeasureChannel, AcquireChannel,
MemorySlot, RegisterSlot)
from qiskit.pulse.schedule import ParameterizedSchedule, Schedule
Expand Down Expand Up @@ -157,6 +157,20 @@ def test_set_frequency(self):

self.assertEqual(converter(0, instruction), valid_qobj)

def test_shift_frequency(self):
"""Test converted qobj from ShiftFrequency."""
converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2)
instruction = ShiftFrequency(8.0, DriveChannel(0))
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved

valid_qobj = PulseQobjInstruction(
name='shiftf',
ch='d0',
t0=0,
frequency=8.0
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
)

self.assertEqual(converter(0, instruction), valid_qobj)

def test_persistent_value(self):
"""Test converted qobj from PersistentValueInstruction."""
converter = InstructionToQobjConverter(PulseQobjInstruction, meas_level=2)
Expand Down Expand Up @@ -301,7 +315,7 @@ def test_frame_change(self):
self.assertEqual(converted_instruction.instructions[0][-1], instruction)

def test_set_frequency(self):
"""Test converted qobj from FrameChangeInstruction."""
"""Test converted qobj from SetFrequency."""
instruction = SetFrequency(8.0, DriveChannel(0))

qobj = PulseQobjInstruction(name='setf', ch='d0', t0=0, frequency=8.0)
Expand All @@ -312,6 +326,18 @@ def test_set_frequency(self):
self.assertEqual(converted_instruction.instructions[0][-1], instruction)
self.assertTrue('frequency' in qobj.to_dict())

def test_shift_frequency(self):
"""Test converted qobj from ShiftFrequency."""
instruction = ShiftFrequency(8.0, DriveChannel(0))

qobj = PulseQobjInstruction(name='shiftf', ch='d0', t0=0, frequency=8.0)
converted_instruction = self.converter(qobj)

self.assertEqual(converted_instruction.start_time, 0)
self.assertEqual(converted_instruction.duration, 0)
self.assertEqual(converted_instruction.instructions[0][-1], instruction)
self.assertTrue('frequency' in qobj.to_dict())

def test_delay(self):
"""Test converted qobj from Delay."""
instruction = Delay(10, DriveChannel(0))
Expand Down
6 changes: 4 additions & 2 deletions test/python/qobj/test_qobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ def setUp(self):
PulseQobjInstruction(name='fc', t0=5, ch='d0', phase='P1'),
PulseQobjInstruction(name='pv', t0=10, ch='d0', val=0.1 + 0.0j),
PulseQobjInstruction(name='pv', t0=10, ch='d0', val='P1'),
PulseQobjInstruction(name='sf', t0=10, ch='d0', frequency=8.),
PulseQobjInstruction(name='setf', t0=10, ch='d0', frequency=8.),
PulseQobjInstruction(name='shiftf', t0=10, ch='d0', frequency=4.0),
PulseQobjInstruction(name='acquire', t0=15, duration=5,
qubits=[0], memory_slot=[0],
kernels=[
Expand Down Expand Up @@ -265,7 +266,8 @@ def setUp(self):
{'name': 'fc', 't0': 5, 'ch': 'd0', 'phase': 'P1'},
{'name': 'pv', 't0': 10, 'ch': 'd0', 'val': 0.1+0j},
{'name': 'pv', 't0': 10, 'ch': 'd0', 'val': 'P1'},
{'name': 'sf', 't0': 10, 'ch': 'd0', 'frequency': 8.0},
{'name': 'setf', 't0': 10, 'ch': 'd0', 'frequency': 8.0},
{'name': 'shiftf', 't0': 10, 'ch': 'd0', 'frequency': 4.0},
{'name': 'acquire', 't0': 15, 'duration': 5,
'qubits': [0], 'memory_slot': [0],
'kernels': [{'name': 'boxcar',
Expand Down
3 changes: 2 additions & 1 deletion test/python/visualization/test_pulse_visualization_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qiskit.pulse.channels import (DriveChannel, MeasureChannel, ControlChannel, AcquireChannel,
MemorySlot, RegisterSlot)
from qiskit.pulse.commands import FrameChange
from qiskit.pulse.instructions import SetFrequency, Play, Acquire, Delay, Snapshot
from qiskit.pulse.instructions import SetFrequency, Play, Acquire, Delay, Snapshot, ShiftFrequency
from qiskit.pulse.schedule import Schedule
from qiskit.tools.visualization import HAS_MATPLOTLIB
from qiskit.visualization import pulse_drawer
Expand Down Expand Up @@ -68,6 +68,7 @@ def sample_schedule(self):
ControlChannel(0)))
sched = sched.insert(60, FrameChange(phase=-1.57)(DriveChannel(0)))
sched = sched.insert(60, SetFrequency(8.0, DriveChannel(0)))
sched = sched.insert(70, ShiftFrequency(4.0, DriveChannel(0)))
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
sched = sched.insert(30, gp1(DriveChannel(1)))
sched = sched.insert(60, gp0(ControlChannel(0)))
sched = sched.insert(60, gs0(MeasureChannel(0)))
Expand Down