Commit Graph

122 Commits

Author SHA1 Message Date
Raynel Sanchez 5db984ae0c
Initial: Expose operation conversion methods to other crates. (#12698)
- 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.
2024-07-01 19:01:12 +00:00
Jake Lishman 373e8a68c8
Encapsulate Python sequence-like indexers (#12669)
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.
2024-07-01 12:59:21 +00:00
Elena Peña Tapia a7fc2daf4c
Add Rust representation for CHGate, CPhaseGate, CSGate, CSdgGate, CSXGate, CSwapGate (#12639)
* Add CHGate, CPhaseGate, CSGate, CSdgGate, CSXGate, CSwapGate

* Fix tests, add labels

* Fix oversights in gate definitions

* Fix test

* Add ctrl_state 1 to rust building path.
2024-07-01 12:49:06 +00:00
dependabot[bot] c452694d70
Bump rustworkx-core from 0.14.2 to 0.15.0 (#12682)
Bumps [rustworkx-core](https://github.com/Qiskit/rustworkx) from 0.14.2 to 0.15.0.
- [Release notes](https://github.com/Qiskit/rustworkx/releases)
- [Commits](https://github.com/Qiskit/rustworkx/compare/0.14.2...0.15.0)

---
updated-dependencies:
- dependency-name: rustworkx-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
2024-07-01 12:27:45 +00:00
Eli Arbel 7056198242
Add Rust representation for RXX, RYY, RZZ & RZX gates (#12672)
* Updating tables

* Updating mapping tables

* Adding remaining functionality

* Handling Black, clippy, fmt
2024-07-01 10:02:51 +00:00
Shelly Garion e9208a6339
binary matrices utils in rust (#12456)
* 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>
2024-06-28 20:18:17 +00:00
Matthew Treinish 24ee7c69b5
Fix clippy warnings on latest stable rust (#12675)
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>
2024-06-28 16:03:37 +00:00
Julien Gacon 9b0a5849f6
Port CRX/Y/Z gates to Rust (#12648)
* v0 of CR-Pauli gates

* fix inevitable matrix typos

* update multiply_param

and prepare for U1/2/3 PR

* fix num params/qubits

* cct methods to append rust gates

---------

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
2024-06-28 15:34:30 +00:00
John Lapeyre ea5a54b9da
Add constant abbreviations for some values and types. (#12651)
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];`
2024-06-27 19:38:36 +00:00
John Lapeyre 6447941885
Implement RGate in Rust (#12662)
* 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>
2024-06-27 09:08:24 +00:00
Eli Arbel 2fab2007e3
Add Rust representation for DCXGate (#12644)
* Updating tables

* Adding remaining code

* Appending the Rust representation directly

* Fix fmt

---------

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
2024-06-26 15:15:10 +00:00
Jake Lishman 8b1f75ffaf
Deprecate tuple-like access to `CircuitInstruction` (#12640)
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.
2024-06-24 18:21:20 +00:00
Elena Peña Tapia b20a7ceb58
Add placeholders for all mising standard gates in Rust (#12646)
* Add placeholders for all gates, mark TODOs

* Update name for CPhase

* Remove todo from Ux gates
2024-06-24 18:16:16 +00:00
dependabot[bot] 35f6297f20
Bump faer from 0.19.0 to 0.19.1 (#12645)
Bumps [faer](https://github.com/sarah-ek/faer-rs) from 0.19.0 to 0.19.1.
- [Changelog](https://github.com/sarah-ek/faer-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sarah-ek/faer-rs/commits)

---
updated-dependencies:
- dependency-name: faer
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-24 15:23:42 +00:00
Matthew Treinish bf8f398fa4
Add rust representation for the u1, u2, and u3 gates (#12572)
* 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>
2024-06-24 14:05:06 +00:00
Julien Gacon de6c6eb2f9
Follow up on #12327: circuit construction in Rust (#12605)
* 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
2024-06-24 08:02:31 +00:00
Elena Peña Tapia 87aa89c193
Add Rust representation for `XXMinusYYGate` and `XXPlusYYGate` (#12606)
* 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
2024-06-21 15:25:59 +00:00
Jake Lishman 22c145aa0e
Fix `CircuitInstruction` legacy iterable typing (#12630)
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.
2024-06-21 12:28:57 +00:00
Jake Lishman b8de17f908
Localise `py_op` caching data in `RefCell` (#12594)
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.
2024-06-21 10:15:07 +00:00
Luis J Camargo 0f513577b3
Spellcheck Done [Unitary Hack 2024] (#12501)
* spell check iter1

* spell check iter 2

* Fix fmt

* Update qiskit/_numpy_compat.py

* Update qiskit/synthesis/evolution/product_formula.py

* Update qiskit/synthesis/evolution/product_formula.py

* Update releasenotes/notes/0.13/qinfo-states-7f67e2432cf0c12c.yaml

* undo some corrections

---------

Co-authored-by: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com>
Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
Co-authored-by: Julien Gacon <jules.gacon@googlemail.com>
2024-06-19 15:50:03 +00:00
Elena Peña Tapia d4e795b431
Add rust representation for SGates, TGates, and iSwap gate (#12598)
* Add SGate, SdgGate, iSWAP, TGate, and TdgGate to standard gates in rust.
Add missing gate definitions that depended on these gates (marked as todo).

* Add fast path to circuit methods, fix sneaky bugs, unskip cy and sx tests.

* Unskip ccx test too!

* Fix black
2024-06-18 19:28:59 +00:00
Matthew Treinish f304a4b4f8
Add infrastructure for gates, instruction, and operations in Rust (#12459)
* Add infrastructure for gates, instruction, and operations in Rust

This commit adds a native representation of Gates, Instruction, and
Operations to rust's circuit module. At a high level this works by
either wrapping the Python object in a rust wrapper struct that tracks
metadata about the operations (name, num_qubits, etc) and then for other
details it calls back to Python to get dynamic details like the
definition, matrix, etc. For standard library gates like Swap, CX, H,
etc this replaces the on-circuit representation with a new rust enum
StandardGate. The enum representation is much more efficient and has a
minimal memory footprint (just the enum variant and then any parameters
or other mutable state stored in the circuit instruction). All the gate
properties such as the matrix, definiton, name, etc are statically
defined in rust code based on the enum variant (which represents the
gate).

The use of an enum to represent standard gates does mean a change in
what we store on a CircuitInstruction. To represent a standard gate
fully we need to store the mutable properties of the existing Gate class
on the circuit instruction as the gate by itself doesn't contain this
detail. That means, the parameters, label, unit, duration, and condition
are added to the rust side of circuit instrucion. However no Python side
access methods are added for these as they're internal only to the Rust
code. In Qiskit 2.0 to simplify this storage we'll be able to drop, unit,
duration, and condition from the api leaving only label and parameters.
But for right now we're tracking all of the fields.

To facilitate working with circuits and gates full from rust the
setting the `operation` attribute of a `CircuitInstruction` object now
transltates the python object to an internal rust representation.
For standard gates this translates it to the enum form described earlier,
and for other circuit operations 3 new Rust structs: PyGate,
PyInstruction, and PyOperation are used to wrap the underlying Python
object in a Rust api. These structs cache some commonly accessed static
properties of the operation, such as the name, number of qubits, etc.
However for dynamic pieces, such as the definition or matrix, callback
to python to get a rust representation for those.

Similarly whenever the `operation` attribute is accessed from Python
it converts it back to the normal Python object representation. For
standard gates this involves creating a new instance of a Python object
based on it's internal rust representation. For the wrapper structs a
reference to the wrapped PyObject is returned.

To manage the 4 variants of operation (`StandardGate`, `PyGate`,
`PyInstruction`, and `PyOperation`) a new Rust trait `Operation` is
created that defines a standard interface for getting the properties
of a given circuit operation. This common interface is implemented for
the 4 variants as well as the `OperationType` enum which wraps all 4
(and is used as the type for `CircuitInstruction.operation` in the
rust code.

As everything in the `QuantumCircuit` data model is quite coupled moving
the source of truth for the operations to exist in Rust means that more
of the underlying `QuantumCircuit`'s responsibility has to move to Rust
as well. Primarily this involves the `ParameterTable` which was an
internal class for tracking which instructions in the circuit have a
`ParameterExpression` parameter so that when we go to bind parameters we
can lookup which operations need to be updated with the bind value.
Since the representation of those instructions now lives in Rust and
Python only recieves a ephemeral copy of the instructions the
ParameterTable had to be reimplemented in Rust to track the
instructions. This new parameter table maps the Parameter's uuid (as a
u128) as a unique identifier for each parameter and maps this to a
positional index in the circuit data to the underlying instruction using
that parameter. This is a bit different from the Python parameter table
which was mapping a parameter object to the id of the operation object
using that parmaeter. This also leads to a difference in the binding
mechanics as the parameter assignment was done by reference in the old
model, but now we need to update the entire instruction more explicitly
in rust. Additionally, because the global phase of a circuit can be
parameterized the ownership of global phase is moved from Python into
Rust in this commit as well.

After this commit the only properties of a circuit that are not defined
in Rust for the source of truth are the bits (and vars) of the circuit,
and when creating circuits from rust this is what causes a Python
interaction to still be required.

This commit does not translate the full standard library of gates as
that would make the pull request huge, instead this adds the basic
infrastructure for having a more efficient standard gate representation
on circuits. There will be follow up pull requests to add the missing
gates and round out support in rust.

The goal of this pull request is primarily to add the infrastructure for
representing the full circuit model (and dag model in the future) in
rust. By itself this is not expected to improve runtime performance (if
anything it will probably hurt performance because of extra type
conversions) but it is intended to enable writing native circuit
manipulations in Rust, including transpiler passes without needing
involvement from Python. Longer term this should greatly improve the
runtime performance and reduce the memory overhead of Qiskit. But,
this is just an early step towards that goal, and is more about
unlocking the future capability. The next steps after this commit are
to finish migrating the standard gate library and also update the
`QuantumCircuit` methods to better leverage the more complete rust
representation (which should help offset the performance penalty
introduced by this).

Fixes: #12205

* Fix Python->Rust Param conversion

This commit adds a custom implementation of the FromPyObject trait for
the Param enum. Previously, the Param trait derived it's impl of the
trait, but this logic wasn't perfect. In cases whern a
ParameterExpression was effectively a constant (such as `0 * x`) the
trait's attempt to coerce to a float first would result in those
ParameterExpressions being dropped from the circuit at insertion time.
This was a change in behavior from before having gates in Rust as the
parameters would disappear from the circuit at insertion time instead of
at bind time. This commit fixes this by having a custom impl for
FromPyObject that first tries to figure out if the parameter is a
ParameterExpression (or a QuantumCircuit) by using a Python isinstance()
check, then tries to extract it as a float, and finally stores a
non-parameter object; which is a new variant in the Param enum. This
new variant also lets us simplify the logic around adding gates to the
parameter table as we're able to know ahead of time which gate
parameters are `ParameterExpression`s and which are other objects (and
don't need to be tracked in the parameter table.

Additionally this commit tweaks two tests, the first is
test.python.circuit.library.test_nlocal.TestNLocal.test_parameters_setter
which was adjusted in the previous commit to workaround the bug fixed
by this commit. The second is test.python.circuit.test_parameters which
was testing that a bound ParameterExpression with a value of 0 defaults
to an int which was a side effect of passing an int input to symengine
for the bind value and not part of the api and didn't need to be
checked. This assertion was removed from the test because the rust
representation is only storing f64 values for the numeric parameters
and it is never an int after binding from the Python perspective it
isn't any different to have float(0) and int(0) unless you explicit
isinstance check like the test previously was.

* Fix qasm3 exporter for std gates without stdgates.inc

This commit fixes the handling of standard gates in Qiskit when the user
specifies excluding the use of the stdgates.inc file from the exported
qasm. Previously the object id of the standard gates were used to
maintain a lookup table of the global definitions for all the standard
gates explicitly in the file. However, the rust refactor means that
every time the exporter accesses `circuit.data[x].operation` a new
instance is returned. This means that on subsequent lookups for the
definition the gate definitions are never found. To correct this issue
this commit adds to the lookup table a fallback of the gate name +
parameters to do the lookup for. This should be unique for any standard
gate and not interfere with the previous logic that's still in place and
functional for other custom gate definitions.

While this fixes the logic in the exporter the test is still failing
because the test is asserting the object ids are the same in the qasm3
file, which isn't the case anymore. The test will be updated in a
subsequent commit to validate the qasm3 file is correct without using
a hardcoded object id.

* Fix base scheduler analysis pass duration setting

When ALAPScheduleAnalysis and ASAPScheduleAnalysis were setting the
duration of a gate they were doing `node.op.duration = duration` this
wasn't always working because if `node.op` was a standard gate it
returned a new Python object created from the underlying rust
representation. This commit fixes the passes so that they modify the
duration and then explicit set the operation to update it's rust
representation.

* Fix python lint

* Fix last failing qasm3 test for std gates without stdgates.inc

While the logic for the qasm3 exporter was fixed
in commit a6e69ba4c9 to handle the edge
case of a user specifying that the qasm exporter does not use the
stdgates.inc include file in the output, but also has qiskit's standard
gates in their circuit being exported. The one unit test to provide
coverage for that scenario was not passing because when an id was used
for the gate definitions in the qasm3 file it was being referenced
against a temporary created by accessing a standard gate from the
circuit and the ids weren't the same so the reference string didn't
match what the exporter generated. This commit fixes this by changing
the test to not do an exact string comparison, but instead a line by
line comparison that either does exact equality check or a regex search
for the expected line and the ids are checked as being any 15 character
integer.

* Remove superfluous comment

* Cache imported classes with GILOnceCell

* Remove unused python variables

* Add missing file

* Update QuantumCircuit gate methods to bypass Python object

This commit updates the QuantumCircuit gate methods which add a given
gate to the circuit to bypass the python gate object creation and
directly insert a rust representation of the gate. This avoids a
conversion in the rust side of the code. While in practice this is just
the Python side object creation and a getattr for the rust code to
determine it's a standard gate that we're skipping. This may add up over
time if there are a lot of gates being created by the method.

To accomplish this the rust code handling the mapping of rust
StandardGate variants to the Python classes that represent those gates
needed to be updated as well. By bypassing the python object creation
we need a fallback to populate the gate class for when a user access the
operation object from Python. Previously this mapping was only being
populated at insertion time and if we never insert the python object
(for a circuit created only via the methods) then we need a way to find
what the gate class is. A static lookup table of import paths and class names
are added to `qiskit_circuit::imports` module to faciliate this and
helper functions are added to facilitate interacting with the class
objects that represent each gate.

* Deduplicate gate matrix definitions

* Fix lint

* Attempt to fix qasm3 test failure

* Add compile time option to cache py gate returns for rust std gates

This commit adds a new rust crate feature flag for the qiskit-circuits
and qiskit-pyext that enables caching the output from
CircuitInstruction.operation to python space. Previously, for memory
efficiency we were reconstructing the python object on demand for every
access. This was to avoid carrying around an extra pointer and keeping
the ephemeral python object around longer term if it's only needed once.
But right now nothing is directly using the rust representation yet and
everything is accessing via the python interface, so recreating gate
objects on the fly has a huge performance penalty. To avoid that this
adds caching by default as a temporary solution to avoid this until we
have more usage of the rust representation of gates.

There is an inherent tension between an optimal rust representation
and something that is performant for Python access and there isn't a
clear cut answer on which one is better to optimize for. A build time
feature lets the user pick, if what we settle on for the default doesn't
agree with their priorities or use case. Personally I'd like to see us
disable the caching longer term (hopefully before releasing this
functionality), but that's dependent on a sufficent level of usage from
rust superseding the current Python space usage in the core of Qiskit.

* Add num_nonlocal_gates implementation in rust

This commit adds a native rust implementation to rust for the
num_nonlocal_gates method on QuantumCircuit. Now that we have a rust
representation of gates it is potentially faster to do the count because
the iteration and filtering is done rust side.

* Performance tuning circuit construction

This commit fixes some performance issues with the addition of standard
gates to a circuit. To workaround potential reference cycles in Python
when calling rust we need to check the parameters of the operation. This
was causing our fast path for standard gates to access the `operation`
attribute to get the parameters. This causes the gate to be eagerly
constructed on the getter. However, the reference cycle case can only
happen in situations without a standard gate, and the fast path for
adding standard gates directly won't need to run this so a skip is added
if we're adding a standard gate.

* Add back validation of parameters on gate methods

In the previous commit a side effect of the accidental eager operation
creation was that the parameter input for gates were being validated by
that. By fixing that in the previous commit the validation of input
parameters on the circuit methods was broken. This commit fixes that
oversight and adds back the validation.

* Skip validation on gate creation from rust

* Offload operation copying to rust

This commit fixes a performance regression in the
`QuantumCircuit.copy()` method which was previously using Python to copy
the operations which had extra overhead to go from rust to python and
vice versa. This moves that logic to exist in rust and improve the copy
performance.

* Fix lint

* Perform deepcopy in rust

This commit moves the deepcopy handling to occur solely in Rust.
Previously each instruction would be directly deepcopied by iterating
over the circuit data. However, we can do this rust side now and doing
this is more efficient because while we need to rely on Python to run a
deepcopy we can skip it for the Rust standard gates and rely on Rust to
copy those gates.

* Fix QuantumCircuit.compose() performance regression

This commit fixes a performance regression in the compose() method. This
was caused by the checking for classical conditions in the method
requiring eagerly converting all standard gates to a Python object. This
changes the logic to do this only if we know we have a condition (which
we can determine Python side now).

* Fix map_ops test case with no caching case

* Fix typos in docs

This commit fixes several docs typos that were caught during code review.

Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>

* Shrink memory usage for extra mutable instruction state

This commit changes how we store the extra mutable instruction state
(condition, duration, unit, and label) for each `CircuitInstruction`
and `PackedInstruction` in the circuit. Previously it was all stored
as separate `Option<T>` fields on the struct, which required at least
a pointer's width for each field which was wasted space the majority of
the time as using these fields are not common. To optimize the memory
layout of the struct this moves these attributes to a new struct which
is put in an `Option<Box<_>>` which reduces it from 4 pointer widths
down to 1 per object. This comes from extra runtime cost from the extra
layer of pointer indirection but as this is the uncommon path this
tradeoff is fine.

* Remove Option<> from params field in CircuitInstruction

This commit removes the Option<> from the params field in
CircuitInstruction. There is no real distinction between an empty vec
and None in this case, so the option just added another layer in the API
that we didn't need to deal with. Also depending on the memory alignment
using an Option<T> might have ended up in a little extra memory usage
too, so removing it removes that potential source of overhead.

* Eagerly construct rust python wrappers in .append()

This commit updates the Python code in QuantumCircuit.append() method
to eagerly construct the rust wrapper objects for python defined circuit
operations.

* Simplify code around handling python errors in rust

* Revert "Skip validation on gate creation from rust"

This reverts commit 2f81bde8bf. The
validation skipping was unsound in some cases and could lead to invalid
circuit being generated. If we end up needing this as an optimization we
can remove this in the future in a follow-up PR that explores this in
isolation.

* Temporarily use git for qasm3 import

In Qiskit/qiskit-qasm3-import#34 the issue we're hitting caused by
qiskit-qasm3-import using the private circuit attributes removed in this
PR was fixed. This commit temporarily moves to installing it from git so
we can fully run CI. When qiskit-qasm3-import is released we should
revert this commit.

* Fix lint

* Fix lint for real (we really need to use a py312 compatible version of pylint)

* Fix test failure caused by incorrect lint fix

* Relax trait-method typing requirements

* Encapsulate `GILOnceCell` initialisers to local logic

* Simplify Interface for building circuit of standard gates in rust

* Simplify complex64 creation in gate_matrix.rs

This just switches Complex64::new(re, im) to be c64(re, im) to reduce
the amount of typing. c64 needs to be defined inplace so it can be a
const fn.

* Simplify initialization of array of elements that are not Copy (#28)

* Simplify initialization of array of elements that are not Copy

* Only generate array when necessary

* Fix doc typos

Co-authored-by: Kevin Hartman <kevin@hart.mn>

* Add conversion trait for OperationType -> OperationInput and simplify CircuitInstruction::replace()

* Use destructuring for operation_type_to_py extra attr handling

* Simplify trait bounds for map_indices()

The map_indices() method previously specified both Iterator and
ExactSizeIterator for it's trait bounds, but Iterator is a supertrait of
ExactSizeIterator and we don't need to explicitly list both. This commit
removes the duplicate trait bound.

* Make Qubit and Clbit newtype member public

As we start to use Qubit and Clbit for creating circuits from accelerate
and other crates in the Qiskit workspace we need to be able to create
instances of them. However, the newtype member BitType was not public
which prevented creating new Qubits. This commit fixes this by making it
public.

* Use snakecase for gate matrix names

* Remove pointless underscore prefix

* Use downcast instead of bound

* Rwork _append reference cycle handling

This commit reworks the multiple borrow handling in the _append() method
to leveraging `Bound.try_borrow()` to return a consistent error message
if we're unable to borrow a CircuitInstruction in the rust code meaning
there is a cyclical reference in the code. Previously we tried to detect
this cycle up-front which added significant overhead for a corner case.

* Make CircuitData.global_phase_param_index a class attr

* Use &[Param] instead of &SmallVec<..> for operation_type_and_data_to_py

* Have get_params_unsorted return a set

* Use lookup table for static property methods of StandardGate

* Use PyTuple::empty_bound()

* Fix lint

* Add missing test method docstring

* Reuse allocations in parameter table update

* Remove unnecessary global phase zeroing

* Move manually set params to a separate function

* Fix release note typo

* Use constant for global-phase index

* Switch requirement to release version

---------

Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
Co-authored-by: Kevin Hartman <kevin@hart.mn>
2024-06-13 10:48:40 +00:00
jpacold 1956220509
Move utility functions _inverse_pattern and _get_ordered_swap to Rust (#12327)
* Move utility functions _inverse_pattern and _get_ordered_swap to Rust

* fix formatting and pylint issues

* Changed input type to `PyArrayLike1<i64, AllowTypeChange>`

* Refactor `permutation.rs`, clean up imports, fix coverage error

* fix docstring for `_inverse_pattern`

Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>

* fix docstring for `_get_ordered_swap`

Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>

* remove pymodule nesting

* remove explicit `AllowTypeChange`

* Move input validation out of `_inverse_pattern` and `_get_ordered_swap`

---------

Co-authored-by: Raynel Sanchez <87539502+raynelfss@users.noreply.github.com>
2024-06-10 12:00:21 +00:00
Kevin Hartman d1c8404dca
[DAGCircuit Oxidation] Refactor bit management in `CircuitData` (#12372)
* Checkpoint before rebase.

* Refactor bit management in CircuitData.

* Revert changes not for this PR.

* Add doc comment for InstructionPacker, rename Interner::lookup.

* Add CircuitData::map_* and refactor.

* Fix merge issue.

* CircuitInstruction::new returns Self.

* Use unbind.

* Make bit types pub.

* Fix merge.
2024-06-06 20:29:23 +00:00
John Lapeyre 72ff2cf20e
Implement `num_qubits` and `num_clbits` in Rust (#12495)
* Implement num_qubits and num_clbits in Rust

* QuantumCircuit.num_qubits and num_clbits are twice as fast after
  this PR.
* These are used in several places. For example QuantumCircuit.width()
  is three times faster.
* num_qubits and num_clbits are introduced in circuit_data.rs. These
  functions are called by the corresponding Python methods.
  They are also used in circuit_data.rs itself.

* Add doc strings for rust implemented num_qubits and num_clbits

* Add doc string for `width` in Rust
2024-06-04 18:12:06 +00:00
dependabot[bot] 473c3c2e58
Bump faer from 0.18.2 to 0.19.0 (#12466)
* Bump faer from 0.18.2 to 0.19.0

Bumps [faer](https://github.com/sarah-ek/faer-rs) from 0.18.2 to 0.19.0.
- [Changelog](https://github.com/sarah-ek/faer-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sarah-ek/faer-rs/commits)

---
updated-dependencies:
- dependency-name: faer
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump faer-ext to 0.2.0 too

The faer and faer-ext versions need to be kept in sync. This commit
bumps the faer-ext version as part of the dependabot automated bump for
faer to do this.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
2024-05-28 18:12:33 +00:00
Shelly Garion 0f0a6347d0
Fix a bug in isometry.rs (#12469)
* remove assertion

* extend the test

* add release notes

* fix release notes

* Update releasenotes/notes/fix-isometry-rust-adf0eed09c6611f1.yaml

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
2024-05-28 17:59:38 +00:00
dependabot[bot] 44c0ce3686
Bump pulp from 0.18.12 to 0.18.21 (#12457)
Bumps [pulp](https://github.com/sarah-ek/pulp) from 0.18.12 to 0.18.21.
- [Commits](https://github.com/sarah-ek/pulp/commits)

---
updated-dependencies:
- dependency-name: pulp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 12:53:57 +00:00
Matthew Treinish 531f91c24b
Add `DenseLayout` trial to `SabreLayout` (#12453)
Building on the work done in #10829, #10721, and #12104 this commit adds
a new trial to all runs of `SabreLayout` that runs the dense layout
pass. In general the sabre layout algorithm starts from a random layout
and then runs a routing algorithm to permute that layout virtually where
swaps would be inserted to select a layout that would result in fewer
swaps. As was discussed in #10721 and #10829 that random starting point
is often not ideal especially for larger targets where the distance
between qubits can be quite far. Especially when the circuit qubit count
is low relative to the target's qubit count this can result it poor
layouts as the distance between the qubits is too large. In qiskit we
have an existing pass, `DenseLayout`, which tries to find the most
densely connected n qubit subgraph of a connectivity graph. This
algorithm necessarily will select a starting layout where the qubits are
near each other and for those large backends where the random starting
layout doesn't work well this can improve the output quality.

As the overhead of `DenseLayout` is quite low and the core algorithm is
written in rust already this commit adds a default trial that uses
DenseLayout as a starting point on top of the random trials (and any
input starting points). For example if the user specifies to run
SabreLayout with 20 layout trials this will run 20 random trials and
one trial with `DenseLayout` as the starting point. This is all done
directly in the sabre layout rust code for efficiency. The other
difference between the standalone `DenseLayout` pass is that in the
standalone pass a sparse matrix is built and a reverse Cuthill-McKee
permutation is run on the densest subgraph qubits to pick the final
layout. This permutation is skipped because in the case of Sabre's
use of dense layout we're relying on the sabre algorithm to perform
the permutation.

Depends on: #12104
2024-05-22 19:25:32 +00:00
Matthew Treinish f08c579ce1
Expose internal rust interface to DenseLayout (#12104)
* Expose internal rust interface to DenseLayout

This commit makes a small change to the rust code for DenseLayout that
enables calling it more easily from rust. The primary obstacle was the
pyfunction used PyReadonlyArray2<f64> inputs which precludes calling it
with rust constructed Array2Views<f64>. This adds a new inner public
function which takes the array view directly and then the pyfunction's
only job is to convert the inputs and outputs to Python. The python side
of the function is still building a sparse matrix and then runs reverse
Cuthill–McKee to get a permutation of the densest subgraph so any rust
consumers will want to keep that in mind (and maybe use sprs to do the
same).

At the same time it corrects an oversight in the original implementation
where the returned numpy arrays of the densest subgraph are copied
instead of being returned as references. This should slightly improve
performance by eliminating 3 array copies that weren't needed.

* Remove PyResult

---------

Co-authored-by: Henry Zou <87874865+henryzou50@users.noreply.github.com>
2024-05-22 16:31:43 +00:00
dependabot[bot] 9d0ae64f6d
Bump itertools from 0.12.1 to 0.13.0 (#12427)
Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.12.1 to 0.13.0.
- [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-itertools/itertools/compare/v0.12.1...v0.13.0)

---
updated-dependencies:
- dependency-name: itertools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 10:51:40 +00:00
dependabot[bot] d4522251d3
Bump pulp from 0.18.10 to 0.18.12 (#12409)
Bumps [pulp](https://github.com/sarah-ek/pulp) from 0.18.10 to 0.18.12.
- [Commits](https://github.com/sarah-ek/pulp/commits)

---
updated-dependencies:
- dependency-name: pulp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-15 13:40:38 +00:00
Jake Lishman fe69594699
Handle huge integers in OpenQASM 2 expression evaluator (#12140)
* Handle huge integers in OpenQASM 2 expression evaluator

This modifies the expression evaluator to directly parse the backing
string data of an integer token in a floating-point context, which lets
us handle numbers that would otherwise overflow a `usize`.  It's
possible for this to be totally valid, if, for example, the integer is a
multiple of some very large power of two that doesn't overflow a
double-precision float.

We already needed to immediately cast the integer to a float, so this is
just a more accurate way of doing the evaluation, and doesn't affect
when we use integers in other contexts.

* Clarify int/float split
2024-05-14 15:26:27 +00:00
Kevin Hartman 8985b24c6b
[DAGCircuit Oxidation] Port `DAGNode` to Rust (#12380)
* Checkpoint before rebase.

* [Tests passing] Port DAGNode classes to Rust.

Also has beginnings of DAGCircuit, but this is not
complete or wired up at all.

* Revert DAGCircuit stuff.

* Fix lint.

* Address review comments.

* Python lint + format

* Fix format

* Remove unnecessary state methods from CircuitInstruction pickling.
2024-05-14 09:41:49 +00:00
Matthew Treinish c062dd6cf2
Fix Rustfmt and clippy with latest rust stable (#12339)
* Fix Rustfmt and clippy with latest rust stable

Running `cargo fmt` with a newer version of rust than what we use in CI
(1.77.2 and 1.78.0 locally for me) is triggering the formatting updates
in this commit. To ensure developers don't have to worry about commiting
an accidental formatting change in their commits this commit proactively
makes the change. Similarly the recent Rust 1.78 release included new
clippy rules which are flagging some small issues that our MSRV of
clippy doesn't have. This commit also fixes these as the suggestions
are good and are compatible with our MSRV of 1.70.

* Rename deprecated config file name

* Remove dead code
2024-05-06 19:08:19 +00:00
John Lapeyre 68f4b52894
Adapt crates/qasm3 to work with recent versions of openqasm3_parser (#12087)
* Adapt crates/qasm3 to work with recent versions of openqasm3_parser

This commit adds no new features or capabilities to the importer. But it brings
the importer up to date with the latest version of openqasm3_parser as a preliminary
step in improving the importer.

The biggest change in openqasm3_parser is in handling stdgates.inc.  Upon encountering
`include "stdgates.inc" openqasm3_parser reads no file, but rather adds symbols to the
symbol table for gates in the standard library.

The function `convert_asg` in the importer calls oq3_semantics:🔣:SymbolTable.gates
which returns a `Vec` of information about each "declared" gate. The information is the
gate's name and signature and SymbolID, which is sufficient to do everything the importer
could do before this commit.

Encountering `Stmt::GateDefinition` now is a no-op rather than an error.  (This was
previously called `Stmt::GateDeclaration`, but importantly it is really a definition.)

How the standard library, and gates in general, are handled will continue to evolve.

A behavioral difference between this commit and its parent: Before if the importer
encountered a gate call before the corresponding definition an error would be raised. With
the current commit, the importer behaves as if all gate definitions were moved to the top
of the OQ3 program. However, the error will still be found by the parser so that the
importer never will begin processing statements.

The importer depends on a particular branch of a copy of openqasm3_parser. When
the commit is ready to merge, we will release a version of openqasm3_parser and
depend instead on that release.

See https://github.com/openqasm/openqasm/pull/517

* Remove unnecessary conversion `name.to_string()`

Response to reviewer comment https://github.com/Qiskit/qiskit/pull/12087/files#r1586949717

* Remove check for U gate in map_gate_ids

* This requires modifying the external parser crate.
* Depend temporarily on the branch of the parser with this modification.
* Make another change required by other upstream improvments.
* Cargo config files are changed because of above changes.

* Return error returned by map_gate_ids in convert_asg

Previously this error was ignored. This would almost certainly cause
an error later. But better to do it at the correct place.

* Remove superfluous call to `iter()`

* Depend on published oq3_semantics 0.6.0

* Fix cargo lock file

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
2024-05-03 13:49:35 +00:00
Jake Lishman 6b73b58550
Support `Var` in circuit-substitution methods (#12215)
* Support `Var` in `QuantumCircuit.compose`

This converts the operation-rewriting step of `QuantumCircuit.compose`
into one that can recurse through control-flow operations rewriting
variables (to avoid conflicts). This initial commit adds two ways of
combining the variables:

1. variables in the `other` are disjoint from those in `self`, and are
   simply added to them.  This makes it easy to join unrelated circuits.
2. variables marked as "captures" in `other` can be inlined onto
   existing variables in `self`.  This makes it possible to build up a
   circuit with variables layer-by-layer.

In support of objective 2, I also taught `copy_empty_like` a way to
produce a new base layer with all the declared variables converted to
"captures" to make it easier to produce new base layers.

I deliberately did not include any _automatic_ variable renaming because
the usability of that seemed very hard to do well; while the circuit can
easily be created in a unique way, the user would then be hard-pressed
to actually retrieve the new `Var` nodes afterwards.  Asking the user to
manually break naming collisions guarantees that they'll be able to find
their variables again afterwards.

* Support `Var` in `DAGCircuit.compose`

This similarly adds support for a `vars_mode` argument to
`DAGCircuit.copy_empty_like` to make using this more convenient.  It
threads the same argument through some of the `DAGCircuit` methods that
build up layers of DAGs, since this is more common here.

Unlike `QuantumCircuit.compose`, `DAGCircuit.compose` does not (yet?)
offer the ability to remap variables during the composition, because the
use-cases for direct `DAGCircuit` composition are typically less about
building up many circuits from scratch and more about rebuilding a DAG
from itself.  Not offering the option makes it simpler to implement.

* Support `Var` in `DAGCircuit.replace_block_with_op`

This is straightforwards, since the wire structure is the same; there's
not actually any changes needed except for a minor comment explaining
that it works automatically.

* Support `Var` in `DAGCircuit.substitute_node_with_dag`

This is marginally trickier, and to avoid encoding performance problems
for ourselves in the public API, we want to avoid any requirement for
ourselves to recurse.  The expectation is that use-cases of this will be
building the replacement DAG themselves, where it's easy for them to
arrange for the `Var`s to be the correct ones immediately.

This also allows nice things like substitutions that contract wire use
out completely, over all wire types, not just qubits.

* Support `Var` in `DAGCircuit.substitute_node`

The easiest way to do this is actually to simplify the code a whole
bunch using the wire helper methods.  It would have been automatically
supported, had those methods already been in use.

* Increase test coverage
2024-05-01 20:12:26 +00:00
Matthew Treinish febc16cb43
Oxidize the numeric code in the Isometry gate class (#12197)
* Oxidize the numeric code in the Isometry gate class

This commit ports the numeric portion of the Isometry gate class to
rust. While this will likely improve the performance slightly this move
is more to make isolate this code from blas/lapack in numpy. We're
hitting some stability issues on arm64 mac in CI and moving this code to
rust should hopefully fix this issue. As this is more for functional
reasons no real performance tuning was done on this port, there are
likely several opportunities to improve the runtime performance of the
code.

* Remove unused import

* Use rust impl for small utility functions too

* Oxidize the linalg in UCGate too

The UCGate class is used almost exclusively by the Isometry class to
build up the definition of the isometry circuit. There were also some
linear algebra inside the function which could also be the source of the
stability issues we were seeing on arm64. This commit ports this
function as part of the larger isometry migration.

* Migrate another numeric helper method of UCGate

* Remove now unused code paths

* Remove bitstring usage with bitwise ops

This commit removes the use of bit string manipulations that were
faithfully ported from the original python logic (but left a bad taste
in my mouth) into more efficient bitwise operations (which were
possible in the original python too).

* Mostly replace Vec<u8> usage with bitwise operations

The use of intermediate Vec<u8> as proxy bitstrings was originally
ported nearly exactly from the python implementation. But since
everything is working now this commit switches to use bitwise operations
where it makes sense as this will be more efficient.

* Apply suggestions from code review

Co-authored-by: Jake Lishman <jake@binhbar.com>

* Remove python side call sites

* Fix integer typing in uc_gate.rs

* Simplify basis state bitshift loop logic

* Build set of control labels outside construct_basis_states

* Use 2 element array for reverse_qubit_state

* Micro optimize reverse_qubit_state

* Use 1d numpy arrays for diagonal inputs

* Fix lint

* Update crates/accelerate/src/isometry.rs

Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>

* Add back sqrt() accidentally removed by inline suggestion

* Use a constant for rz pi/2 elements

---------

Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
2024-04-30 21:28:46 +00:00
Jake Lishman d084aebfe0
Add Rust-based `SparsePauliOp.to_matrix` and Miri tests (#11388)
* Add Rust-based `SparsePauliOp.to_matrix`

This rewrites the numerical version of `SparsePauliOp.to_matrix` to be
written in parallelised Rust, building up the matrices row-by-row rather
than converting each contained operator to a matrix individually and
summing them.

The new algorithms are complete row-based, which is embarrassingly
parallel for dense matrices, and parallelisable with additional copies
and cumulative sums in the CSR case.

The two new algorithms are an asymptotic complexity improvement for both
dense and sparse matrices over the "sum the individual matrices"
version.  In the dense case, the cost goes from

        O(4 ** num_qubits * num_ops)

to

        O(4 ** num_qubits + (2 ** num_qubits) * reduced_num_ops)

where the first term is from the zeroing of the matrix, and the second
is from updating the elements in-place.  `reduced_num_ops` is the number
of explicitly stored operations after Pauli-operator uniqueness
compaction, so is upper-bounded as `4 ** num_qubits`.  (The Pauli
compaction goes as `O(num_ops)`, so is irrelevant to the complexity
discussion.) The CSR form of the algorithm goes as

        O(2 ** num_qubits * reduced_num_ops * lg(reduced_num_ops))

which (I think! - I didn't fully calculate it) is asymptotically the
same as before, but in practice the constant factors and intermediate
memory use are *dramatically* reduced, and the new algorithm is
threadable with an additional `O(2 ** num_qubits * reduced_num_ops)`
intermediate memory overhead (the serial form has only
`O(reduced_num_ops)` memory overhead).

The `object`-coefficients form is left as-is to avoid exploding the
complexity in Rust space; these objects are already slow and unsuited
for high-performance code, so the effects should be minimal.

* Add non-blocking Miri to CI

As we begin to include more `unsafe` code in the Rust-accelerated
components, it is becoming more important for us to test these in an
undefined-behaviour sanitiser.  This is done in a separate CI job
because:

- we do not yet know how stable Miri will be, so we don't want to block
  on it.

- some dependencies need their version-resolution patching to
  Miri-compatible versions, but we want to run our regular test suites
  with the same versions of packages we will be building against.

* Parallelise cumulative nnz sum

This parallelises the previously serial-only cumulative sum of the
`indptr` array of number of non-zero entries at the end.  In practice, I
didn't actually see any change in performance from this, but
philosophically it feels like the right thing to do.

* Update Miri pin to later version of crossbeam-epohc

* Improve error handling and messages

* Simplify unnecessary match

* Add link to environment variable configuration

* Add link to Rayon plumbing README

* Add explicit test of serial and parallel modes
2024-04-26 15:30:07 +00:00
Jake Lishman 136548c9d0
Fix pickling of `NLayout` (#12298)
Previously the module of this was set incorrectly (stemming from its
move in gh-9064), at which point the `__getstate__`/`__setstate__`
pickling wouldn't work correctly any more.  Also, however, there was no
`__getnewargs__` and `new` didn't have a zero-argument form, so this
wouldn't have worked either.
2024-04-25 21:45:10 +00:00
Jake Lishman 5f535242ff
Refactor Rust crates to build a single extension module (#12134)
* Refactor Rust crates to build a single extension module

Previously we were building three different Python extension modules out
of Rust space.  This was convenient for logical separation of the code,
and for making the incremental compilations of the smaller crates
faster, but had the disadvantage that `qasm2` and `qasm3` couldn't
access the new circuit data structures directly from Rust space and had
to go via Python.

This modifies the crate structure to put the Rust-space acceleration
logic into crates that we only build as Rust libraries, then adds
another (`pyext`) crate to be the only that that actually builds as
shared Python C extension.  This then lets the Rust crates interact with
each other (and the Rust crates still contain PyO3 Python-binding logic
internally) and accept and output each others' Python types.

The one Python extension is still called `qiskit._accelerate`, but it's
built by the Rust crate `qiskit-pyext`.  This necessitated some further
changes, since `qiskit._accelerate` now contains acccelerators for lots
of parts of the Qiskit package hierarchy, but needs to have a single
low-level place to initialise itself:

- The circuit logic `circuit` is separated out into its own separate
  crate so that this can form the lowest part of the Rust hierarchy.
  This is done so that `accelerate` with its grab-bag of accelerators
  from all over the place does not need to be the lowest part of the
  stack.  Over time, it's likely that everything will start touching
  `circuit` anyway.

- `qiskit._qasm2` and `qiskit._qasm3` respectively became
  `qiskit._accelerate.qasm2` and `qiskit._accelerate.qasm3`, since they
  no longer get their own extension modules.

- `qasm3` no longer stores a Python object on itself during module
  initialisation that depended on `qiskit.circuit.library` to create.
  Now, the Python-space `qiskit.qasm3` does that and the `qasm3` crate
  just retrieves that at Python runtime, since that crate requires
  Qiskit to be importable anyway.

* Fix and document Rust test harness

* Fix new clippy complaints

These don't appear to be new from this patch series, but changing the
access modifiers on some of the crates seems to make clippy complain
more vociferously about some things.

* Fix pylint import order

* Remove erroneous comment

* Fix typos

Co-authored-by: Kevin Hartman <kevin@hart.mn>

* Comment on `extension-module`

* Unify naming of `qiskit-pyext`

* Remove out-of-date advice on starting new crates

---------

Co-authored-by: Kevin Hartman <kevin@hart.mn>
2024-04-17 19:52:07 +00:00
Luciano Bello 46b12c5535
follow up to 12121: empty_bound instead of empty (#12188) 2024-04-16 13:32:26 +00:00
Matthew Treinish de4b5a21c5
Bump faer to latest 0.18.x release (#12184)
This commit bumps the faer version used to the latest release 0.18.x.
There were some changes to the package structure in 0.18 which reduced
the number of crates used to build faer as it's now a flatter project.
However, the converter to ndarray is now in a seperate faer-ext crate
which is added to the dependencies list.
2024-04-16 12:54:09 +00:00
dependabot[bot] 9422492991
Bump pulp from 0.18.9 to 0.18.10 (#12182)
Bumps [pulp](https://github.com/sarah-ek/pulp) from 0.18.9 to 0.18.10.
- [Commits](https://github.com/sarah-ek/pulp/commits)

---
updated-dependencies:
- dependency-name: pulp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-15 12:29:10 +00:00
Jake Lishman eed53888df
Fix RNG-compatibility of Sabre for large sizes (#12172)
The recent Sabre refactor (gh-11977, 3af3cf588) inadvertently switched
the order that physical qubits were considered when modifying the front
layer after a swap insertion. This could occasionally have an impact in
the swap-chooser and extended-set population, if a swap enabled two
separate gates at once.
2024-04-12 14:25:57 +00:00
Jake Lishman 3af3cf5880
Refactor Sabre to an explicitly stateful router (#11977)
This commit is an overdue tidy up of the Sabre code, which had been
through a few growth spurts with the addition of the combined
layout-and-routing pass in Rust, and the support for control-flow
operations and directives. I have a few things I'd like to try with
Sabre, and the code was getting quite unwieldy to modify and extend.

This refactors the Sabre routing internals, encapsulating a "routing
target" into a single view object that is used to define the hardware
target, and the stateful components of the routing algorithm into a
formal `RoutingState` object.  The functions that build up the routing
algorithm then become stateful instance methods, avoiding needing to
pass many things through several internal function calls.

In addition to the non-trivial lines-of-code savings, this also made it
clearer to me (while doing the refactor) that routing-state methods were
not all really at similar levels of abstraction, meaning that things
like the escape-valve mechanism took up oversized space in the
description of the main algorithm, and the control-flow block handling
was not as neatly split from the rest of the logic as it could have
been.  This reorganises some of the methods to make the important
components of the algorithms clearer; the top level of the algorithm now
fits on one screen.

Lastly, this moves both layout and routing into a unified `sabre`
module, mostly just to simplify all the `use` statements and to put
logically grouped code in the same place.
2024-04-11 18:22:31 +00:00
dependabot[bot] 9ed963f1aa
Bump ahash from 0.8.6 to 0.8.11 (#12154)
Bumps [ahash](https://github.com/tkaitchuck/ahash) from 0.8.6 to 0.8.11.
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits/v0.8.11)

---
updated-dependencies:
- dependency-name: ahash
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
2024-04-08 09:59:38 +00:00
Kevin Hartman d76e53a548
Migrate to PyO3 0.21's Bounds API (#12121)
* Update cargo version, pyo3 + numpy.

* Get Rust compiling with deprecated usage.

* Update to (|in)to_pyarray_bound.

* Eliminate other array warnings.:

* Disable gil-refs feature.

* Fixes for strings.

* Resolve qasm2 warnings.

* Resolve qasm3 warnings.

* Resolve _accelerate errors, pt. 1.

* Pt2.

* Use proper loop.

* Avoid extra bind in _legacy_format.
2024-04-03 16:59:28 +00:00
Matthew Treinish b9ee758904
Oxidize two qubit basis decomposer (#12010)
* Oxidize TwoQubitBasisDecomposer

This commit is the second part of migrating the default 2q unitary
synthesis method to leverage parallel rust as described in #8774. The
Eventual goal is to be able to run unitary synthesis in parallel for all
the unitary matrices in a single call from the `UnitarySynthesis` pass.
The TwoQubitBasisDecomposer class is one of the default decomposers used
by the unitary synthesis plugin. After this we can build an interface
that will run the decomposition in parallel for a given decomposer.

This commit re-implements the TwoQubitBasisDecomposer class in rust. It
keeps the same algorithm from the previous python version but implements
it in rust. This builds off of #11946 and for the operation of the
decomposer class the TwoQubitWeylDecomposition class is used solely
through rust.

This commit depends on #11946 and will need to be rebased after #11946
is merged.

Fixes #12004

* Fix errors after rebase

* Fix traces method

* Fix pulse optimized synthesis

* Add release notes

* Fix lint

* Use consts for static decomposition arrays

* Run cargo fmt

* Handle basis_fidelity inside unitary synthesis path

* Cast input to TwoQubitBasisDecomposer.num_basis_gates

* Use statics instead of consts

* Pre-allocate 2q circuit sequence outside the pulse optimal path.
2024-03-28 16:07:22 +00:00
dependabot[bot] 81d133af2d
Bump rayon from 1.9.0 to 1.10.0 (#12077)
Bumps [rayon](https://github.com/rayon-rs/rayon) from 1.9.0 to 1.10.0.
- [Changelog](https://github.com/rayon-rs/rayon/blob/main/RELEASES.md)
- [Commits](https://github.com/rayon-rs/rayon/compare/rayon-core-v1.9.0...rayon-core-v1.10.0)

---
updated-dependencies:
- dependency-name: rayon
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 13:18:16 +00:00