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 1 commit
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
29 changes: 29 additions & 0 deletions qiskit/pulse/instructions/frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,32 @@ def channel(self) -> PulseChannel:
scheduled on.
"""
return self._channel


class ShiftFrequency(Instruction):
r"""Shift the channel frequency away from the LO 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: Optional[PulseChannel],
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
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:
"""New frequency."""
SooluThomas marked this conversation as resolved.
Show resolved Hide resolved
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
43 changes: 43 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_set_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,30 @@ 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): set 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('pv')
def convert_persistent_value(self, instruction):
"""Return converted `PersistentValueInstruction`.
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
25 changes: 18 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 @@ -611,6 +611,7 @@ class TestScheduleFilter(BaseTestSchedule):
def test_filter_channels(self):
"""Test filtering over channels."""
lp0 = self.linear(duration=3, slope=0.2, intercept=0.1)
import ipdb; ipdb.set_trace()
sched = Schedule(name='fake_experiment')
sched = sched.insert(0, Play(lp0, self.config.drive(0)))
sched = sched.insert(10, Play(lp0, self.config.drive(1)))
Expand Down Expand Up @@ -653,6 +654,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 +676,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
from qiskit.pulse.instructions import ShiftPhase, SetFrequency, ShiftFrequency, Play
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_persistent_value(self):
"""Test converted qobj from PersistentValueInstruction."""
with self.assertWarns(DeprecationWarning):
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