quil.program
Retrieve the attributes of a frame by its identifier.
Return a list of all FrameIdentifier
s described by this FrameSet
.
Insert a new FrameIdentifier
, overwriting any existing one.
Merge another FrameSet
into this one, overwriting any existing keys.
Return a new FrameSet
which describes only the given FrameIdentifier
s.
Parses the given Quil string and returns a new Program
.
Raises a ProgramError
if the given string isn't valid Quil.
Attempt to convert the instruction to a valid Quil string.
Raises an exception if the instruction can't be converted to valid Quil.
Convert the instruction to a Quil string.
If any part of the instruction can't be converted to valid Quil, it will be printed in a human-readable debug format.
Creates a clone of this Program
with an empty body instructions list.
Return the control flow graph of the program.
Creates a new conjugate transpose of the Program
by reversing the order of gate instructions and applying the DAGGER modifier to each.
Raises a GateError
if any of the instructions in the program are not a `Gate
Expand any instructions in the program which have a matching calibration, leaving the others unchanged.
Recurses though each instruction while ensuring there is no cycle in the expansion graph (i.e. no calibration expands directly or indirectly into itself)
Simplify this program into a new Program
which contains only instructions and definitions which are executed; effectively, perform dead code removal.
Removes:
- All calibrations, following calibration expansion
- Frame definitions which are not used by any instruction such as
PULSE
orCAPTURE
- Waveform definitions which are not used by any instruction
When a valid program is simplified, it remains valid.
Returns a set consisting of every Qubit that is used in the program.
Add a list of instructions to the end of the program.
Return a new Program
containing only the instructions for which predicate
returns True
.
Resolve TargetPlaceholder
s and QubitPlaceholder
s within the program using default resolvers.
The default resolver will be used to generate a unique value for that placeholder within the scope of the program using an auto-incrementing value (for qubit) or suffix (for target) while ensuring that unique value is not already in use within the program.
Return a copy of the Program
wrapped in a loop that repeats iterations
times.
The loop is constructed by wrapping the body of the program in classical Quil instructions.
The given loop_count_reference
must refer to an INTEGER memory region. The value at the
reference given will be set to iterations
and decremented in the loop. The loop will
terminate when the reference reaches 0. For this reason your program should not itself
modify the value at the reference unless you intend to modify the remaining number of
iterations (i.e. to break the loop).
The given start_target
and end_target
will be used as the entry and exit points for
the loop, respectively. You should provide unique quil.instructions.Target
s that won't be
used elsewhere in the program.
If iterations
is 0, then a copy of the program is returned without any changes. Raises a
TypeError
if iterations
is negative.
Resolve TargetPlaceholder
s and QubitPlaceholder
s within the program.
The resolved values will remain unique to that placeholder within the scope of the program.
If you provide target_resolver
and/or qubit_resolver
, those will be used to resolve those values respectively.
If your resolver returns None
for a particular placeholder, it will not be replaced but will be left as a placeholder.
If you do not provide a resolver for a placeholder, a default resolver will be used which will generate a unique value for that placeholder within the scope of the program using an auto-incrementing value (for qubit) or suffix (for target) while ensuring that unique value is not already in use within the program.
Given an instruction, return the instructions to which it is expanded if there is a match.
Recursively calibrate instructions, returning an error if a calibration directly or indirectly expands into itself.
Returns the last-specified MeasureCalibrationDefinition
that matches the target qubit (if any), or otherwise the last-specified one that specified no qubit.
Return the final calibration which matches the gate per the QuilT specification.
A calibration matches a gate if:
- It has the same name
- It has the same modifiers
- It has the same qubit count (any mix of fixed & variable)
- It has the same parameter count (both specified and unspecified)
- All fixed qubits in the calibration definition match those in the gate
- All specified parameters in the calibration definition match those in the gate
Insert another Calibration
(DEFCAL
) to the set.
If a calibration with the same name already exists, it is overwritten and this function returns the previous calibration. Otherwise, None is returned.
Add another MeasureCalibrationDefinition
(DEFCAL MEASURE
) to the set.
If a calibration with the same name already exists, it is overwritten and this function returns the previous calibration. Otherwise, None is returned.
Append another [CalibrationSet
] onto this one.
Create a new instance of a BasicBlock
(or a subclass) using an existing instance.
Return the ScheduleSeconds
representing the timing of the instructions within the block.
- Expanding each instruction within the block using the program's calibration definitions
- Resolving the
ScheduleSeconds
of the expanded instructions - Mapping calibrated instructions back to the original instructions within this block, such that the block's instruction is represented as a timespan encompassing all of its expanded instructions
Parameters
- program: The program containing the calibrations to be used to schedule this block. Generally, this should be the program from which the block was extracted.
Important note: If the basic block contains gates, the program must contain corresponding DEFCAL
s for those gates.
Gates do not inherently have durations, but rather inherit them from the PULSE
, CAPTURE
, DELAY
,
and other instructions within their calibrations. Without a calibration, a gate's duration cannot be computed.
The following example demonstrates construction of such a schedule for a simple program without explicit control flow (and thus with only one basic block):
.. example-code::
.. code-block:: python
from quil.program import Program
program = Program.parse("CZ 0 1; CZ 0 2")
print(program.to_quil())
control_flow_graph = program.control_flow_graph()
assert control_flow_graph.has_dynamic_control_flow() == False
basic_blocks = control_flow_graph.basic_blocks()
assert len(basic_blocks) == 1
schedule = blocks[0].as_schedule_seconds(program)
print(f"Duration = {schedule.duration()}")
print(schedule.items())
Note: when an instruction is expanded, the "time" of that original instruction includes the times of all of the resulting instructions. This may cause gate times to be longer than a user might expect.
To understand why, consider a program like this:
.. example-code::
.. code-block:: text
# One-qubit frame
DEFFRAME 0 "a":
ATTRIBUTE: 1
# Two-qubit frame
DEFFRAME 0 1 "b":
ATTRIBUTE: 1
DEFCAL A 0:
PULSE 0 "a" flat(duration: 1.0)
DEFCAL B 0 1:
FENCE 1
PULSE 0 1 "b" flat(duration: 1.0)
A 0
B 0 1
B 0
will be scheduled from time 0 to time 2, because its inner FENCE
is scheduled for time 0.
This may be unexpected if the user expects to see only the timing of the inner PULSE
.
Returns the length of the longest path from an initial instruction (one with no prerequisite instructions) to a final instruction (one with no dependent instructions), where the length of a path is the number of gate instructions in the path.
Parameters
- gate_minimum_qubit_count: The minimum number of qubits in a gate for it to be counted in the depth.
Return a list of the instructions in the block, in order of definition.
This does not include the label or terminator instructions.
Representation of a control flow graph (CFG) for a Quil program.
The CFG is a directed graph where each node is a basic block and each edge is a control flow transition between two basic blocks.
Create a new instance of a ControlFlowGraph
(or a subclass) using an existing instance.
Return True
if the program has dynamic control flow, i.e. contains a conditional branch instruction.
False
does not imply that there is only one basic block in the program. Multiple basic blocks may have
non-conditional control flow among them, in which the execution order is deterministic and does not depend
on program state. This may be a sequence of basic blocks with fixed JUMP
s or without explicit terminators.
A single item within a fixed schedule, representing a single instruction within a basic block.
Representation of a time span in seconds.
The end time of the time span, in seconds.
This is the sum of the start time and duration.