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

Issue 3750 wrap up #4034

Merged
merged 34 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ebaf14a
Clean up instructions and update documentation
lcapelluto Mar 19, 2020
0a1c1f0
Documentation improvements, add 'name=' to Instruction repr
lcapelluto Mar 26, 2020
a5d8ad6
Fixup description of operands (does not return a list now, returns a …
lcapelluto Mar 27, 2020
8d4a2e1
Clean up magic methods for Pulse and its subclasses
lcapelluto Mar 27, 2020
d66d9c6
Add more tests for instructions and move Pulse tests into a new pulse…
lcapelluto Mar 27, 2020
9ddbe40
Give instructions an ID. Give instructions a simple default name if o…
lcapelluto Mar 30, 2020
304c613
Give pulses ids too
lcapelluto Mar 30, 2020
1ed82cd
fixup some documentation and style
lcapelluto Mar 30, 2020
1baf335
Fixup name printing of pulses: Display names are not auto generated. …
lcapelluto Mar 30, 2020
3c1e2f2
Remove deprecation warnings from reschedule
lcapelluto Mar 31, 2020
aa68680
Try to fix missing docs links
lcapelluto Mar 31, 2020
90c05b8
Hide full path of module in autosum
lcapelluto Mar 31, 2020
d93defb
Add an autosummary to the pulse lib init file for api ref
lcapelluto Mar 31, 2020
489ee64
Apply suggestions from code review
lcapelluto Mar 31, 2020
2e5bfb9
Fixup style errors that I introduced during review
lcapelluto Mar 31, 2020
cbbc4dc
Cannot use 'Pulse' type hint from 'Play' due to cyclic import while d…
lcapelluto Apr 1, 2020
8f98e51
Respond to feedback: improve documentation about instruction operands
lcapelluto Apr 1, 2020
7f2571c
Upgrade to threadsafe ids for Pulse and Instruction: no longer is the…
lcapelluto Apr 1, 2020
57f5c17
Fixup style (ignore id is not a valid name)
lcapelluto Apr 1, 2020
e1775e3
No display name if it is not provided by the user
lcapelluto Apr 1, 2020
6342468
Update qiskit/pulse/instructions/play.py
lcapelluto Apr 1, 2020
c13c144
Update tests and instruction repr for None default name
lcapelluto Apr 1, 2020
8bc38ae
Style fix
lcapelluto Apr 1, 2020
f07d177
Update qiskit/pulse/instructions/play.py
lcapelluto Apr 1, 2020
3563220
Merge branch 'master' into issue-3750-wrap-up
lcapelluto Apr 1, 2020
5f790b5
Remove danp's trailing whitespace :D
lcapelluto Apr 1, 2020
731f639
PulseCommand is not used anywhere now and can be removed
lcapelluto Apr 2, 2020
70dae97
Improve deprecation messaging for pulses being called
lcapelluto Apr 2, 2020
c266541
Include operands as the first argument to Instruction
lcapelluto Apr 2, 2020
2ab1b35
Merge branch 'master' into issue-3750-wrap-up
lcapelluto Apr 2, 2020
136fc2b
Fixup docs error
lcapelluto Apr 2, 2020
97beb28
Merge branch 'issue-3750-wrap-up' of github.com:lcapelluto/qiskit-ter…
lcapelluto Apr 2, 2020
e3c7a48
Make Instruction init arg take a tuple rather than a list
lcapelluto Apr 2, 2020
d3209ce
Merge branch 'master' into issue-3750-wrap-up
lcapelluto Apr 2, 2020
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
52 changes: 26 additions & 26 deletions qiskit/pulse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,44 @@
instructions. Pulse answers that need: it enables the quantum physicist *user* to specify the
exact time dynamics of an experiment. It is especially powerful for error mitigation techniques.

The input is given as arbitrary, time-ordered signals (see: :ref:`pulse-commands`) scheduled in
The input is given as arbitrary, time-ordered signals (see: :ref:`pulse-insts`) scheduled in
parallel over multiple virtual hardware or simulator resources (see: :ref:`pulse-channels`). The
system also allows the user to recover the time dynamics of the measured output.

This is sufficient to allow the quantum physicist to explore and correct for noise in a quantum
system.

.. _pulse-commands:
.. _pulse-insts:

Commands (:mod:`~qiskit.pulse.commands`)
========================================
Instructions (:mod:`~qiskit.pulse.instructions`)
================================================

.. autosummary::
:toctree: ../stubs/

SamplePulse
~qiskit.pulse.instructions

Acquire
Delay
FrameChange
Play
SetFrequency
ShiftPhase
Snapshot

Pulse Library (waveforms :mod:`~qiskit.pulse.pulse_lib`)
========================================================

.. autosummary::
:toctree: ../stubs/

~qiskit.pulse.pulse_lib

~qiskit.pulse.pulse_lib.discrete
SamplePulse
ConstantPulse
Drag
Gaussian
GaussianSquare
Drag
ConstantPulse
Acquire
Snapshot

.. _pulse-channels:

Expand All @@ -66,6 +80,8 @@
.. autosummary::
:toctree: ../stubs/

~qiskit.pulse.channels

DriveChannel
MeasureChannel
AcquireChannel
Expand All @@ -77,21 +93,13 @@
=========

Schedules are Pulse programs. They describe instruction sequences for the control hardware.
An :class:`~qiskit.pulse.Instruction` is a :py:class:`~qiskit.pulse.commands.Command` which has
been assigned to its :class:`~qiskit.pulse.channels.Channel` (s).

.. autosummary::
:toctree: ../stubs/

Schedule
Instruction

.. autosummary::
:toctree: ../stubs/

qiskit.pulse.commands
qiskit.pulse.channels

Configuration
=============

Expand All @@ -112,14 +120,6 @@
~reschedule.add_implicit_acquires
~reschedule.pad

Pulse Library
=============

.. autosummary::
:toctree: ../stubs/

~qiskit.pulse.pulse_lib.discrete

Exceptions
==========

Expand Down
30 changes: 6 additions & 24 deletions qiskit/pulse/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,13 @@

# pylint: disable=cyclic-import

"""
Supported command types in Pulse.

.. autosummary::
:toctree: ../stubs/

Acquire
FrameChange
SamplePulse
Snapshot
Delay
Gaussian
GaussianSquare
Drag
ConstantPulse
"""Supported command types in Pulse. This directory is deprecated.

Abstract Classes
----------------
.. autosummary::
:toctree: ../stubs/

ParametricPulse
Command

"""
AcquireInstruction, FrameChange, FrameChangeInstruction, PersistentValue,
PersistentValueInstruction, PulseInstruction, DelayInstruction and ParametricInstruction are all
deprecated. When they are removed, this ``pulse.commands`` import path for the remaining objects
can also be deprecated.
"""
from .acquire import Acquire, AcquireInstruction
from .frame_change import FrameChange, FrameChangeInstruction
from .meas_opts import Discriminator, Kernel
Expand Down
6 changes: 4 additions & 2 deletions qiskit/pulse/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def __init__(self, name: Optional[str] = None, **params):
def __repr__(self):
return "{}({}{})".format(self.__class__.__name__,
"'" + self.name + "', " or "",
', '.join("{}={}".format(str(k), str(v)) for k, v in self.params))
', '.join("{}={}".format(str(k), str(v))
for k, v in self.params.items()))


class Discriminator:
Expand All @@ -60,7 +61,8 @@ def __init__(self, name: Optional[str] = None, **params):
def __repr__(self):
return "{}({}{})".format(self.__class__.__name__,
"'" + self.name + "', " or "",
', '.join("{}={}".format(str(k), str(v)) for k, v in self.params))
', '.join("{}={}".format(str(k), str(v))
for k, v in self.params.items()))


class LoRange:
Expand Down
4 changes: 1 addition & 3 deletions qiskit/pulse/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
Exception for errors raised by pulse module.
"""
"""Exception for errors raised by the pulse module."""
from qiskit.exceptions import QiskitError


Expand Down
2 changes: 2 additions & 0 deletions qiskit/pulse/instruction_schedule_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class InstructionScheduleMap():
where the first key is the name of a circuit instruction (e.g. ``'u1'``, ``'measure'``), the
second key is a tuple of qubit indices, and the final value is a Schedule implementing the
requested instruction.

These can usually be seen as gate calibrations.
"""

def __init__(self):
Expand Down
35 changes: 28 additions & 7 deletions qiskit/pulse/instructions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,42 @@
# that they have been altered from the originals.

"""The ``instruction`` module holds the various ``Instruction`` s which are supported by
Qiskit Pulse. Instructions accept a list of operands unique to instructions of that type.
Instructions typically include at least one :py:class:`~qiskit.pulse.channels.Channel` as an
operand specifying where the instruction will be applied, and every instruction has a duration,
whether implicitly or explicitly defined.
Qiskit Pulse. Instructions have operands, which typically include at least one
:py:class:`~qiskit.pulse.channels.Channel` specifying where the instruction will be applied.

Every instruction has a duration, whether explicitly included as an operand or implicitly defined.
For instance, a :py:class:`~qiskit.pulse.instructions.ShiftPhase` instruction can be instantiated
with operands *phase* and *channel*, for some float ``phase`` and a
:py:class`~qiskit.pulse.channels.Channel` ``channel``::
:py:class:`~qiskit.pulse.channels.Channel` ``channel``::

ShiftPhase(phase, channel)

The duration of this instruction is implicitly zero.
The duration of this instruction is implicitly zero. On the other hand, the
:py:class:`~qiskit.pulse.instructions.Delay` instruction takes an explicit duration::

Delay(duration, channel)

An instruction can be added to a :py:class:`~qiskit.pulse.Schedule`, which is a
sequence of scheduled Pulse ``Instruction`` s over many channels.
sequence of scheduled Pulse ``Instruction`` s over many channels. ``Instruction`` s and
``Schedule`` s implement the same interface.

.. autosummary::
:toctree: ../stubs/

Acquire
Delay
Play
SetFrequency
ShiftPhase
Snapshot

Abstract Classes
----------------
.. autosummary::
:toctree: ../stubs/

Instruction

"""
from .acquire import Acquire
from .delay import Delay
Expand Down
34 changes: 14 additions & 20 deletions qiskit/pulse/instructions/acquire.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""
import warnings

from typing import List, Optional, Union
from typing import List, Optional, Tuple, Union

from ..channels import MemorySlot, RegisterSlot, AcquireChannel
from ..configuration import Kernel, Discriminator
Expand Down Expand Up @@ -107,29 +107,26 @@ def __init__(self,
else:
reg_slot = []

if name is None and channels is None:
name = 'acq{:10x}'.format(hash((duration, kernel, discriminator)))
elif name is None:
name = 'acq{:10x}'.format(hash((duration, tuple(channels), tuple(mem_slot),
tuple(reg_slot), kernel, discriminator)))

if channels is not None:
super().__init__(duration, *channels, *mem_slot, *reg_slot, name=name)
else:
super().__init__(duration, name=name)

self._acquires = channels
self._channel = channels[0] if channels else None
self._mem_slots = mem_slot
self._reg_slots = reg_slot
self._kernel = kernel
self._discriminator = discriminator

if channels is not None:
super().__init__(duration, *channels, *mem_slot, *reg_slot, name=name)
else:
warnings.warn("Usage of Acquire without specifying a channel is deprecated. For "
"example, Acquire(1200)(AcquireChannel(0)) should be replaced by "
"Acquire(1200, AcquireChannel(0)).", DeprecationWarning)
super().__init__(duration, name=name)

@property
def operands(self) -> List:
"""Return a list of instruction operands."""
return [self.duration, self.channel,
self.mem_slot, self.reg_slot]
def operands(self) -> Tuple[int, AcquireChannel, MemorySlot, RegisterSlot]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be limited to one of MemorySlot or RegisterSlot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen that restriction anywhere else, what does that stem from? I've seen tests with acquire taking memslot and reg slot. No one uses register slots yet, so it's possible they're not handled correctly in a couple places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can users not use readout results for fast feedback and also get that result?

Copy link
Contributor

@taalexander taalexander Apr 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be a practical restriction in the hardware. In reality it would be something like

  1. acquire qubit into register
  2. store register into memory

Storing directly into a memory_slot is currently supported but is a convenience that masks hardware implementation. I would like to get away from multi-purpose instructions and I think this is a good first step that can be made while we are already changing the interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so Acquire should really only take a register slot. This seems like an implementation change that is out of scope for this PR. Maybe next sprint?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we be able to make the change before release?

"""Return instruction operands."""
return (self.duration, self.channel,
self.mem_slot, self.reg_slot)

@property
def channel(self) -> AcquireChannel:
Expand Down Expand Up @@ -182,7 +179,7 @@ def reg_slots(self) -> List[RegisterSlot]:
"""RegisterSlots."""
return self._reg_slots

def __repr__(self):
def __repr__(self) -> str:
return "{}({}{}{}{}{}{})".format(
self.__class__.__name__,
self.duration,
Expand All @@ -192,9 +189,6 @@ def __repr__(self):
', ' + str(self.kernel) if self.kernel else '',
', ' + str(self.discriminator) if self.discriminator else '')

def __eq__(self, other):
return isinstance(other, type(self)) and self.operands == other.operands

def __call__(self,
channel: Optional[Union[AcquireChannel, List[AcquireChannel]]] = None,
mem_slot: Optional[Union[MemorySlot, List[MemorySlot]]] = None,
Expand Down
23 changes: 9 additions & 14 deletions qiskit/pulse/instructions/delay.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
"""An instruction for blocking time on a channel; useful for scheduling alignment."""
import warnings

from typing import List, Optional, Union
from typing import Optional, Tuple

from qiskit.pulse.channels import PulseChannel
from qiskit.pulse.exceptions import PulseError
from ..channels import Channel
from ..exceptions import PulseError
from .instruction import Instruction


Expand All @@ -39,7 +39,7 @@ class Delay(Instruction):
"""

def __init__(self, duration: int,
channel: Optional[PulseChannel] = None,
channel: Optional[Channel] = None,
name: Optional[str] = None):
"""Create a new delay instruction.

Expand All @@ -58,18 +58,18 @@ def __init__(self, duration: int,
super().__init__(duration, channel, name=name)

@property
def operands(self) -> List[Union[int, PulseChannel]]:
"""Return a list of instruction operands."""
return [self.duration, self.channel]
def operands(self) -> Tuple[int, Channel]:
"""Return instruction operands."""
return (self.duration, self.channel)

@property
def channel(self) -> PulseChannel:
def channel(self) -> Channel:
"""Return the :py:class:`~qiskit.pulse.channels.Channel` that this instruction is
scheduled on.
"""
return self._channel

def __call__(self, channel: PulseChannel) -> 'Delay':
def __call__(self, channel: Channel) -> 'Delay':
"""Return new ``Delay`` that is fully instantiated with both ``duration`` and a ``channel``.

Args:
Expand All @@ -86,8 +86,3 @@ def __call__(self, channel: PulseChannel) -> 'Delay':
if self._channel is not None:
raise PulseError("The channel has already been assigned as {}.".format(self.channel))
return Delay(self.duration, channel)

def __repr__(self):
return "{}({}, {})".format(self.__class__.__name__,
self.duration,
self.channel)
Loading