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

Pulse builder interface #4174

Merged
merged 294 commits into from
Jul 8, 2020
Merged

Conversation

taalexander
Copy link
Contributor

@taalexander taalexander commented Apr 18, 2020

Summary

This PR adds a new imperative pulse builder interface based on contextvars. This enables an interface like described below.

Details and comments

Example of using the pulse builder interface:

    import math

    from qiskit import QuantumCircuit
    import qiskit.pulse as pulse
    import qiskit.pulse.pulse_lib as pulse_lib
    from qiskit.test.mock import FakeOpenPulse2Q

    backend = FakeOpenPulse2Q()

    with pulse.build(backend) as pulse_prog:
        # Create a pulse.
        gaussian_pulse = pulse_lib.gaussian(10, 1.0, 2)
        # Get the qubit's corresponding drive channel from the backend.
        d0 = pulse.drive_channel(0)
        d1 = pulse.drive_channel(1)
        # Play a pulse at t=0.
        pulse.play(gaussian_pulse, d0)
        # Play another pulse directly after the previous pulse at t=10.
        pulse.play(gaussian_pulse, d0)
        # The default scheduling behavior is to schedule pulses in parallel
        # across channels. For example, the statement below
        # plays the same pulse on a different channel at t=0.
        pulse.play(gaussian_pulse, d1)

        # We also provide pulse scheduling alignment contexts.
        # The default alignment context is align_left.

        # The sequential context schedules pulse instructions sequentially in time.
        # This context starts at t=10 due to earlier pulses above.
        with pulse.align_sequential():
            pulse.play(gaussian_pulse, d0)
            # Play another pulse after at t=20.
            pulse.play(gaussian_pulse, d1)

            # We can also nest contexts as each instruction is
            # contained in its local scheduling context.
            # The output of a child context is a scheduled block
            # with the internal instructions timing fixed relative to
            # one another. This is block is then called in the parent context.

            # Context starts at t=30.
            with pulse.align_left():
                # Start at t=30.
                pulse.play(gaussian_pulse, d0)
                # Start at t=30.
                pulse.play(gaussian_pulse, d1)
            # Context ends at t=40.

            # Alignment context where all pulse instructions are
            # aligned to the right, ie., as late as possible.
            with pulse.align_right():
                # Shift the phase of a pulse channel.
                pulse.shift_phase(math.pi, d1)
                # Starts at t=40.
                pulse.delay(100, d0)
                # Ends at t=140.

                # Starts at t=130.
                pulse.play(gaussian_pulse, d1)
                # Ends at t=140.

            # Acquire data for a qubit and store in a memory slot.
            pulse.acquire(100, 0, pulse.MemorySlot(0))

            # We also support a variety of macros for common operations.

            # Measure all qubits.
            pulse.measure_all()

            # Delay on some qubits.
            # This requires knowledge of which channels belong to which qubits.
            pulse.delay_qubits(100, 0, 1)

            # Call a quantum circuit. The pulse builder lazily constructs a quantum
            # circuit which is then transpiled and scheduled before inserting into
            # a pulse schedule.
            # NOTE: Quantum register indices correspond to physical qubit indices.
            qc = QuantumCircuit(2, 2)
            qc.cx(0, 1)
            pulse.call(qc)
            # Calling a small set of standard gates and decomposing to pulses is
            # also supported with more natural syntax.
            pulse.u3(0, math.pi, 0, 0)
            pulse.cx(0, 1)


            # It is also be possible to call a preexisting schedule
            tmp_sched = pulse.Schedule()
            tmp_sched += pulse.Play(gaussian_pulse, d0)
            pulse.call(tmp_sched)

            # We also support:

            # frequency instructions
            pulse.set_frequency(5.0e9, d0)

            # phase instructions
            pulse.shift_phase(0.1, d0)

            # offset contexts
            with pulse.phase_offset(math.pi, d0):
                pulse.play(gaussian_pulse, d0)

Todo:

  • Contextvars are only supported in Python 3.7+, there is a backport package that should be installed.
  • Flesh out the documentation for the builder interface.
  • Update the tutorials to use the pulse builder interface. See here.

@lcapelluto lcapelluto added the on hold Can not fix yet label Jun 22, 2020
@lcapelluto
Copy link
Contributor

Let's not merge until one other person has reviewed builder.py

@taalexander
Copy link
Contributor Author

taalexander commented Jun 22, 2020

Thanks for the approval!

Let's not merge until one other person has reviewed builder.py

More eyes are important, but I'm also not sure we can continue to hold this up. There is a lot of follow on work we need to add and schedule. @ajavadia, could you please recommend how we proceed.

@lcapelluto lcapelluto removed the on hold Can not fix yet label Jul 6, 2020
@ajavadia
Copy link
Member

ajavadia commented Jul 7, 2020

@taalexander were you going to add more documentation/release note saying it is experimental feature? otherwise i'm good to add the automerge label.

@taalexander
Copy link
Contributor Author

@taalexander were you going to add more documentation/release note saying it is experimental feature? otherwise i'm good to add the automerge label.

I'll do this in a separate follow up PR. I'll submit that shortly after this gets merged.

@mergify mergify bot merged commit 5bdee8c into Qiskit:master Jul 8, 2020
faisaldebouni pushed a commit to faisaldebouni/qiskit-terra that referenced this pull request Aug 5, 2020
* Fix setting contexts.

* Make builder class private.

* Add group transform.

* Initial demo test is running (not necessarily doing the right thing.

* Typed context gate call parameters.

* Fix imports for builder.

* Fix bugs in tests.

* Minor changes.

* Add pad context. Rename active -> current.

* Add barrier test, expected fail.

* Added group context test.

* Fix bug in acquire instruction.

* Add instruction tests.

* Add builder utilities tests.

* Fix bug in scheduler when no gates present in circuit.

* Test transpiler and scheduler context settings / utilities.

* Made children, a public method.

* add default alignment context for builder.

* Get tests working for call_schedule and call_circuit. Rework right align transform.

* Rename test file.

* Test measure macro.

* Add delay_qubit macro test.

* Update context builder test docstring.

* Review suggestions

* Add gate tests. Running into a bug with the schedule implementation.

* Fix get_qubit_channels

* Fix bug in acquire round 2.

* Deprecation warning to use control(qubits: List) instead of control(channel: int)

* Fix mutable insert flattening schedule tree.

* Fix delay test using qubit index.

* Fix using deprecated cnotgate.

* typos

* Rename alignment contexts.

* update the control based on the new backend schema

* typos

* Unify alignment context naming.

* Unify naming of transforms and fix broken align_right.

* More logic fixes

* lint

* lint

* add older code

* More logic fixes

* lint

* Update docstrings and typehints

* Unused imports

* Release notes

* Review suggestions

* Bug fix for get_qubit_channels(0)

Updated tests too

* Review Suggestions

* lint

* Change error message of _get_channel_prefix_index

* Added raise error for backends without 'channel' information

* Update docstrings for raise errors

* Fix error messages and docstrings

* make self.channels private

* Remove collections.Counter

* Revert "Remove collections.Counter"

This reverts commit d602738.

* Add complex test.

* Rename _schedule_lazy_circuit_before to _compile_lazy_circuit_before

* Add delay_qubits instruction. Fix bug in schedule equality test.

* Add frequency and phase offset contexts.

* Renamed builder_context to builder.

* Add inline directive.

* linting.

* Fix linting errors.

* Add rescheduler linting.

* Add transforms documentation.

* Lint test builder.

* Add macro linting.

* Schedule linting.

* lint pulse builder.

* Remove cyclical imports with compiler import in pulse builder.

* Add channel builder helper functions. Rename current to active.

* Add relative barrier directive.

* Refactor visualization namespacing.

* Add barrier directive to builder.

* Add num_qubits.

* Add measure_all builder command.

* Add acquire on qubit.

* Add error if not all channels supplied to an Instruction is a channel.

* Remove notebooks directory from hackathon.

* linting

* Fix issue with deprecated Delay.

* Add backport packages for contextvars.

* Reorder schedule and backend arguments. Make backend no longer required.

* Small builder doc update.

* Add simpler calling syntax for the builder.

* Fix python versioninign.

* Add __all__ for builder.

* Add exceptions for no active builder or no backend set.

* Update automodule

Adds documentation of all non-private member function and properties

* Remove unwanted docstrings

Also fixes some typos

* Fix pylint error - BackendNotSet not added in docstring

* Fix weird bug

* Fix 'commands' not imported

* Fix typo

* Rename pulse.reschedule -> pulse.transforms

* Update surrounding code to support rename (releasenotes, add rescheduler back for import path deprecation, API documentation, update imports in tests)

* Remove unwanted newlines

* Reapply feedback from code review

* Add test cases for issues with timeslots.'

* Fix small bug in timeslot insertion finder.

* Fixed another error in the code path.

* Remove accidental comment.

* Fix another small timeslot bug.

(cherry picked from commit 28bbbdec13ebd137ca4e5fd1c61aff0c0304988e)

* Fix small issue.

* Moved circuit_scheduler back to scheduler.

* Properly deprecate scheduler utils.

* linting

* Fix missed pieces when moving back scheduler.

* Fix circular imports by using from instead of import

* linting.

* use Constant instead of ConstantPulse.

* Rename pulse.reschedule -> pulse.transforms

* Update surrounding code to support rename (releasenotes, add rescheduler back for import path deprecation, API documentation, update imports in tests)

* Remove unwanted newlines

* Reapply feedback from code review

* Fix docs unexpected indent

* Linting.

* Change deprecation warning to emit warning at proper stack location.

* Make changes to remove deprecation warnings.

* Remove leftover files from moving of scheduler.

* Revert ordering of channel and qubit arguments compared to parameters.

* Add pulse builder documentation.

* fix up builder tests.

* Linting.

* Docs update.

* Fix deprecation warning.

* Fix reno warnings

* Some builder.py docstring updates

* Documentation updates.

* Fix issue with wrapped function not being properly documented.

* Update builder docs to use jupyter-executer

* Builder interface documentation.

* Fix issue with pulse barrier padding.

* Fix builder barrier doc.

* Structure builder imports.

* Update qiskit/pulse/instructions/directives.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Update qiskit/pulse/instructions/acquire.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Update qiskit/pulse/instructions/directives.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Fix call circuit.

* Enable a samples_to_time and time_to_samples method.

* Add test to builder for calling circuit with cregs.

* Update qiskit/pulse/builder.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Update qiskit/pulse/builder.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Update qiskit/pulse/builder.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Revert acquire import changes.

* Ignore trivial barriers.

* Add note on future deprecation of calling gates within the pulse builder interface.

* Remove commented out execution.

* Update qiskit/pulse/transforms.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Remove mention of quantum circuit in builder documentation intro.

* Update qiskit/pulse/builder.py

Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>

* Fix jupyter execute import style.

* Fix unclear arguments in delay_qubits doc.

* Make pulse builder warning more prominent and revise message.

* Fixed import asthetic.

* Move BackendNotSet to exceptions.

* Fix more asthetic setting of default settings in builder.

* Remove left over assert in builder.

* Remove dead comment.

* Reorder _call_circuit.

* Fix small linting error

* Fix commented out example code.

* Remove comment headers.

* Move NoActiveBuilder exception to exceptions.

* Rename time to sample and vice versa to seconds to samples

* Update macros module docstring.

* Fix measure docstring spacing.

* Update test_builder copyright.

* Fix test docstrings.

* Add notes for expected test failures.

* Rename types sections to channels.

* Fix test spacing.

* Revert test modification.

* Fix test_transform docstring.

* Add better coverage for TestRemoveTrivialBarriers

* Readd transform tests.

* Change example usage to examples for uniformity.

* linting invalid name.

* Replace mutate flag with inplace to mirror the circuit model.

* Allow passing name to pulse.build.

* Fix bad builder example assert.

* Allow frequency and phase offset contexts to broacast across channels.

* Revert delay instruction error.

* Remove unnecessary assignments for inplace schedule operations.

* Reorder sequential transform reference ordering.

* Removed unnecessary removal of barriers in transform test.

* Verify that flattened works correctly by testing aligned on grouped schedule.

* Make align right test depending on nesting. Refactor implementation of align_right.

* Use append instead of append where it makes sense. Use inplace where I can.

* Remove the pulse group instruction for now.

* Added better inlining test.

* Implement shift frequency and frequency_offset.

* Clean up builder tests Qiskit#1

* Deprecate warns only once.

* Remove append_instruction from pulse namespace.

* Fix bad test name in test_instructions.

* Added beta flag.

* Update flatten transform documentation.

* Operator spaces.

* Fix unnecessary else in schedule.

* Fix operator spacing in test-transforms.

* time to seconds

* Fix misnamed test.

* Revert children to _children.

* Update pulse module docstring

* linting.

* Revert apidocs change in pulse.

* Remove call_schedule, call_circuit, call_gate from top-level import.

* Rename block to context_schedule.

* Better error message.

* Fix module level import.

* revert reno files.

* Added space in test builder.

* Added set_phase instruction.

* Revert visualization changes.

* Remove unused import

* Standardize imports for builder PR.

* Docs updates.

Co-authored-by: SooluThomas <soolu.elto@gmail.com>
Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
@mtreinish mtreinish added the Changelog: New Feature Include in the "Added" section of the changelog label Aug 6, 2020
@1ucian0 1ucian0 added the mod: pulse Related to the Pulse module label Jan 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: pulse Related to the Pulse module type: enhancement It's working, but needs polishing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants