Conversation
This pull request sets up the integration of QRE into the code base. In the first PR it defines classes and functions to create ISAs and ISA requirements.
This implements ISA transforms that can provide new ISAs from existing ones. It also builds data structures to define ISA queries that can combine transformations and their parameters to define the ISA exploration space.
Co-authored-by: Mathias Soeken <mathias.soeken@outlook.com>
These are data structures for traces, transform on traces, and Pareto frontiers to store estimation results. The `Trace` struct also implements an estimate function to estimate a trace with respect to an ISA. The two current trace transformations are PSSPC and LatticeSurgery. The trace API is considered final for now, whereas the implementation might still change. Instruction IDs are now provided by the Rust crate, the updates for the corresponding IDs in the Python package happen in an upcoming PR to keep this PR in a reasonable size.
#2912) Updated the Hypergraph class to support edge partitioning (coloring) * Added a function to perform (multiple trials) of greedy edge coloring * Added two simple 1d lattices: a open string (chain) and a ring Added/updated tests. --------- Co-authored-by: Mathias Soeken <mathias.soeken@outlook.com>
This is the skeleton implementations for Trotter-Suzuki expansions
* TrotterStep class wraps the basic functionality of a Trotter step
* StrangStep class subclasses TrotterStep for the (second-order)
symmetric Trotter step
* TrotterExpansion wraps the basic functionality of a full Trotter
expansion
* Test file included.
This PR is disjoint from #2912.
---------
Co-authored-by: Mathias Soeken <mathias.soeken@outlook.com>
This is the base class for a magnet model. * Draws on the geometry from the Hypergraph class (base class for geometries) * Only implements simple modification of the Hamiltonian * Test file included This PR is disjoint from #2912 and #2913 --------- Co-authored-by: Mathias Soeken <mathias.soeken@outlook.com>
Added more basic hypergraphs to the geometies library. * Patch2D and Torus2D: two dimensional analogues of chains and rings * Compete graphs: the base geometry for the Sherrington–Kirkpatrick model * Complete bipartite graphs: useful to create models with hidden frustration The complete graph does not have edge partitioning implemented (this is a bit tricky) * All others have edge partitioning * In the case of complete bipartite graphs it still needs to be tested, and comments added Basic tests added
This introduces ISA queries and trace queries in the Python API. With that one can implement a preliminary implementation for the central `estimate` function which can enumerate traces and ISA using these queries and perform estimation. It also moves some of the preliminary models from the test code to proper places in the API (`qsharp.qre.models`) with `AQREGateBased` as first architecture and `SurfaceCode` as first QEC model. Further it defines the application base class with a `QSharpApplication` as first implementation of it.
Changed how edge coloring is implemented: - Old: self.part was a list of lists indicating the partitions of the edges. - New: self.color is a dictionary keyed on the vertices of the edge with values indicating the "color" or which part the edge belongs. - Property ncolors gives the number of parts (colors) in the partition Convention: self loops are all called "color" -1. Remaining colors are 0, 1, .... - Automatic indexing (creating lists of parts) then places the self loops at the end (index -1). Updated all the examples of graphs to using this coloring implementation - Chain1D, Ring1D, Patch2D, Torus2D, and CompleteBipartiteGraph have only minor changes. - CompleteGraph has a new implementation of edge coloring. All test files updated.
… recursion (#2926) Changed some basic functionality: - The TrotterStep class is now just a wrapper class with some information functions and an iterator - Factory functions instantiate TrotterStep classes at desired orders (trotter_decomposition, strang_splitting) Added recursion - Both the Suzuki fractal recursion and Yoshide triple recursion are implemented (suzuki_recursion, yoshide_recursion) - fourth_order_trotter_suzuki is a convenience function for strang_splitting composed with suzuki_recursion Tests added. This PR is independent from #2925. --------- Co-authored-by: Mathias Soeken <mathias.soeken@outlook.com>
This PR provides some support for upcoming models by providing new features to ISAs and the Rust bindings in general - ISA instructions can have properties (e.g., the `LATTICE_SURGERY` instruction can have a distance property if it was generated by a surface code) - ISA requirement constraints can check if some properties are set, e.g., one can require that the `LATTICE_SURGERY` instruction also provides a `distance` property. - Variable arity instructions can provide space, time, and error_rate functions as generic Python functions. This can be slower than the built-in functions `const`, `linear`, and `block_linear`, but useful for cases that do not have an easy structure. The new function is called `generic` (`generic_function` in the API) - We expose a `binom_ppf` functions that works like `scipy.binom.ppf` and uses the `probability` crate that is already a dependency. This is not only faster but also does not require an additional dependency. It will be used to model round-based distillation factories. I missed to address some comments in the last PR. This is now done here.
The main change of this PR is the introduction of a provenance graph that keeps track of how instructions in ISAs are build from other instructions from other ISAs down to the architecture's ISA. We can then build an `InstructionSource` (also a graph) that describes the dependencies with respect to optimal resource estimation results such that we can track which instructions were used to estimate the trace and what properties they have. Other changes include: - A function `instruction_name` to turn an instruction ID into a name, e.g. `instruction_name(CNOT) == "CNOT"`, as well as using them in `__str__` (`Display`) implementations for ISAs and traces. - Prefixing some Rust bindings with an underscore when exported to the Python package to emphasize that they are private and are not exported by the `qsharp.qre` module.
This PR cleans up the way properties are handled for traces and results. Trace properties can be assigned by application generators and trace transforms and are stored in optimal resource estimation results. The Python API automatically detects whether the property value is `bool`, `int`, `float`, or `str` and does not require a dedicated property class exposed from Rust. Some other changes include - Fixes a deadlock due to the Python GIL - Allows parallel trace generation from application generators - Reorganizes code around Q# application generators - Sets up resource estimation for memory qubits
Major modifications to the internal structure of the Model class. - Coefficients of the model are now a dictionary keyed by the vertex tuple of the (hyper)edges. - API more closely matches QREv3 (still needs some work). - Standard translation-invariant Ising model is implemented as a factory function that builds Model instances. - Tests included.
Added a utilities sublibrary. * Moved Hypergraph and Hyperedge to utilities * Added Pauli and PauliString classes (primitives around Cirq classes) * Modified Model class to use PauliStrings * Modified tests
This PR adds various models: - Qubits - Majorana - Error correcting codes - ThreeAux - Yoked surface code - Factories - Round-based factory - Litinski19 factory It also makes some updates to the surface code model and improves documentation. Further, it adds a large test suite for all the models. Some of these tests are very detailed but they will help us to spot if we introduce inconsistencies with future code changes. Besides that there are some fixes to the Python API: - Adds caching to Q# to Trace transformation - InstructionFrontier can be 2D or 3D (without and with error rates) - Instance enumeration can also consider nested types and union types now - EstimationResult can be used from the Python API to create new results
Issue: different terms in a Trotter expansion may need different coloring of the edges. So the coloring is not an intrinsic property of the graph. We remove (edge) coloring of a graph to be a seperate class, and shift all the coloring functionality to this class. Hence a single graph can now support multiple different colorings. - Major revisions to the Hypergraph class and introduction of the HypergraphEdgeColoring class - Introduction of the the edge_coloring() function that wraps greedy_edge_coloring() for the base class - Revisions of each of the graph subclasses to remove coloring and create an overloaded version of edge_coloring() - Revisions of the docstrings across all these classes - Minor changes to some string representations - Update to all the unit tests
#2975) A small PR around the change in functionality of terms in the Model class. - Minor revisions on how edge coloring is presented - Terms are now dict[int, dict[int, int]], where the first index is the term and the second is the color, the value is the index of the interaction operator - Fixed IsingModel to use colorings properly - Added HeisenbergModel - Added tests
This fixes some tests that caused CI errors. The faulty tests were checked in with a previous PR. Fixes #2997
The main feature from this PR is a resource estimation result table that is returned from the `estimate` call. It can be configured to have additional columns which are considered in the creation of a pandas DataFrame. Besides that, the PR - refactors how instructions are build: they are now all build inside the provenance graph that is part of the architecture context - enhances enumeration capabilities: one can now enumerate over nested attributes and union attributes, and also restrict domains, further one can restrict the domain of the application inside the trace query - adds post processing to applications: applications can post-process estimation results _before_ they are inserted in the estimation table. This post processing step comes currently at a cost in runtime, because estimation is parallelized in Python and not in Rust
…ovements (#3013) This PR replaces string-keyed properties with integer keys defined via a Rust macro, and includes several estimation performance and API improvements. **Property keys** - New `define_properties!` macro in isa/property_keys.rs auto-assigns u64 values and generates `property_name_to_key` - Properties on `Trace`, `EstimationResult`, and `Instruction` now use `u64` keys instead of `String` - Python `property_keys` submodule exposes all keys as constants; `PropertyKey` enum is removed **Estimation improvements** - `LockedISA` holds a single read lock for the duration of `estimate()`, avoiding repeated lock acquisitions - ISA cloning is deferred to Pareto-surviving results only, reducing allocation in `estimate_parallel` - `EstimationTableStats` tracks job counts (total, successful, Pareto-surviving) - `add_qubit_partition_column()` breaks down physical qubits into compute, factory, and memory **Model updates** - `SurfaceCode`: configurable `one_qubit_gate_depth` / `two_qubit_gate_depth` with per-instruction time factor overrides - `RoundBasedFactory`: deterministic cache key using full instruction serialization Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This adds QIR support to QRE. It uses existing code to walk the QIR tree. The transformation will fail in programs with branches until we have better heuristics for branch prediction in place. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Splits Yoked SC into two models, also adds more property IDs.
When performing post processing we need to know the updated results after the post_process function on the application is called (in Python). As a result, so far a Python-based parallelism was used for estimation when post processing is in play. This is changed in this PR, by first computing all estimates in parallel (without filtering to Pareto optimal results) and then performing the filtering in Python. This reduces runtime by about 30% on some QRE tests. Further, it allows to use the same Rust-based estimation function which improves code sharing.
#3028) The previous implementation hit a corner case (the one in the test) which is now fixed with a new bucketing logic.
Adds an alternative estimation path that builds a **provenance graph** of ISA instructions and prunes suboptimal candidates before forming the Cartesian product, significantly reducing the combinatorial search space. ### Changes **Rust (`source/qre/src/`)** - `isa.rs`: Add `build_pareto_index()` to compute per-instruction-ID Pareto-optimal node sets over (space, time, error). Add `query_satisfying()` to enumerate ISAs from pruned graph nodes. Extract `InstructionConstraint::is_satisfied_by()` from inline logic. - `trace.rs`: Add `estimate_with_graph()` — a new parallel estimator that uses the provenance graph with per-slot dominance pruning to skip combinations dominated by previously successful estimates. Add `Trace::required_instruction_ids()` helper. Add `post_process` flag to `estimate_parallel()` to control summary collection. - `result.rs` / `lib.rs`: Expose new types and re-exports. **Python (`source/pip/`)** - `_estimation.py`: Add `use_graph` parameter to `estimate()` (default `True`). When enabled, populates the provenance graph and calls the graph-based estimator instead of the flat enumerator. - `_isa_enumeration.py`: Add `populate()` method to `ISAQuery` and its subclasses to fill the provenance graph without yielding ISA objects. - `_instruction.py`: Add `InstructionSource` utility. - `qre.rs`: Expose `_estimate_with_graph`, `ProvenanceGraph` bindings, and related Python-facing APIs. - `_qre.pyi`: Update type stubs. **Tests** - Add tests verifying graph-based estimation produces Pareto-optimal results consistent with the exhaustive path. ### Trade-offs The graph-based pruning filters ISA instructions by comparing per-instruction space, time, and error independently. Because total qubit counts depend on the interaction between factory space and runtime (copies × factory_space), an instruction dominated on per-instruction metrics can still contribute to a globally Pareto-optimal result. `use_graph=False` can be used when completeness of the Pareto frontier is required.
…3040) New features for Trotter expansions. * Main class is now TrotterExpansion. * TrotterStep represents a single Trotter step. * TrotterExpansion accepts a function the creates the target type of Trotter step. * Minor changes to the Model class and PauliString class to support changes. * Added cirq.Circuit output to TrotterStep instances. * Added cirq.CircuitOperation output to TrotterExpansion instances. * Updated unit tests.
- Remove unused import - Propagate source and transform information in cached T states
Adding a plotting function for estimation results. We may change this later to use Q# widgets like other parts in the repo. But adding this functionality now to support samples of higher priority.
We always get logical compute and memory qubits (memory is 0, if there are no memory qubits). These are the qubits that are in the trace before estimation, and therefore might already contain auxiliary qubits. Application generators may add algorithm logical qubits (for compute and memory) to the trace properties as well.
Some refactoring of the trace code for graph estimation, and a way to expose the ISA requirements of a trace through the Python API.
This improves the function to retrieve ISA requirements from a trace. This can then be used both as a trace profile to prune estimation jobs based on the minimum required error rate for an instruction, but also to report the provided ISA for a trace through the Python API. A function to display it as a pandas data frame facilitates using it in a Jupyter notebook.
This is still an intermediate way to get plots into Jupyter notebooks and should be replaced by qdk widgets in a future PR.
This adds support to generate traces from cirq circuits. These traces represent the original circuit and do not simply represent the gate counts. They monkey patch a `_to_trace` method to cirq gates and users of QRE can add a `_to_trace` method to their custom operations and gates. If no such method is found, the operation's or gate's decomposition method will be called to walk the circuit tree. The PR has some other small fixes: - extending the gate-based architecture gate set - minor fixes to `Trace` Python API - minor improvements on how to create _estimation table results_ (with extended info such as source ISA tree) from unannotated _estimation results_
Some files became too large, so they have been split up. Also some Python names are used in the public API and the `_` prefix was removed. The list of commits gives a good overview of what happened in this PR. There is no changes to the functionality or no added functionality in this PR.
Makes sure that Python docs for QRE are complete and are consistent with the style used in the other Python files.
Using matplotlib in tests is causing CI problems. This fixes #3076
Graph-based estimation missed some estimates when using ISA transforms with a pass-through (e.g., those extending instruction sets and keeping the previous ones).
| instances = _enumerate_instances(t, **transformer_kwargs) | ||
| transformer_instances.append(instances) | ||
|
|
||
| # TODO: make parallel |
Check notice
Code scanning / devskim
A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note
| Returns: | ||
| Trace: The resource estimation trace. | ||
| """ | ||
| # TODO: make caching work for `Callable` as well |
Check notice
Code scanning / devskim
A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note
| self.output_error_rate, | ||
| ) | ||
| ) | ||
| # TODO: handle case when output_error_rate is larger than input_error_rate |
Check notice
Code scanning / devskim
A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note
| } | ||
| } | ||
|
|
||
| // TODO: Assign default value to offset? |
Check notice
Code scanning / devskim
A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note
| pytest | ||
| expecttest==0.3.0 | ||
| pyqir>=0.11.1,<0.12 | ||
| cirq==1.6.1 | ||
| pandas>=2.1 |
There was a problem hiding this comment.
We have a few different test_requirements files in the Python code at this point. Should we consider adding a "test" extra so that we can pip install ".[test]" and consolidate test deps and versions? I bring this up as the cirq version requirement here is compatible but different than the wheel cirq extra version requirements. /CC @minestarks @swernli
|
|
||
| /// A resourc estimation error. | ||
| #[derive(Clone, Debug, Error, PartialEq)] | ||
| pub enum Error { |
There was a problem hiding this comment.
For custom errors we should be using miette diagnostics with code/help where applicable for better errors and consistency with the codebase.
No description provided.