pub struct Program {
pub calibrations: Calibrations,
pub extern_pragma_map: ExternPragmaMap,
pub frames: FrameSet,
pub memory_regions: IndexMap<String, MemoryRegion>,
pub waveforms: IndexMap<String, Waveform>,
pub gate_definitions: IndexMap<String, GateDefinition>,
/* private fields */
}Expand description
A Quil Program instance describes a quantum program with metadata used in execution.
This contains not only instructions which are executed in turn on the quantum processor, but also the “headers” used to describe and manipulate those instructions, such as calibrations and frame definitions.
Fields§
§calibrations: Calibrations§extern_pragma_map: ExternPragmaMap§frames: FrameSet§memory_regions: IndexMap<String, MemoryRegion>§waveforms: IndexMap<String, Waveform>§gate_definitions: IndexMap<String, GateDefinition>Implementations§
Source§impl Program
impl Program
pub fn new() -> Self
Sourcepub fn clone_without_body_instructions(&self) -> Self
pub fn clone_without_body_instructions(&self) -> Self
Like Clone, but does not clone the body instructions.
Sourcepub fn add_instruction(&mut self, instruction: Instruction)
pub fn add_instruction(&mut self, instruction: Instruction)
Add an instruction to the end of the program.
Note, parsing extern signatures is deferred here to maintain infallibility
of Program::add_instruction. This means that invalid PRAGMA EXTERN
instructions are still added to the Program::extern_pragma_map;
duplicate PRAGMA EXTERN names are overwritten.
Sourcepub fn dagger(&self) -> Result<Self, ProgramError>
pub fn dagger(&self) -> Result<Self, ProgramError>
Creates a new conjugate transpose of the Program by reversing the order of gate
instructions and applying the DAGGER modifier to each.
§Errors
Errors if any of the instructions in the program are not Instruction::Gate
Sourcepub fn expand_calibrations(&self) -> Result<Self, ProgramError>
pub fn expand_calibrations(&self) -> Result<Self, ProgramError>
Expand any instructions in the program which have a matching calibration, leaving the others unchanged. Return the expanded copy of the program.
Returns an error if any instruction expands into itself.
See Program::expand_calibrations_with_source_map for a version that returns a source mapping.
Sourcepub fn wrap_in_loop(
&self,
loop_count_reference: MemoryReference,
start_target: Target,
end_target: Target,
iterations: u32,
) -> Self
pub fn wrap_in_loop( &self, loop_count_reference: MemoryReference, start_target: Target, end_target: Target, iterations: u32, ) -> Self
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 Targets that won’t be used elsewhere in
the program.
If iterations is 0, then a copy of the program is returned without any changes.
Sourcepub fn resolve_placeholders(&mut self)
pub fn resolve_placeholders(&mut self)
Resolve [LabelPlaceholder]s and QubitPlaceholders within the program using default resolvers.
See resolve_placeholders_with_custom_resolvers,
default_target_resolver,
and default_qubit_resolver for more information.
Sourcepub fn to_instructions(&self) -> Vec<Instruction>
pub fn to_instructions(&self) -> Vec<Instruction>
Return a copy of all of the instructions which constitute this Program.
Source§impl Program
impl Program
Sourcepub fn body_instructions(&self) -> impl Iterator<Item = &Instruction>
pub fn body_instructions(&self) -> impl Iterator<Item = &Instruction>
Returns an iterator over immutable references to the instructions that make up the body of the program.
pub fn into_body_instructions(self) -> impl Iterator<Item = Instruction>
pub fn add_instructions<I>(&mut self, instructions: I)where
I: IntoIterator<Item = Instruction>,
Sourcepub fn filter_instructions(
&self,
predicate: impl FnMut(&Instruction) -> bool,
) -> Program
pub fn filter_instructions( &self, predicate: impl FnMut(&Instruction) -> bool, ) -> Program
Return a new Program containing only the instructions for which predicate returns
true.
Sourcepub fn expand_calibrations_with_source_map(
&self,
) -> Result<(Program, SourceMap<InstructionIndex, ExpansionResult<CalibrationExpansion>>), ProgramError>
pub fn expand_calibrations_with_source_map( &self, ) -> Result<(Program, SourceMap<InstructionIndex, ExpansionResult<CalibrationExpansion>>), ProgramError>
Expand any instructions in the program which have a matching calibration, leaving the others unchanged. Return the expanded copy of the program and a source mapping of the expansions made.
Sourcepub fn expand_defgate_sequences<F>(
self,
filter: F,
) -> Result<Self, ProgramError>
pub fn expand_defgate_sequences<F>( self, filter: F, ) -> Result<Self, ProgramError>
Expand any DefGateSequence instructions in the program, leaving the others unchanged.
Return the expanded copy of the program. Any sequence gate definitions that are included
by the filter are removed from the program’s gate definitions, unless they are referenced
by unexpanded sequence gate definitions.
The filter that determines which sequence gate definitions to keep in the
program. Gates are kept if the filter returns true for their name.
§Example
Below, we show the results of gate sequence expansion on a program that has two gate
sequence definitions. The first, seq1, has a matching calibration and we do not
want to expand it. The second, seq2, does not have a matching calibration and
we do want to expand it.
use quil_rs::program::Program;
use quil_rs::quil::Quil;
use std::collections::HashSet;
let quil = r#"
DEFCAL seq1 0 1:
FENCE 0 1
NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 6.000000000000001e-08, fwhm: 1.5000000000000002e-08, t0: 3.0000000000000004e-08, anh: -190000000.0, alpha: -1.6453719598238201, scale: 0.168265925924524, phase: 0.0, detuning: 0)
NONBLOCKING PULSE 1 "rf" drag_gaussian(duration: 6.000000000000001e-08, fwhm: 1.5000000000000002e-08, t0: 3.0000000000000004e-08, anh: -190000000.0, alpha: -1.6453719598238201, scale: 0.168265925924524, phase: 0.0, detuning: 0)
FENCE 0 1
DEFGATE seq1() a b AS SEQUENCE:
RX(pi/2) a
RX(pi/2) b
DEFGATE seq2(%theta, %psi, %phi) a AS SEQUENCE:
RZ(%theta) a
RX(pi/2) a
RZ(%psi) a
RX(pi/2) a
RZ(%phi) a
seq1 0 1
seq2(1.5707963267948966, 3.141592653589793, 0) 0
seq2(3.141592653589793, 0, 1.5707963267948966) 1
"#;
let program: Program = quil.parse().unwrap();
let calibrated_gate_names = program.calibrations.calibrations.iter().fold(HashSet::new(), |mut acc, calibration| {
acc.insert(calibration.identifier.name.clone());
acc
});
let expanded_program = program.expand_defgate_sequences(|name| !calibrated_gate_names.contains(name)).unwrap();
let expected_quil = r#"
DEFCAL seq1 0 1:
FENCE 0 1
NONBLOCKING PULSE 0 "rf" drag_gaussian(duration: 6.000000000000001e-08, fwhm: 1.5000000000000002e-08, t0: 3.0000000000000004e-08, anh: -190000000.0, alpha: -1.6453719598238201, scale: 0.168265925924524, phase: 0.0, detuning: 0)
NONBLOCKING PULSE 1 "rf" drag_gaussian(duration: 6.000000000000001e-08, fwhm: 1.5000000000000002e-08, t0: 3.0000000000000004e-08, anh: -190000000.0, alpha: -1.6453719598238201, scale: 0.168265925924524, phase: 0.0, detuning: 0)
FENCE 0 1
DEFGATE seq1 a b AS SEQUENCE:
RX(pi/2) a
RX(pi/2) b
seq1 0 1
RZ(1.5707963267948966) 0
RX(pi/2) 0
RZ(3.141592653589793) 0
RX(pi/2) 0
RZ(0) 0
RZ(3.141592653589793) 1
RX(pi/2) 1
RZ(0) 1
RX(pi/2) 1
RZ(1.5707963267948966) 1
"#;
let expected_program: Program = expected_quil.parse().unwrap();
assert_eq!(expanded_program, expected_program);Sourcepub fn expand_defgate_sequences_with_source_map<F>(
&self,
filter: F,
) -> Result<(Self, SourceMap<InstructionIndex, ExpansionResult<DefGateSequenceExpansion<'_>>>), ProgramError>
pub fn expand_defgate_sequences_with_source_map<F>( &self, filter: F, ) -> Result<(Self, SourceMap<InstructionIndex, ExpansionResult<DefGateSequenceExpansion<'_>>>), ProgramError>
Expand any sequence gate definitions in the program, leaving the others unchanged. Return the expanded copy of the program and a source mapping of the expansions made. Any sequence gate definitions that are included by the filter are removed from the program’s gate definitions, unless they are referenced by unexpanded sequence gate definitions.
§Arguments
filter- A filter that determines which sequence gate definitions to keep in the program. Gates are kept if the filter returnstruefor their name.
See Program::expand_defgate_sequences for an example.
Sourcepub fn from_instructions(instructions: Vec<Instruction>) -> Self
pub fn from_instructions(instructions: Vec<Instruction>) -> Self
Build a program from a list of instructions
Sourcepub fn get_used_qubits(&self) -> &HashSet<Qubit>
pub fn get_used_qubits(&self) -> &HashSet<Qubit>
Returns a HashSet consisting of every Qubit that is used in the program.
Sourcepub fn into_instructions(self) -> Vec<Instruction>
pub fn into_instructions(self) -> Vec<Instruction>
Consume the Program to return all of the instructions which constitute it.
Sourcepub fn simplify<H: InstructionHandler>(
&self,
handler: &H,
) -> Result<Self, ProgramError>
pub fn simplify<H: InstructionHandler>( &self, handler: &H, ) -> Result<Self, ProgramError>
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
PULSEorCAPTURE - Waveform definitions which are not used by any instruction
PRAGMA EXTERNinstructions which are not used by anyCALLinstruction (seeProgram::extern_pragma_map).
When a valid program is simplified, it remains valid.
Sourcepub fn resolve_placeholders_with_custom_resolvers(
&mut self,
target_resolver: Box<dyn Fn(&TargetPlaceholder) -> Option<String>>,
qubit_resolver: Box<dyn Fn(&QubitPlaceholder) -> Option<u64>>,
)
pub fn resolve_placeholders_with_custom_resolvers( &mut self, target_resolver: Box<dyn Fn(&TargetPlaceholder) -> Option<String>>, qubit_resolver: Box<dyn Fn(&QubitPlaceholder) -> Option<u64>>, )
Resolve TargetPlaceholders and QubitPlaceholders within the program such that the resolved values
will remain unique to that placeholder within the scope of the program.
The provided target_resolver and qubit_resolver, will be used to resolve those values respectively.
If your placeholder returns None for a particular placeholder, it will not be replaced but will be left as a placeholder.
If you wish to provide a resolver for either labels or qubits, but want to rely on the
default behavior for the other, considering using either
default_qubit_resolver or default_target_resolver.
Sourcepub fn default_target_resolver(
&self,
) -> Box<dyn Fn(&TargetPlaceholder) -> Option<String>>
pub fn default_target_resolver( &self, ) -> Box<dyn Fn(&TargetPlaceholder) -> Option<String>>
The default target resolver will resolve each TargetPlaceholder in the program to a unique target
by applying an auto-incrementing suffix to the base target.
Sourcepub fn default_qubit_resolver(
&self,
) -> Box<dyn Fn(&QubitPlaceholder) -> Option<u64>>
pub fn default_qubit_resolver( &self, ) -> Box<dyn Fn(&QubitPlaceholder) -> Option<u64>>
The default qubit resolver will resolve each QubitPlaceholder in the program to
a unique fixed qubit index by incrementing to the next available index.
pub fn is_empty(&self) -> bool
pub fn len(&self) -> usize
Sourcepub fn to_unitary(&self, n_qubits: u64) -> Result<Matrix, ProgramError>
pub fn to_unitary(&self, n_qubits: u64) -> Result<Matrix, ProgramError>
Return the unitary of a program.
§Errors
Returns an error if the program contains instructions other than Gates.
Sourcepub fn get_instruction(&self, index: usize) -> Option<&Instruction>
pub fn get_instruction(&self, index: usize) -> Option<&Instruction>
Get a reference to the Instruction at the given index, if present.
Sourcepub fn try_extern_signature_map_from_pragma_map(
&self,
) -> Result<ExternSignatureMap, (Pragma, ExternError)>
pub fn try_extern_signature_map_from_pragma_map( &self, ) -> Result<ExternSignatureMap, (Pragma, ExternError)>
Convert the Program::extern_pragma_map into an ExternSignatureMap.
This will parse all PRAGMA EXTERN instructions in the program. If the
conversion of any Pragma fails, the ExternError is returned along
with the offending Pragma.
Trait Implementations§
Source§impl AddAssign for Program
impl AddAssign for Program
Source§fn add_assign(&mut self, rhs: Program)
fn add_assign(&mut self, rhs: Program)
+= operation. Read moreSource§impl<'p> From<&'p Program> for ControlFlowGraph<'p>
impl<'p> From<&'p Program> for ControlFlowGraph<'p>
Source§impl From<Vec<Instruction>> for Program
impl From<Vec<Instruction>> for Program
Source§fn from(instructions: Vec<Instruction>) -> Self
fn from(instructions: Vec<Instruction>) -> Self
Source§impl Quil for Program
impl Quil for Program
Source§fn write(
&self,
writer: &mut impl Write,
fall_back_to_debug: bool,
) -> Result<(), ToQuilError>
fn write( &self, writer: &mut impl Write, fall_back_to_debug: bool, ) -> Result<(), ToQuilError>
fall_back_to_debug
is true, then it must not return an error.Source§fn to_quil(&self) -> Result<String, ToQuilError>
fn to_quil(&self) -> Result<String, ToQuilError>
Source§fn to_quil_or_debug(&self) -> String
fn to_quil_or_debug(&self) -> String
Debug representation of that
component.Source§impl<'a> TryFrom<&'a Program> for BasicBlock<'a>
impl<'a> TryFrom<&'a Program> for BasicBlock<'a>
impl StructuralPartialEq for Program
Auto Trait Implementations§
impl Freeze for Program
impl RefUnwindSafe for Program
impl Send for Program
impl Sync for Program
impl Unpin for Program
impl UnwindSafe for Program
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.