pyquil.quil module

Module for creating and defining Quil programs.

class pyquil.quil.Program(*instructions: AbstractInstruction | Instruction | Program | Program | Sequence[Any] | tuple[Any, ...] | str | Generator[Any, Any, Any])[source]

Bases: object

A list of pyQuil instructions that comprise a quantum program.

>>> from pyquil import Program
>>> from pyquil.gates import H, CNOT
>>> p = Program()
>>> p += H(0)
>>> p += CNOT(0, 1)

Initialize a Program.

calibrate(instruction: AbstractInstruction, previously_calibrated_instructions: set[AbstractInstruction] | None = None) list[AbstractInstruction][source]

Expand an instruction into its calibrated definition.

If a calibration definition matches the provided instruction, then the definition body is returned with appropriate substitutions made for parameters and qubit arguments. If no calibration definition matches, then the original instruction is returned. Calibrations are performed recursively, so that if a calibrated instruction produces an instruction that has a corresponding calibration, it will be expanded, and so on. If a cycle is encountered, a CalibrationError is raised.

Parameters:
  • instruction – An instruction.

  • previously_calibrated_instructions – A set of instructions that are the results of calibration expansions in the direct ancestry of instruction. Used to catch cyclic calibration expansions.

Returns:

A list of instructions, with the active calibrations expanded.

property calibrations: list[DefCalibration]

A list of Quil-T calibration definitions.

control_flow_graph() ControlFlowGraph[source]

Return the ControlFlowGraph of the program.

copy() Program[source]

Perform a deep copy of this program.

Returns:

a new Program

copy_everything_except_instructions() Program[source]

Copy all the members that live on a Program object.

Returns:

a new Program

dagger() Program[source]

Create the conjugate transpose of the Quil program. The program must contain only gate applications.

Returns:

The Quil program’s inverse

property declarations: dict[str, Declare]

A mapping from declared region names to their declarations.

declare(name: str, memory_type: str = 'BIT', memory_size: int = 1, shared_region: str | None = None, offsets: Sequence[tuple[int, str]] | None = None) MemoryReference[source]

DECLARE a quil variable.

This adds the declaration to the current program and returns a MemoryReference to the base (offset = 0) of the declared memory.

Note

This function returns a MemoryReference and cannot be chained like some of the other Program methods. Consider using inst(DECLARE(...)) if you would like to chain methods, but please be aware that you must create your own MemoryReferences later on.

Parameters:
  • name – Name of the declared variable

  • memory_type – Type of the declared memory: ‘BIT’, ‘REAL’, ‘OCTET’ or ‘INTEGER’

  • memory_size – Number of array elements in the declared memory.

  • shared_region – You can declare a variable that shares its underlying memory with another region. This allows aliasing. For example, you can interpret an array of measured bits as an integer.

  • offsets – If you are using shared_region, this allows you to share only a part of the parent region. The offset is given by an array type and the number of elements of that type. For example, DECLARE target-bit BIT SHARING real-region OFFSET 1 REAL 4 BIT will let you use target-bit to poke into the fourth bit of the second real from the leading edge of real-region.

Returns:

a MemoryReference to the start of the declared memory region, ie a memory reference to name[0].

defgate(name: str, matrix: list[list[Any]] | ndarray | matrix, parameters: list[Parameter] | None = None) Program[source]

Define a new static gate.

Note

The matrix elements along each axis are ordered by bitstring. For two qubits the order is 00, 01, 10, 11, where the the bits are ordered in reverse by the qubit index, i.e., for qubits 0 and 1 the bitstring 01 indicates that qubit 0 is in the state 1. See also the related docs in the WavefunctionSimulator Overview.

Parameters:
  • name – The name of the gate.

  • matrix – List of lists or Numpy 2d array.

  • parameters – list of parameters that are used in this gate

Returns:

The Program instance.

define_noisy_gate(name: str, qubit_indices: Sequence[int], kraus_ops: Sequence[Any]) Program[source]

Overload a static ideal gate with a noisy one defined in terms of a Kraus map.

Note

The matrix elements along each axis are ordered by bitstring. For two qubits the order is 00, 01, 10, 11, where the the bits are ordered in reverse by the qubit index, i.e., for qubits 0 and 1 the bitstring 01 indicates that qubit 0 is in the state 1. See also the related docs in the WavefunctionSimulator Overview.

Parameters:
  • name – The name of the gate.

  • qubit_indices – The qubits it acts on.

  • kraus_ops – The Kraus operators.

Returns:

The Program instance

define_noisy_readout(qubit: int, p00: float, p11: float) Program[source]

For this program define a classical bit flip readout error channel parametrized by p00 and p11.

This models the effect of thermal noise that corrupts the readout signal after it has interrogated the qubit.

Parameters:
  • qubit – The qubit with noisy readout.

  • p00 – The probability of obtaining the measurement result 0 given that the qubit is in state 0.

  • p11 – The probability of obtaining the measurement result 1 given that the qubit is in state 1.

Returns:

The Program with an appended READOUT-POVM Pragma.

property defined_gates: list[DefGate]

A list of defined gates on the program.

filter_instructions(predicate: Callable[[AbstractInstruction], bool]) Program[source]

Return a new Program containing only the instructions for which predicate returns True.

Parameters:

predicate – A function that takes an instruction and returns True if the instruction should not be removed from the program, False otherwise.

Returns:

A new Program object with the filtered instructions.

property frames: dict[Frame, DefFrame]

A mapping from Quil-T frames to their definitions.

gate(name: str, params: Sequence[Expression | MemoryReference | int | float | complex | number], qubits: Sequence[Qubit | QubitPlaceholder]) Program[source]

Add a gate to the program.

Note

The matrix elements along each axis are ordered by bitstring. For two qubits the order is 00, 01, 10, 11, where the the bits are ordered in reverse by the qubit index, i.e., for qubits 0 and 1 the bitstring 01 indicates that qubit 0 is in the state 1. See also the related docs in the WavefunctionSimulator Overview.

Parameters:
  • name – The name of the gate.

  • params – Parameters to send to the gate.

  • qubits – Qubits that the gate operates on.

Returns:

The Program instance

get_all_instructions() list[AbstractInstruction][source]

Get _all_ instructions that makeup the program.

get_calibration(instr: AbstractInstruction) DefCalibration | DefMeasureCalibration | None[source]

Get the calibration corresponding to the provided instruction.

Parameters:

instr – An instruction.

Returns:

A matching Quil-T calibration definition, if one exists.

get_qubit_indices() set[int][source]

Return the index of each qubit used in the program.

Will raise an exception if any of the qubits are placeholders.

get_qubits(indices: bool = True) set[Qubit | QubitPlaceholder | FormalArgument | int] | set[int][source]

Return all of the qubit indices used in this program, including gate applications and allocated qubits.

For example:

>>> from pyquil.gates import H
>>> p = Program()
>>> p.inst(("H", 1))
Program { ... }
>>> p.get_qubits()
{1}
>>> q = QubitPlaceholder()
>>> p.inst(H(q))
Program { ... }
>>> len(p.get_qubits(indices=False))
2
Parameters:

indices – Return qubit indices as integers instead of the wrapping Qubit object

Returns:

A set of all the qubit indices used in this program

Deprecated since version 4.0: The indices flag will be removed. Use get_qubit_indices() instead.

if_then(classical_reg: MemoryReference | MemoryReference | tuple[str, int] | list[Any] | str, if_program: Program, else_program: Program | None = None) Program[source]

If the classical register at index classical reg is 1, run if_program, else run else_program.

Equivalent to the following construction:

IF [c]:
   instrA...
ELSE:
   instrB...
=>
  JUMP-WHEN @THEN [c]
  instrB...
  JUMP @END
  LABEL @THEN
  instrA...
  LABEL @END
Parameters:
  • classical_reg – The classical register to check as the condition

  • if_program – A Quil program to execute if classical_reg is 1

  • else_program – A Quil program to execute if classical_reg is 0. This argument is optional and defaults to an empty Program.

Returns:

The Quil Program with the branching instructions added.

inst(*instructions: AbstractInstruction | Instruction | Program | Program | Sequence[Any] | tuple[Any, ...] | str | Generator[Any, Any, Any]) Program[source]

Mutates the Program object by appending new instructions.

This function accepts a number of different valid forms, e.g.

>>> from pyquil import Program
>>> from pyquil.gates import H
>>> p = Program()
>>> p.inst(H(0))  # A single instruction
Program { ... }
>>> p.inst(H(0), H(1))  # Multiple instructions
Program { ... }
>>> p.inst([H(0), H(1)])  # A list of instructions
Program { ... }
>>> p.inst(H(i) for i in range(4))  # A generator of instructions
Program { ... }
>>> p.inst("H 0")  # A string representing an instruction
Program { ... }
>>> q = Program()
>>> p.inst(q)  # Another program
Program { ... }
It can also be chained:
>>> p = Program()
>>> p.inst(H(0)).inst(H(1))
Program { ... }
Parameters:

instructions – A list of Instruction objects, e.g. Gates

Returns:

self for method chaining

property instructions: list[AbstractInstruction]

Fill in any placeholders and return a list of quil AbstractInstructions.

is_protoquil(quilt: bool = False) bool[source]

Return True, this method is deprecated.

Deprecated since version 4.0: This function always returns True and will be removed.

is_supported_on_qpu() bool[source]

Return True, this method is deprecated.

Deprecated since version 4.0: This function always returns True and will be removed.

match_calibrations(instr: AbstractInstruction) CalibrationMatch | None[source]

Attempt to match a calibration to the provided instruction.

Note: preference is given to later calibrations, i.e. in a program with

DEFCAL X 0:

<a>

DEFCAL X 0:

<b>

the second calibration, with body <b>, would be the calibration matching X 0.

Parameters:

instr – An instruction.

Returns:

a CalibrationMatch object, if one can be found.

measure(qubit: Qubit | QubitPlaceholder | FormalArgument | int, classical_reg: MemoryReference | MemoryReference | tuple[str, int] | list[Any] | str | None) Program[source]

Measures a qubit at qubit_index and puts the result in classical_reg.

Parameters:
  • qubit – The qubit to measure.

  • classical_reg – The classical register to measure into, or None.

Returns:

The Quil Program with the appropriate measure instruction appended, e.g. MEASURE 0 [1]

measure_all(*qubit_reg_pairs: tuple[Qubit | QubitPlaceholder | FormalArgument | int, MemoryReference | MemoryReference | tuple[str, int] | list[Any] | str | None]) Program[source]

Measures many qubits into their specified classical bits, in the order they were entered.

If no qubit/register pairs are provided, measure all qubits present in the program into classical addresses of the same index.

Parameters:

qubit_reg_pairs – Tuples of qubit indices paired with classical bits.

Returns:

The Quil Program with the appropriate measure instructions appended, e.g.

MEASURE 0 [1]
MEASURE 1 [2]
MEASURE 2 [3]
property measure_calibrations: list[DefMeasureCalibration]

A list of measure calibrations.

no_noise() Program[source]

Prevent a noisy gate definition from being applied to the immediately following Gate instruction.

Returns:

Program

out(*, calibrations: bool | None = True) str[source]

Serialize the Quil program to a string suitable for submitting to the QVM or QPU.

prepend_instructions(instructions: Iterable[AbstractInstruction]) Program[source]

Prepend instructions to the beginning of the program.

remove_quil_t_instructions() Program[source]

Return a copy of the program with all Quil-T instructions removed.

reset(qubit_index: int | None = None) Program[source]

Reset all qubits or just a specific qubit at qubit_index.

Parameters:

qubit_index – The address of the qubit to reset. If None, reset all qubits.

Returns:

The Quil Program with the appropriate reset instruction appended, e.g. RESET 0

resolve_label_placeholders() None[source]

Resolve all label placeholders in the program.

resolve_placeholders() None[source]

Resolve all label and qubit placeholders in the program.

A default resolver will generate a unique value for each placeholder within the scope of the program.

resolve_placeholders_with_custom_resolvers(*, label_resolver: Callable[[LabelPlaceholder], str | None] | None = None, qubit_resolver: Callable[[QubitPlaceholder], int | None] | None = None) None[source]

Resolve LabelPlaceholder\s and QubitPlaceholder\s within the program using a function.

If you provide label_resolver and/or qubit_resolver, they 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.

resolve_qubit_placeholders() None[source]

Resolve all qubit placeholders in the program.

resolve_qubit_placeholders_with_mapping(qubit_mapping: dict[QubitPlaceholder, int]) None[source]

Resolve all qubit placeholders using a mapping of QubitPlaceholder\s to the index they resolve to.

property waveforms: dict[str, DefWaveform]

A mapping from waveform names to their corresponding definitions.

while_do(classical_reg: MemoryReference | MemoryReference | tuple[str, int] | list[Any] | str, q_program: Program) Program[source]

While a classical register at index classical_reg is 1, loop q_program.

Equivalent to the following construction:

WHILE [c]:
   instr...
=>
  LABEL @START
  JUMP-UNLESS @END [c]
  instr...
  JUMP @START
  LABEL @END
Parameters:
  • classical_reg (MemoryReferenceDesignator) – The classical register to check

  • q_program (Program) – The Quil program to loop.

Returns:

The Quil Program with the loop instructions added.

with_loop(num_iterations: int, iteration_count_reference: MemoryReference, start_label: Label | LabelPlaceholder, end_label: Label | LabelPlaceholder) Program[source]

Return a copy of the Program wrapped in a Quil loop that will execute num_iterations times.

This loop is implemented with Quil and should not be confused with the num_shots property set by wrap_in_numshots_loop(). The latter is metadata on the program that can tell an executor how many times to run the program. In comparison, this method adds Quil instructions to your program to specify a loop in the Quil program itself.

The loop is constructed by wrapping the body of the program in classical Quil instructions. The given iteration_count_reference must refer to an INTEGER memory region. The value at the reference given will be set to num_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_label and end_label will be used as the entry and exit points for the loop, respectively. You should provide unique JumpTarget\s that won’t be used elsewhere in the program.

If num_iterations is 1, then a copy of the program is returned without any changes. Raises a TypeError if num_iterations is negative.

Parameters:
  • num_iterations – The number of times to execute the loop.

  • loop_count_reference – The memory reference to use as the loop counter.

  • start_label – The JumpTarget to use at the start of the loop.

  • end_label – The JumpTarget to use to at the end of the loop.

wrap_in_numshots_loop(shots: int) Program[source]

Wrap a Quil program in a loop that re-runs the same program many times.

Note: this function is a prototype of what will exist in the future when users will be responsible for writing this loop instead of having it happen automatically.

Parameters:

shots – Number of iterations to loop through.

pyquil.quil.address_qubits(program: Program, qubit_mapping: dict[QubitPlaceholder, int] | None = None) Program[source]

Take a program which contains placeholders and assigns the all defined values.

Either all qubits must be defined or all undefined. If qubits are undefined, you may provide a qubit mapping to specify how placeholders get mapped to actual qubits. If a mapping is not provided, integers 0 through N are used. This function will also instantiate any label placeholders. :param program: The program. :param qubit_mapping: A dictionary-like object that maps from QubitPlaceholder to Qubit or int (but not both). :return: A new Program with all qubit and label placeholders assigned to real qubits and labels.

pyquil.quil.get_classical_addresses_from_program(program: Program) dict[str, list[int]][source]

Return a sorted list of classical addresses found in the MEASURE instructions in the program.

Parameters:

program – The program from which to get the classical addresses.

Returns:

A mapping from memory region names to lists of offsets appearing in the program.

pyquil.quil.instantiate_labels(instructions: Iterable[AbstractInstruction]) list[AbstractInstruction][source]

Take an iterable of instructions which may contain label placeholders and assigns them all defined values.

Returns:

list of instructions with all label placeholders assigned to real labels.

pyquil.quil.merge_programs(prog_list: Sequence[Program]) Program[source]

Merge a list of pyQuil programs into a single one by appending them in sequence.

Deprecated since version 4.0: This function will be removed. Use Program addition instead.

pyquil.quil.merge_with_pauli_noise(prog_list: Iterable[Program], probabilities: Sequence[float], qubits: Sequence[int]) Program[source]

Insert pauli noise channels between each item in the list of programs.

This noise channel is implemented as a single noisy identity gate acting on the provided qubits. This method does not rely on merge_programs and so avoids the inclusion of redundant Kraus Pragmas that would occur if merge_programs was called directly on programs with distinct noisy gate definitions.

Parameters:
  • prog_list – an iterable such as a program or a list of programs. If a program is provided, a single noise gate will be applied after each gate in the program. If a list of programs is provided, the noise gate will be applied after each program.

  • probabilities – The 4^num_qubits list of probabilities specifying the desired pauli channel. There should be either 4 or 16 probabilities specified in the order I, X, Y, Z or II, IX, IY, IZ, XI, XX, XY, etc respectively.

  • qubits – a list of the qubits that the noisy gate should act on.

Returns:

A single program with noisy gates inserted between each element of the program list.

pyquil.quil.percolate_declares(program: Program) Program[source]

As of pyQuil v4.0, the Program class does this automatically.

This function is deprecated and just immediately returns the passed in program.

Parameters:

program – A program.

Deprecated since version 4.0: The Program class now sorts instructions automatically. This function will be removed.

pyquil.quil.validate_protoquil(program: Program, quilt: bool = False) None[source]

Deprecated since version 4.0: This is now a no-op and will be removed in future versions of pyQuil.

pyquil.quil.validate_supported_quil(program: Program) None[source]

Deprecated since version 4.0: This is now a no-op and will be removed in future versions of pyQuil.