* Avoid Python op creation in commutative cancellation
This commit updates the commutative cancellation and commutation
analysis transpiler pass. It builds off of #12692 to adjust access
patterns in the python transpiler path to avoid eagerly creating a
Python space operation object. The goal of this PR is to mitigate the
performance regression on these passes introduced by the extra
conversion cost of #12459.
* Remove stray print
* Don't add __array__ to DAGOpNode or CircuitInstruction
* Use rust gates for Optimize1QGatesDecomposition
This commit moves to using rust gates for the Optimize1QGatesDecomposition
transpiler pass. It takes in a sequence of runs (which are a list of
DAGOpNodes) from the python side of the transpiler pass which are
generated from DAGCircuit.collect_1q_runs() (which in the future should
be moved to rust after #12550 merges). The rust portion of the pass now
iterates over each run, performs the matrix multiplication to compute the
unitary of the run, then synthesizes that unitary, computes the
estimated error of the circuit synthesis and returns a tuple of the
circuit sequence in terms of rust StandardGate enums. The python portion
of the code then takes those sequences and does inplace substitution of
each run with the sequence returned from rust.
Once #12550 merges we should be able to move the input collect_1q_runs()
call and perform the output node substitions in rust making the full
pass execute in the rust domain without any python interaction.
Additionally, the OneQubitEulerDecomposer class is updated to use
rust for circuit generation instead of doing this python side. The
internal changes done to use rust gates in the transpiler pass meant we
were half way to this already by emitting rust StandardGates instead of
python gate objects. The dag handling is still done in Python however
until #12550 merges.
This also includes an implementation of the r gate, I temporarily added
this to unblock this effort as it was the only gate missing needed to
complete this. We can rebase this if a standalone implementation of the
gate merges before this.
* Cache target decompositions for each qubit
Previously this PR was re-computing the target bases to synthesize with
for each run found in the circuit. But in cases where there were
multiple runs repeated on a qubit this was unecessary work. Prior to
moving this code to rust there was already caching code to make this
optimization, but the rust path short circuited around this. This commit
fixes this so we're caching the target bases for each qubit and only
computing it once.
* Optimize rust implementation slightly
* Avoid extra allocations by inlining matrix multiplication
* Remove unnecessary comment
* Remove stray code block
* Add import path for rust gate
* Use rust gate in circuit constructor
* Remove duplicated op_name getter and just use existing name getter
* Apply suggestions from code review
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
* Simplify construction of target_basis_vec
* Fix rebase issue
* Update crates/accelerate/src/euler_one_qubit_decomposer.rs
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
* Update crates/accelerate/src/euler_one_qubit_decomposer.rs
---------
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
After the recently merged #12543 when working with Rust 1.79 cargo fmt
makes a small formatting change that rust 1.70 wouldn't and clippy makes
flags a &Vec<_> that should be a slice &[_] instead. This commit makes
these two small chagnes so they're not an issue for people building with
the latest stable version of rust, not just our MSRV.
* Avoid Python operation creation in transpiler
Since #12459 accessing `node.op` in the transpiler eagerly creates a
Python object on access. This is because we now are no longer storing a
Python object internally and we need to rebuild the object to return the
python object as expected by the api. This is causing a significant
performance regression because of the extra overhead. The longer term
goal is to move as much of the performance critical passes to operate in
rust which will eliminate this overhead. But in the meantime we can
mitigate the performance overhead by changing the Python access patterns
to avoid the operation object creation. This commit adds some new getter
methods to DAGOpNode to give access to the inner rust data so that we
can avoid the extra overhead. As a proof of concept this updates the
unitary synthesis pass in isolation. Doing this fixes the regression
caused by #12459 for that pass. We can continue this migration for
everything else in follow up PRs. This commit is mostly to establish the
pattern and add the python space access methods.
* Remove unused import
* Add path to avoid StandardGate conversion in circuit_to_dag
* Add fast path through dag_to_circuit
* Fix ' into `
* More typos on release notes and on API documentation
* change `self.filter` for `Schedule.filter`
* change `Schedule` -> `ScheduleBlock` in its `filter()` reference
- Expose `operation_type_to_py`, `operation_type_and_data_to_py`, `convert_py_to_operation_type`, methods to other rust crates.
- Expose `OperationTypeConstruct` struct to other crates.
* add warning for bad justify input in circuit_drawer
* change justify after raising error
* typo indentation + improving warning string
* Undo max_lenght limit by autoformater (120 > 105)
* Make lines fullfill 105 max lenght requirement
* Solve regex matching parenthesis problem and don't trigger the wanring for default value
* Change justify default value to "left", & add deprecation wrapper
* Change and extend warnings tests
* Solve various layers of same argument DeprecationWarning
* Added a clarification comment for the solution, about multiple deprecationwarnings
* Ignore cyclic import error, as above
* Apply suggestions from code review
Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com>
* Apply suggestions from code review
* Improve DeprecationWarning readability, and fix warning checks tests
* Remove `_is_valid_justify_arg` from `@deprecate_arg`, for solving circular import
* in `deprecate_arg` change `since` to "1.2.0"
* black formater suggestion
* negate conditions for `predicate` in `@deprecate_arg`
* remove `pending=True`, since then warning is not raised
* change qiskit version on tests
* remove assert Regex for DeprecationWarning
* Add release note, and remove two undesired changes in imports
* changing release note naming from "_" to "-"
* Add extra line in the end, for lint
* Redid release file from start, with shorter name, and correct spacings
* Remove final spaces in all lines...
* Try without deprecations_visualization section..
* Solve, bad Sphinx spacing, go back to deprecations_visualization
* Go back to `None` as default value
* Simplifying deprecation logic
* Remove unused imports and changed missing default value
* Improve docstring for public methods
* Improve error readbility and testing of it with regex
---------
Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com>
This encapsulates a lot of the common logic around Python sequence-like
indexers (`SliceOrInt`) into iterators that handle adapting negative
indices and slices in `usize` for containers of a given size.
These indexers now all implement `ExactSizeIterator` and
`DoubleEndedIterator`, so they can be used with all `Iterator` methods,
and can be used (with `Iterator::map` and friends) as inputs to
`PyList::new_bound`, which makes code simpler at all points of use.
The special-cased uses of this kind of thing from `CircuitData` are
replaced with the new forms. This had no measurable impact on
performance on my machine, and removes a lot noise from error-handling
and highly specialised functions.
* gaussian elimination in rust
* handle lint errors
* replace python function by rust function for gauss elimination
* change matrix elements type from bool to i8
* add parallelization in row operations
* update matrices in place
* change matrix type in rust code to bool
* handle type in python code
* update filter following review
* remove parallelization using rayon
* move _gauss_elimination_with_perm to rust
* fix fmt error
* simplify _gauss_elimination function
* update _compute_rank_after_gauss_elim to rust
* update _row_op and _col_op
* transfer _row_op and _col_op from python to rust
* fix code due to failing tests
* minor update of types
* move calc_inverse_matrix to rust, add _binary_matmul in rust
* fix failing tests, by changing mat type from int to bool
* update rust docstrings
* add function _add_row_or_col to rust code
* improve binary_matmul
* proper error handling
* unified format of function names
* move compute_rank from python to rust, update errors
* update type of mat in compute_rank
* move random_invertible_binary_matrix and check_invertible_binary_matrix to rust
* Updating HighLevelSynthesis tests that depend on the specific random number
* Updating LinearSynthesis tests to pass seeds
* Updating tests in test_linear_function
* changing the matrix type in random dyhedral to be a matrix of ints rather than bools
* updating cx_cz synthesis tests
* updating clifford tests
* remove unused imports
* add option seed=None
* enhance rust docs
* add release notes
* remove unnecessary copy in python
* another copy fix
* another copy fix
* update rust docstrings
* update release notes
---------
Co-authored-by: AlexanderIvrii <alexi@il.ibm.com>
In Rust 1.79.0 several new clippy rules were added and/or enabled by
default. This was causing some new issues to be flagged when building
qiskit with the this release of Rust. This commit fixes these issues
flagged by clippy.
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* Suppress nonsense `DeprecationWarning` caused by `unittest`
`unittest.TestCase.assertWarns` in context-manager form has an awkward
habit of querying the `__warningregistry__` attribute on every module in
existence. This interacts poorly with a Numpy 2 deprecation warning
trigger for code that's attempting to import functions from modules that
became private in Numpy 2, if a warning has previously been triggered
out of `numpy.linalg._linalg`.
This simply suppresses that particular warning from the test suite.
* Refine filter
* Pin Rustworkx to avoid buggy graphviz drawing
* Update test/utils/base.py
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
---------
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
This PR introduces some abbreviations for repetitive Rust code. Motivations are reducing
clutter, improving readability, and perhaps modest support for rapid development.
* Use the definition of `const fn 64` that was introduced in #12459 uniformly in all crates.
* Define some complex constants `C_ONE`, `C_ZERO`, `IM`, etc.
* Introduce type definitions for arrays representing gates. For example:
`GateArray1Q = [[Complex64; 2]; 2];`
* Implement RGate in Rust
* Update crates/circuit/src/operations.rs
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* Fix error in decomposition of RGate
There is an error in the expression for decomposition of the R gate
in the port to Rust.
This fixes the error and re-enables the skipped test that failed because
of the incorrect expression.
* Factor cloning the Param enum in Rust
To clone the enum, each variant must be handled separately. This is currently used once,
but can be used each time a `Param` is cloned. In case more work needs to be done within
match arms, one might choose not to use this function, but rather clone in each of these
arms.
* Run cargo fmt
* Implement and use addition for enum Param
This handles `Float` and `ParameterExpression` variants uniformly.
---------
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
This commit adds a test to the test_rust_equivalence module to assert
that the Python gate objects returned from the Rust CircuitData is
the correct type.
* Simplify QuantumCircuit._from_circuit_data bit handling
This commit simplifies the logic around bit handling in the
`QuantumCircuit._from_circuit_data()` constructor. Previously it was
calling `add_bits()` for each bit in the `CircuitData` object to update
the output circuit's accounting for each qubit. But this was needlessly
heavy as the `CircuitData` is already the source of truth for the bits
in a circuit and we just need to update the indices dictionary. The
`add_bits()` method attempts to add the bits to the `CircuitData` too
but this is wasted overhead because the `CircuitData` already has the
bits as that's where the came from. This changes the constructor to just
directly set the bit indices as needed and return the circuit.
* Use a dict comprehension instead of a for loop
* GenericBackendV2 should fail when the backend cannot allocate the basis gate because its size
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* reno
* Update releasenotes/notes/fixes_GenericBackendV2-668e40596e1f070d.yaml
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* another single qubit backend
---------
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
This has been the legacy path since `CircuitInstruction` was added in
gh-8093. It's more performant to use the attribute-access patterns, and
with more of the internals moving to Rust and potentially needing more
use of additional class methods and attributes, we need to start
shifting people away from the old form.
* Add rust representation for the u1, u2, and u3 gates
This commit adds the rust representation of the U1Gate, U2Gate, and
U3Gate to the `StandardGates` enum in rust.
Part of #12566
* Update crates/circuit/src/imports.rs
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* Fix test failures
* Fix pylint pedantry
---------
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
* Follow up on #12327
also port circuit construction to rust and add a reno
* move _get_ordered_swap to Rust only
* drop redundant Ok(expect())
* proper synthesis structure
* Add XXMinusYYGate and XXPlusYYGate, implement parameter multiplication function (naive approach).
Co-authored by: Julien Gacon jul@zurich.ibm.com
* * Format code
* Use multiply_param in RZGate
* Fix signs and indices
The legacy 3-tuple format of `CircuitInstruction` still exposes the
object in the old tuple-like way of `(Operation, list[Qubit],
list[Clbit])`, rather than the new-style attribute access using tuples
for the qargs and cargs. This was inadvertantly changed when it moved
to Rust.
The return type hint of `find_basic_approximation` method changes from `Gate` to `GateSequence` in `SolovayKitaevDecomposition` class, as implied by `self.basic_approximations`.
With no remaining mentions of `Gate`, its corresponding import statement is removed.
This localises the caching concerns of the `PackedInstruction::py_op`
field into a method `unpack_py_op`, which can now update the cache
through an immutable reference (if no other immutable references are
taken out). Having the new method to encapsulate the `cache_pyops`
feature simplifies the large `#[cfg(feature = "cache_pyop")]` gates.
* fix error when V2 model is set
* Apply suggestions from code review
* Fix black
---------
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
Co-authored-by: Elena Peña Tapia <epenatap@gmail.com>