Closed kalzoo closed 3 weeks ago
PR Preview Action v1.4.8
:---:
:rocket: Deployed preview to https://rigetti.github.io/quil-rs/pr-preview/pr-370/
on branch quil-py-docs
at 2024-10-12 00:42 UTC
As much as I can read Rust, this is making sense to me. On the first point about a lurking bug, I wonder if impl SourceMapRange for CalibrationExpansion
contains()
is incomplete as containment is only by the index being valid, not that it also came from the same calibration? On the third point about reverse-mapping help, if I could see the pattern for this implemented using only the Python bindings as a recipe I think I'd be fine, but if doing that means you might as well codify on the Rust side, happy for that also!
As much as I can read Rust, this is making sense to me. On the first point about a lurking bug, I wonder if
impl SourceMapRange for CalibrationExpansion
contains()
is incomplete as containment is only by the index being valid, not that it also came from the same calibration? On the third point about reverse-mapping help, if I could see the pattern for this implemented using only the Python bindings as a recipe I think I'd be fine, but if doing that means you might as well codify on the Rust side, happy for that also!
Hey, thanks @mhodson-rigetti . I've added python bindings and docs but no example (yet) - I'll have to think about how best to expose those direct mappings from source to target. Right now (following our chat a week ago) I made the structure recursive to model the recursive nature of calibration expansion, and that's the least intuitive part in practical use, because each level of expansion has its own index basis. There's an example describing that problem in the python docstrings now.
You were right about SourceMapRange
for exactly that reason - two ranges might not share the same basis and the SourceMapRange doesn't have enough information to make that clear. I just removed SourceMapRange
altogether in this iteration, I don't think this functionality needs to be so general-purpose just yet.
The lingering bug though was actually fixed in this commit and was something prompted by our chat a week ago - certain instructions being yoinked out of the instruction body and thus (necessarily) out the source map.
Just wanted to check on the status of this - it's important for pulse plotting to work.
I'm a little surprised by the extent of the changes in this PR. I was expecting something more along the lines of this:
from quil.program import Program
from typing import Tuple, List
def expand_with_source_mapping(program: Program) -> Tuple[Program, List[int]]:
"""
Expand any instructions in the program which have a matching calibration, leaving the others
unchanged.
:param program: A quil.Program.
:return: A quil.Program with the instructions expanded and a source map.
The source map is a list with the length of the expanded instructions, and indicates the index
of the logical instruction in the original program from which the expanded instruction originated.
"""
instructions = program.body_instructions
calibrations = program.calibrations
expanded_program = program.clone_without_body_instructions()
source_map = []
expanded_instructions = []
for logical_index, inst in enumerate(instructions):
expanded_instruction = calibrations.expand(inst, [])
source_map += [logical_index]*len(expanded_instruction)
expanded_instructions += expanded_instruction
expanded_program.add_instructions(expanded_instructions)
return expanded_program, source_map
expanded_program, source_map = expand_with_source_mapping(quil_program)
default_expanded_program = quil_program.expand_calibrations()
assert expanded_program == default_expanded_program
I'm a little surprised by the extent of the changes in this PR. I was expecting something more along the lines of this:
from quil.program import Program from typing import Tuple, List def expand_with_source_mapping(program: Program) -> Tuple[Program, List[int]]: """ Expand any instructions in the program which have a matching calibration, leaving the others unchanged. :param program: A quil.Program. :return: A quil.Program with the instructions expanded and a source map. The source map is a list with the length of the expanded instructions, and indicates the index of the logical instruction in the original program from which the expanded instruction originated. """ instructions = program.body_instructions calibrations = program.calibrations expanded_program = program.clone_without_body_instructions() source_map = [] expanded_instructions = [] for logical_index, inst in enumerate(instructions): expanded_instruction = calibrations.expand(inst, []) source_map += [logical_index]*len(expanded_instruction) expanded_instructions += expanded_instruction expanded_program.add_instructions(expanded_instructions) return expanded_program, source_map expanded_program, source_map = expand_with_source_mapping(quil_program) default_expanded_program = quil_program.expand_calibrations() assert expanded_program == default_expanded_program
@bramathon that snippet doesn't:
Some of the diff, also, improves how calibrations are handled and matched
Yup, that's true. I don't have any need for those things for my use case.
On Fri, Oct 11, 2024, 20:00 Kalan @.***> wrote:
I'm a little surprised by the extent of the changes in this PR. I was expecting something more along the lines of this:
from quil.program import Programfrom typing import Tuple, List def expand_with_source_mapping(program: Program) -> Tuple[Program, List[int]]: """ Expand any instructions in the program which have a matching calibration, leaving the others unchanged. :param program: A quil.Program. :return: A quil.Program with the instructions expanded and a source map. The source map is a list with the length of the expanded instructions, and indicates the index of the logical instruction in the original program from which the expanded instruction originated. """ instructions = program.body_instructions calibrations = program.calibrations expanded_program = program.clone_without_body_instructions()
source_map = [] expanded_instructions = [] for logical_index, inst in enumerate(instructions): expanded_instruction = calibrations.expand(inst, []) source_map += [logical_index]*len(expanded_instruction) expanded_instructions += expanded_instruction expanded_program.add_instructions(expanded_instructions) return expanded_program, source_map
expanded_program, source_map = expand_with_source_mapping(quil_program)default_expanded_program = quil_program.expand_calibrations()assert expanded_program == default_expanded_program
@bramathon https://github.com/bramathon that snippet doesn't:
- break out recursive calibrations
- capture which calibration was used to do the expansion
Some of the diff, also, improves how calibrations are handled and matched
— Reply to this email directly, view it on GitHub https://github.com/rigetti/quil-rs/pull/370#issuecomment-2407972352, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEWA7XSPPA5YGRQB4JXV4DZ3AN5PAVCNFSM6AAAAABHGSS7PSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMBXHE3TEMZVGI . You are receiving this because you were mentioned.Message ID: @.***>
Over to you now @bramathon
This PR allows the (Rust package) user to do the following:
Reviewer:
MeasureCalibrationDefinition
andCalibration
structs. This would make them somewhat more similar to DEFFRAME in that they would have identifiers that could be used to index them without respect to their instruction bodies. We could also take the chance to renameCalibration
toCalibrationDefinition
for consistency.@property
s are there, so this will only break users who construct and modify calibrations and measure calibrations. I could add additional setters to help migrate, but there's only one__new__
and it doesn't feel right to leave those behind.CalibrationSet#_expand
method and those nearby.CalibrationExpansion
when that is returned to the user; I first tried anexpansion: Option<&mut CalibrationExpansion>
argument, but that doesn't work well here because that doesn't have a sensible default.build_source_map
which skips most of the work involved in calibration expansion source mapping while still technically constructing one which is then discarded prior to return fromCalibrationSet.expand
.TODOs:
Closes #366