# Providers

Every entry point that builds a circuit accepts a `provider=` argument, in the same three forms: a string (a registered name), a configuration dataclass, or a backend instance. The same circuit can run on any backend without changes.

```python
from eigenkit import Circuit, PennyLaneConfig

# String: registered name lookup.
Circuit(blocks=..., provider="pennylane")

# Config: routes to the matching backend via `make_backend()`.
Circuit(blocks=..., provider=PennyLaneConfig(device_name="lightning.qubit"))

# Backend instance: used directly.
from eigenkit import CudaQuantumBackend, register

Circuit(blocks=..., provider=CudaQuantumBackend())

# Or register it once under a name, then use the name anywhere.
register("cudaq", CudaQuantumBackend())
Circuit(blocks=..., provider="cudaq")
```

The built-in **NumPy** simulator is the default (`provider="numpy"`), and it is always available, with no extra. PennyLane, Qiskit, Braket, IQM, TensorCircuit, Qulacs and qsim register their names automatically once their extras are installed. CUDA Quantum and Qiskit Runtime do not register a name by themselves: pass an instance as `provider=`, or import the backend and call `register()`. A `QiskitRuntimeConfig` passed as `provider=` does not need registration either.

Naming a backend whose package is not installed raises an `ImportError`, which tells you which extra to install. The name stays registered, so once the extra is installed, the same process finds it, without a restart:

```text
ImportError: provider 'pennylane' is registered but its package is not
installed (install with `pip install eigenkit[pennylane]`).
```

A name that the library does not know at all raises a `KeyError` instead, and lists the names that it knows. These are two different problems, and the two messages keep them apart.

## What "faster" is measured against

When these docs call a backend *fast* or *faster* without naming a baseline, the comparison is with the built-in **NumPy** reference simulator. This is the default `provider="numpy"`, run on the central processing unit (CPU), analytically (`shots=None`) and in double precision. That simulator is written to be readable, and it is not tuned, which is what makes it the zero point. "Faster than NumPy" says that a backend is worth installing for a given workload. It does not say that the backend beats every other backend.

The batching table further down uses a **different** baseline, and its heading says so. It compares the native batched call of a backend with the library's own Python loop over the samples, *on that same backend*. The speedup of about `30×` given for NumPy there is that same comparison between the loop and the batch, not a comparison between backends.

All these figures are rough expectations from development runs, not published benchmarks with fixed hardware and versions. Time your own circuit before you choose a backend for its speed.

## Backend matrix

| Backend               | Registration                                    | Gradients                           | Native batching         | Notes                                                                                                                                                                                                                                                     |
| --------------------- | ----------------------------------------------- | ----------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NumPy                 | Built in (`"numpy"`).                           | Adjoint.                            | Yes, vectorised.        | **The default.** The reference statevector simulator, with no extra dependencies.                                                                                                                                                                         |
| PennyLane             | Lazy (`"pennylane"`).                           | Native.                             | Yes.                    | Any PennyLane device, through `PennyLaneConfig`. It needs the `pennylane` extra.                                                                                                                                                                          |
| Qiskit                | Lazy (`"qiskit"`).                              | Parameter shift.                    | No, it loops.           | A statevector simulator. Finite shots are not supported yet, and any value other than `shots=None` raises an error.                                                                                                                                       |
| Braket (local)        | Lazy (`"braket"`).                              | Parameter shift.                    | No, it loops.           | `LocalSimulator`.                                                                                                                                                                                                                                         |
| Braket (cloud or QPU) | The same backend, chosen by the configuration.  | Parameter shift, or none.           | No, it loops.           | `BraketConfig(device_arn=...)`. On a quantum processing unit (QPU), gradients are turned off unless `enable_gradients=True`, and `shots > 0` is required.                                                                                                 |
| Qiskit Runtime        | On request (`register("qiskit-runtime", ...)`). | None, or parameter shift.           | Yes.                    | IBM Eagle and Heron devices, and the fake backends. Gradients only with `enable_gradients=True`.                                                                                                                                                          |
| IQM                   | Lazy (`"iqm"`).                                 | None, or parameter shift.           | No, one job per sample. | IQM Resonance through iqm-client, and the fake backends of IQM, which model its noise. The hardware returns only counts, so every value is computed from histograms of bitstrings. Gradients only with `enable_gradients=True`. It needs the `iqm` extra. |
| CUDA Quantum          | On request (`register("cudaq", ...)`).          | Parameter shift.                    | Partly.                 | The optional `cudaq` dependency. `Sum` and `Multiply` expressions are not supported.                                                                                                                                                                      |
| TensorCircuit         | Lazy (`"tensorcircuit"`).                       | Automatic differentiation with JAX. | Yes, with `jax.vmap`.   | A tensor-network simulator, through tensorcircuit-ng on JAX. It needs the `tensorcircuit` extra. It is best for workloads that are run many times (see the note below).                                                                                   |
| Qulacs                | Lazy (`"qulacs"`).                              | Adjoint.                            | No, it loops.           | A fast statevector simulator written in C++. It has a native reverse-mode gradient through `backprop`, and it supports the full set of gates. It needs the `qulacs` extra.                                                                                |
| Qiskit Aer            | Lazy (`"qiskit-aer"`).                          | Parameter shift.                    | No, it loops.           | The dense statevector core of Aer. It comes with the `qiskit` extra, so it adds no dependency.                                                                                                                                                            |
| Qiskit Aer MPS        | Lazy (`"qiskit-aer-mps"`).                      | Parameter shift.                    | No, it loops.           | The same backend, with `method="matrix_product_state"`. It is exact when the bond dimension is not limited. It is the natural point of comparison for a simulation based on the time-evolving block decimation (TEBD) algorithm.                          |
| qsim                  | Lazy (`"qsim"`).                                | Parameter shift.                    | No, it loops.           | The qsim simulator of Google, through Cirq. It works in **single precision** (`float32`), so it is fast but has a residual error of about `1e-6`. It needs the `qsim` extra.                                                                              |

## NumPy (built in)

This is the default: a reference statevector simulator in pure NumPy, with no extra dependencies, so that an install with no extra can run circuits immediately:

```python
import numpy as np
from eigenkit import Circuit, Encoding, Variational, all_z

circuit = Circuit(
    blocks=[Encoding(in_features=2), Variational(depth=1)],
    observables=all_z(2),
)  # provider="numpy", interface="numpy" by default
circuit(np.zeros(circuit.spec.n_weights), np.array([0.3, -0.2]))
```

Gradients use the analytic **adjoint** method, which is exact and costs `O(1)` in the number of parameters on statevector simulators. The simulator takes the simple speed gains that NumPy allows. A batch of inputs evolves in one vectorised sweep, with a leading batch axis on the state tensor, which is about `30×` faster than a loop over the samples with a batch of `64`. A CNOT is applied as a swap of amplitudes (`np.flip`), not as a matrix product. It is still the readable reference and not a tuned simulator, and it is the baseline of every "faster" claim in these docs. Install `pennylane` for the fast path. The forward values and the gradients agree with PennyLane to machine precision.

## PennyLane

```python
from eigenkit import Circuit, PennyLaneConfig

config = PennyLaneConfig(device_name="lightning.qubit", shots=None)
Circuit(blocks=..., provider=config)
```

`device_name` is the identifier of any PennyLane device. `shots=None` evaluates the circuit analytically. The PyTorch interface of PennyLane computes gradients natively.

## Qiskit

```python
from eigenkit import Circuit, QiskitConfig

config = QiskitConfig(shots=None)
Circuit(blocks=..., provider=config)
```

The backend builds a parametric `QuantumCircuit` once. Each forward pass binds the parameters with `assign_parameters` and computes the expectation values with `Statevector`. Gradients use the parameter-shift rule.

## Braket

`BraketConfig` chooses between the local simulator, a cloud simulator and a QPU, based on `device_arn`:

```python
from eigenkit import BraketConfig

# Local (default).
local = BraketConfig()

# Cloud simulator (SV1).
sv1 = BraketConfig(
    device_arn="arn:aws:braket:::device/quantum-simulator/amazon/sv1",
    shots=1000,
)

# QPU (gradients disabled unless enable_gradients=True, shots > 0 enforced).
qpu = BraketConfig(
    device_arn="arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1",
    shots=1000,
)
```

Runs on the cloud and on a QPU issue a single `CostWarning` when the circuit is compiled. See [QPU and cloud workflows](https://docs.kit.eigenorbit.com/user-guide/qpu/index.md) for submitting without waiting and for dry runs.

Braket runs `run`, `sample`, `probabilities` and `zero_state_probability`, either waiting for the result or through `submit()`. `sample()` needs `shots > 0`. With `shots=0`, `probabilities()` and `zero_state_probability()` are exact on the local simulator, SV1 and DM1. The result type that each device uses, and the largest number of qubits for the exact results, are in the [table of Braket result types](https://docs.kit.eigenorbit.com/user-guide/qpu/#braket-shot-rules-and-result-types).

## Qiskit Runtime

This backend targets real IBM hardware, and the fake backends of `qiskit_ibm_runtime`, which model the noise of the devices. The token is looked up in this order: an explicit token, then the `QISKIT_IBM_TOKEN` environment variable, then the saved account file. `channel` defaults to `"ibm_quantum_platform"`, because the older `"ibm_quantum"` channel was retired.

```python
from eigenkit import Circuit, QiskitRuntimeConfig

config = QiskitRuntimeConfig(backend_name="ibm_fez", shots=1024)
Circuit(blocks=..., provider=config)

# Or let the service choose its least busy operational device.
config = QiskitRuntimeConfig(backend_name="least_busy", shots=1024)
```

`backend_name` is required unless `backend_instance` is given. There is no default device, because IBM retires devices. Passing the configuration does not need a `register()` call.

For tests, pass a `FakeBackendV2` directly through `backend_instance`. No authentication is needed.

`primitive="sampler"` uses `SamplerV2` in place of `EstimatorV2`, and computes the expectation values from the raw counts of bitstrings. This also makes `sample()` and `probabilities()` available. See [QPU and cloud workflows](https://docs.kit.eigenorbit.com/user-guide/qpu/index.md).

## IQM

This backend targets IQM hardware through the software of IQM itself, and not through Braket. The difference is between a bill from Amazon Web Services (AWS) and the plans of IQM, and this is the only way to use the fake backends of IQM and its Star architectures, which use MOVE gates. The token is looked up in this order: an explicit token, then the `IQM_TOKEN` environment variable, then whatever iqm-client finds by itself.

```python
from eigenkit import Circuit, IQMConfig

config = IQMConfig(
    url="https://resonance.iqm.tech/",
    quantum_computer="garnet",
    shots=2048,
)
Circuit(blocks=..., provider=config)
```

The service of IQM returns only histograms of bitstrings, so every expectation value is computed from counts, and `shots > 0` is required. For tests, pass an `IQMFakeAdonis()` or an `IQMFakeDeneb()` directly through `backend_instance`. They run locally on Aer, with a model of the noise of IQM, and they need no token and no network.

## CUDA Quantum

```python
from eigenkit import (
    Circuit,
    CudaQuantumConfig,
    CudaQuantumBackend,
    register,
)

register("cudaq", CudaQuantumBackend())
config = CudaQuantumConfig(target="nvidia", shots=None)
Circuit(blocks=..., provider=config)
```

Common targets are `"qpp-cpu"` (a statevector on the CPU, the default), `"nvidia"` (one graphics processing unit, or GPU), `"nvidia-mgpu"`, `"nvidia-mqpu"` and `"tensornet"`.

The arithmetic of CUDA Quantum on parameters (`QuakeValue`) is limited: `Sum` and `Multiply` expressions are not supported. This rules out `Reuploading(trainable_scale=True)` on CUDA Quantum.

## TensorCircuit

```python
from eigenkit import Circuit, TensorCircuitConfig

# Auto-registered once the `tensorcircuit` extra is installed.
Circuit(blocks=..., provider="tensorcircuit")

# Equivalently, via the config.
Circuit(blocks=..., provider=TensorCircuitConfig())
```

This backend simulates circuits as tensor networks, with [tensorcircuit-ng](https://github.com/tensorcircuit/tensorcircuit-ng) on the JAX backend (the `tensorcircuit` extra). Expectation values are exact contractions of the tensor network. The batch of parameters is vectorised with `jax.vmap`, and the whole forward pass and gradient are compiled with `jax.jit`. Gradients use the native reverse-mode automatic differentiation of JAX (`jax.jacrev`), exposed as the `jacobian` of the provider. So both the NumPy variational optimisation tools (VQE and QAOA through `minimize_expectation`) and the PyTorch interface use them, without the parameter-shift rule. The software is imported only when it is needed, so `import eigenkit` does not import JAX until this provider is resolved. The supported gates are `RX`, `RY`, `RZ`, `H`, `X`, `Z`, `CNOT` and `SWAP`.

**When it pays off.** The simulation is still an *exact* contraction, so what this backend gives is a constant factor, not access to larger circuits. It has a one-time compilation cost with `jax.jit` of a few seconds, which grows with the number of qubits and the size of the Hamiltonian. So it suits workloads that are **run many times** (training loops, searches over hyperparameters, VQE and QAOA with an ansatz of fixed shape), where this cost is spread over many evaluations. For single runs or exploration, the NumPy simulator is faster. The forward values and the gradients match the NumPy reference to machine precision.

## Qulacs

```python
from eigenkit import Circuit, QulacsConfig, QulacsBackend, register

register("qulacs", QulacsBackend())  # auto-registers when the extra is installed
Circuit(blocks=..., provider="qulacs")  # or provider=QulacsConfig()
```

[qulacs](https://github.com/qulacs/qulacs) is a statevector simulator with a compiled C++ core, where the NumPy reference is written in Python and NumPy. It has a **native adjoint gradient** (`ParametricQuantumCircuit.backprop`), so it declares `gradient_method="adjoint"`, like the NumPy reference simulator. One `backprop` sweep per observable gives the gradient of every gate angle in reverse mode, at a cost of `O(1)` in the number of parameters. These gradients are mapped onto the weights and the inputs with the chain factors of the intermediate representation, so `Reuploading(trainable_scale=True)` and other angles with `Scale` or `Multiply` are differentiated correctly. The forward values, the gradients, `zero_state_probability` (the primitive of quantum kernels) and the reading and writing of `statevector` all agree with the NumPy reference to machine precision.

The full set of gates is supported. Gates for which qulacs has no parametric primitive are decomposed onto parametric rotations, so that they stay differentiable: `PhaseShift` becomes `RZ`, `CRY` becomes `RY·CX·RY·CX`, and `CPHASE` becomes three `RZ` and `CX` gates. `adjoint(AmplitudeEncoding)` is not supported, as with Qiskit, because a state preparation cannot be inverted as a gate. Install it with `pip install eigenkit[qulacs]`.

## Qiskit Aer

```python
from eigenkit import Circuit, QiskitAerConfig

Circuit(blocks=..., provider="qiskit-aer")  # dense statevector core
Circuit(blocks=..., provider="qiskit-aer-mps")  # matrix-product-state core
Circuit(blocks=..., provider=QiskitAerConfig(method="matrix_product_state"))
```

[Aer](https://github.com/Qiskit/qiskit-aer) is the high-performance simulator of Qiskit. It already comes with the `qiskit` extra, so this backend adds **no new dependency**. It reuses the translation of the plain Qiskit backend without changes (the lowering of gates, the binding of symbolic `Parameter` values, and the `SparsePauliOp` observables). Only the way the circuit is executed changes: the expectation values are read through `save_expectation_value` of Aer, in place of `Statevector.from_instruction`.

Two methods are available, as two provider names. `qiskit-aer` is the dense statevector core, which is exact and matches the NumPy reference to about `1e-12`. `qiskit-aer-mps` is the matrix product state (MPS) core. It is exact when the bond dimension is not limited (the default of Aer), it is a fast approximation for circuits with little entanglement, and it is the natural point of comparison for a simulation with tensor networks. It agrees with NumPy to about `1e-9`, and the difference comes from the truncation of the singular value decomposition.

The full set of gates is supported by both. Both methods translate the circuit to the native gates of Aer first (`optimization_level=0`, with no coupling map, so no routing and no permutation of the qubits). This is needed because the MPS core rejects `cry`, and because the statevector core cannot run the controlled unitary that a `ControlledQubitUnitary` becomes. Sampling with finite shots is not supported yet, so `shots` must be `None`. Install it with `pip install eigenkit[qiskit]`.

## qsim

```python
from eigenkit import Circuit, QsimConfig

Circuit(blocks=..., provider="qsim")  # or provider=QsimConfig()
Circuit(blocks=..., provider=QsimConfig(threads=8))
```

[qsim](https://github.com/quantumlib/qsim) is the high-performance Schrödinger statevector simulator of Google, used through its `qsimcirq` bridge to Cirq. The intermediate representation is translated once into a parametrised `cirq.Circuit`, whose angles are SymPy symbols, and each call resolves the symbols and runs the circuit.

**qsim works in single precision (`float32`)**, because the pip package has no build in double precision. The values are returned as `complex128`, but they carry an accumulated error of about `1e-6`, so qsim does not pass a parity test at `1e-9`. This residual comes from the precision and is not a bug, as with the single-precision path of CUDA Quantum. The parity tests check qsim at `1e-4`. What qsim gives is speed over the NumPy reference simulator, and the residual should be reported together with any timing, not hidden.

The full set of gates of the circuit algebra is supported. The primitives that carry data (`AmplitudeEncoding`, `QubitUnitary` and `ControlledQubitUnitary`) are not, and they are rejected before the run. An `initial_state` is not supported, and passing one raises a `NotImplementedError`. The number of threads follows `OMP_NUM_THREADS` unless `QsimConfig(threads=...)` sets it, so qsim respects a benchmark setup that fixes the threads. Install it with `pip install eigenkit[qsim]`.

## Batched evaluation

Batching works on **both interfaces** and on every backend. Pass a 2-D `inputs` array of shape `(B, n_inputs)`, and you get an output of shape `(B, n_obs)`, or `(B,)` when there is a single observable. `weights` stays 1-D, because the weights are shared across the batch.

```python
import numpy as np
from eigenkit import Circuit, Encoding, Variational, all_z

# numpy interface (the default): weights are passed per call.
circuit = Circuit(
    blocks=[Encoding(in_features=4), Variational(rotation="RY", depth=2)],
    observables=all_z(4),
)
weights = np.zeros(circuit.spec.n_weights)  # or a trained vector
x_batch = np.random.uniform(0, np.pi, size=(128, 4))
y_batch = circuit(weights, x_batch)  # shape (128, 4)
```

On the PyTorch interface, the module stores the weights, so you pass only the batch:

```python
import torch
from eigenkit import Circuit, Encoding, Variational, all_z

circuit = Circuit(
    blocks=[Encoding(in_features=4), Variational(rotation="RY", depth=2)],
    observables=all_z(4),
    interface="torch",
    provider="pennylane",
)
y_batch = circuit(torch.randn(128, 4, dtype=torch.float64))  # shape (128, 4)
```

### What "native batching" means here

When a call has the shape of the **fast path** (`weights.ndim == 1` and `inputs.ndim == 2`), the backends with native batching send the whole batch through one batched call of the provider. The Qiskit statevector backend and the local Braket backend use the shared Python loop `batch_call`. Any other combination of shapes (batched weights, a single sample of inputs in a 2-D wrapper and so on) falls back to a loop in Python, which gives the index of a sample that fails.

The speedups below are **within one backend**: the native batched call of the backend against the library's own loop over the samples, on the same simulator. They are not comparisons between backends, and they are not measured against the NumPy reference.

| Backend                  | How the fast path works                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | Speedup over the loop on the same backend                                                                                                                     |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **NumPy**                | A leading batch axis on the state tensor, so the whole batch evolves in one sweep. The inputs are transposed to `(n_inputs, B)`, so an angle that depends on the inputs becomes a `(B,)` vector (a stack of `(B, 2, 2)` rotations), while angles that depend only on weights stay a single shared `(2, 2)` matrix. A CNOT is a swap of amplitudes with `np.flip`, not a matrix product.                                                                                                           | About `30×` over the loop with a batch of `64`.                                                                                                               |
| **PennyLane**            | Parameter broadcasting in the QNode. The `inputs` are transposed to `(n_inputs, B)`, so each `InputRef(j)` becomes a vector of shape `(B,)`, and every gate angle is broadcast through a single evaluation of the tape.                                                                                                                                                                                                                                                                           | About `B×` over the loop. On `default.qubit` with inputs of shape `(128, 4)`, the overhead of the library is at most `20%` of the plain PennyLane QNode call. |
| **Qiskit Runtime**       | The `EstimatorV2` primitive accepts a `(B, n_params)` array of parameters in each Primitive Unified Bloc (PUB), so the whole batch is sent as one job, with one PUB per observable, in place of one job per sample.                                                                                                                                                                                                                                                                               | Large. IBM Runtime is dominated by the overhead of each job, so collapsing one job per sample into one job is a big change. Check it on your own backend.     |
| **CUDA Quantum**         | `cudaq.observe(kernel, ham, *2D_args)` uses the broadcast helper of CUDA Quantum. **Limitation**: this helper is itself a Python loop for kernels built with `cudaq.make_kernel(...)`, so the cost of just-in-time compilation is not shared. The behaviour is correct, and it is the usual way to batch in CUDA Quantum, but in practice the run time is currently within about `10%` of the explicit loop. Full vectorisation would require moving the backend to `@cudaq.kernel` declarations. | About the same as the loop.                                                                                                                                   |
| **TensorCircuit**        | `jax.vmap` over the contraction of one sample, compiled with `jax.jit`, so the batch of parameters is a vectorised extra index of the tensor-network contraction.                                                                                                                                                                                                                                                                                                                                 | About `B×` once it is compiled. The one-time compilation takes seconds, grows with the number of qubits, and is spread over the loop.                         |
| **Qiskit (statevector)** | None. `Statevector.expectation_value` works on one state at a time, so the backend loops through the shared helper.                                                                                                                                                                                                                                                                                                                                                                               | None.                                                                                                                                                         |
| **Braket (local)**       | None. It calls `LocalSimulator.run` once per task. Braket has `run_batch` to submit independent tasks in parallel, but it is not used yet.                                                                                                                                                                                                                                                                                                                                                        | None.                                                                                                                                                         |
| **Qulacs**               | None. `Observable.get_expectation_value` works on one state at a time, so the backend loops through the shared helper. The gradients also loop over `backprop`, one sample at a time, and each call is fast because it runs in C++.                                                                                                                                                                                                                                                               | None.                                                                                                                                                         |

### Gradients through batched inputs

For the **backends with native automatic differentiation** (PennyLane), gradients through a 2-D `inputs` batch go through the same broadcasting as the forward pass, so the library does no extra work.

For the **backends that use the parameter-shift rule** (Qiskit, local Braket, CUDA Quantum), the backward pass of the autograd function loops over the samples. It computes the jacobian of each sample, adds them into the shared gradient of the weights, and stacks the gradients of the inputs of each sample. This loop is part of the parameter-shift rule, because each sample has its own input vector, and therefore its own shifted expectation values. The forward pass still uses the batched path of the backend. Qiskit Runtime and IQM refuse gradients (`gradient_method="none"`) unless their configuration sets `enable_gradients=True`. Then they use the same loop, and every shifted evaluation is a paid forward call.

## Registering custom configs

Use `register()` to give a configuration a name, so that you can reuse it:

```python
from eigenkit import PennyLaneConfig, register

register("lightning", PennyLaneConfig(device_name="lightning.qubit"))

Circuit(blocks=..., provider="lightning")
```

## Reusing the same circuit on another provider

`with_provider` is a method of the **PyTorch** circuit (`interface="torch"`). If you already have one, and you want the **same** `CircuitSpec` and observables on a different backend, call it instead of building the list of blocks again. The `provider` argument accepts the same three forms as `Circuit(..., provider=...)`: a registered name, a configuration with `make_backend()`, or a backend instance.

```python
import torch

from eigenkit import Circuit, Encoding, Variational, all_z, PennyLaneConfig

layer = Circuit(
    blocks=[Encoding(in_features=2), Variational(depth=1)],
    observables=all_z(2),
    provider="pennylane",
    interface="torch",
)
x = torch.randn(2, dtype=torch.float64)

layer_qiskit = layer.with_provider("qiskit")
layer_lightning = layer.with_provider(
    PennyLaneConfig(device_name="lightning.qubit"),
)
```

By default, the weights are **cloned** from the original circuit. Pass `copy_weights=False` for new random weights, or `init=...` to set the weights explicitly (it takes precedence over `copy_weights`).

## API reference

### `eigenkit.core.provider.register(name, provider_or_config)`

Register a backend, or a configuration that can build one, under `name`.

Later calls to `Circuit(..., provider=name)` then use that backend. If a configuration is passed, its `make_backend()` method is called to build the backend.

Parameters:

| Name                 | Type       | Description           | Default                                                              |
| -------------------- | ---------- | --------------------- | -------------------------------------------------------------------- |
| `name`               | `str`      | The name to register. | *required*                                                           |
| `provider_or_config` | \`Provider | object\`              | A backend instance, or a configuration with a make_backend() method. |

### `eigenkit.core.provider.registered_names()`

Return every provider name that `get` accepts, including the lazy ones.

### `eigenkit.torch.circuit.TorchCircuit.with_provider(provider, *, copy_weights=True, init=None)`

Return a new `TorchCircuit` for another `provider`.

The new circuit has the same `spec` and the same `observables` argument as this instance, and it is compiled for the given `provider`.

`provider` accepts the same forms as in `__init__()`: a registered name (a `str`), a configuration object with a `make_backend()` method (for example `PennyLaneConfig`), or a backend instance.

The gradients follow the `gradient_method` of the new backend. The forward values should match across simulators up to numerical tolerance, but not exactly.

Parameters:

| Name           | Type           | Description                                                                                                   | Default                                                                                                                       |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `provider`     | `ProviderSpec` | The backend for the new circuit.                                                                              | *required*                                                                                                                    |
| `copy_weights` | `bool`         | If True, the new circuit starts from a copy of self.weights. It is ignored when init is given. Default: True. | `True`                                                                                                                        |
| `init`         | \`Tensor       | None\`                                                                                                        | An optional weight tensor of shape (spec.n_weights,). When it is given, it takes precedence over copy_weights. Default: None. |

Returns:

| Type             | Description           |
| ---------------- | --------------------- |
| `'TorchCircuit'` | The new TorchCircuit. |

### `eigenkit.core.provider.CostWarning`

Bases: `UserWarning`

Warning issued before a submission to a paid quantum backend.

A paid backend is a quantum processing unit (QPU) or a cloud simulator that charges for use. The first compilation for such a device issues this warning, so that costs cannot build up without the user noticing.

### Config dataclasses

### `eigenkit.core.backends.numpy_backend.NumpyConfig`

Configuration for the reference NumPy simulator.

It has no settings yet. It exists so that `Circuit(provider=NumpyConfig())` works in the same way as with the configurations of the other backends.

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type               | Description                                |
| ------------------ | ------------------------------------------ |
| `'NumpySimulator'` | The NumpySimulator for this configuration. |

### `eigenkit.core.backends.pennylane_backend.PennyLaneConfig`

Device settings, used for every `qml.device()` call.

Pass it directly to `Circuit(provider=PennyLaneConfig(...))`, or pass it to `register()` under a name to reuse it.

Parameters:

| Name          | Type  | Description                                                                                                                                                                             | Default                                                                                                                           |
| ------------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `device_name` | `str` | The identifier of the PennyLane simulator plugin: "default.qubit", "lightning.qubit", "lightning.gpu", or any other installed device. Default: "default.qubit".                         | `'default.qubit'`                                                                                                                 |
| `shots`       | \`int | None\`                                                                                                                                                                                  | None computes exact expectation values, and a positive integer samples that many shots for each expectation value. Default: None. |
| `diff_method` | `str` | The PennyLane differentiation method. With "best", PennyLane chooses for each device, usually backpropagation on a simulator and the parameter-shift rule on hardware. Default: "best". | `'best'`                                                                                                                          |

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type                 | Description                                  |
| -------------------- | -------------------------------------------- |
| `'PennyLaneBackend'` | The PennyLaneBackend for this configuration. |

### `eigenkit.core.backends.qiskit_backend.QiskitConfig`

Device configuration for the Qiskit backend.

Pass it to `Circuit(provider=QiskitConfig(...))`, or register it under a name with `register()` to use it again.

Parameters:

| Name    | Type  | Description | Default                                                                                                                                                                                                                                                                                            |
| ------- | ----- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `shots` | \`int | None\`      | None computes exact expectation values with Statevector. Finite-shot sampling is not supported on this backend yet, and any other value makes the compilation raise NotImplementedError. For sampling, use the Qiskit Runtime backend, which can also run locally on a fake device. Default: None. |

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type              | Description                               |
| ----------------- | ----------------------------------------- |
| `'QiskitBackend'` | The QiskitBackend for this configuration. |

### `eigenkit.core.backends.qiskit_aer_backend.QiskitAerConfig`

Device configuration for the Qiskit Aer backend.

Parameters:

| Name     | Type  | Description                                                                                                                                                                                                                                                                                                                                                                                                                            | Default                                                                                                                                                               |
| -------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method` | `str` | The Aer simulation method. "statevector" selects the exact dense simulator. "matrix_product_state" selects the matrix product state (MPS) simulator, which is exact when the bond dimension is not bounded, and an approximation for circuits with little entanglement otherwise. The provider name "qiskit-aer-mps" is this configuration with the MPS method already set. Any other value raises ValueError. Default: "statevector". | `'statevector'`                                                                                                                                                       |
| `shots`  | \`int | None\`                                                                                                                                                                                                                                                                                                                                                                                                                                 | None returns exact expectation values. Finite-shot sampling is not supported yet, and any other value makes the compilation raise NotImplementedError. Default: None. |

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type                 | Description                                  |
| -------------------- | -------------------------------------------- |
| `'QiskitAerBackend'` | The QiskitAerBackend for this configuration. |

### `eigenkit.core.backends.braket_backend.BraketConfig`

Device configuration for the Braket backend.

Parameters:

| Name                   | Type   | Description                                                                                                                                                                                                                                                                                                                                   | Default                                                                                                                                                                                                                                                                                                                    |
| ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `device_arn`           | \`str  | None\`                                                                                                                                                                                                                                                                                                                                        | None (the default) for the local simulator, or the Amazon Resource Name (ARN) of an Amazon Web Services (AWS) device. An example for a cloud simulator is arn:aws:braket:::device/quantum-simulator/amazon/sv1. Quantum processing units (QPUs) have ARNs of the form arn:aws:braket:<region>::device/qpu/<vendor>/<name>. |
| `local_backend`        | `str`  | The LocalSimulator backend to use when device_arn is None. Common values are "braket_sv" (state vector) and "braket_dm" (density matrix).                                                                                                                                                                                                     | `'braket_sv'`                                                                                                                                                                                                                                                                                                              |
| `shots`                | `int`  | 0 means exact values (simulators only), and a positive integer turns on sampling with that number of shots. AWS QPUs require shots > 0.                                                                                                                                                                                                       | `0`                                                                                                                                                                                                                                                                                                                        |
| `s3_bucket`            | \`str  | None\`                                                                                                                                                                                                                                                                                                                                        | The Amazon Simple Storage Service (S3) bucket for the results of cloud tasks. With None, the Braket package picks the default of the account.                                                                                                                                                                              |
| `s3_prefix`            | `str`  | The key prefix inside s3_bucket.                                                                                                                                                                                                                                                                                                              | `'braket-results'`                                                                                                                                                                                                                                                                                                         |
| `poll_timeout_seconds` | `int`  | How many seconds result() waits for a submitted task.                                                                                                                                                                                                                                                                                         | `3600`                                                                                                                                                                                                                                                                                                                     |
| `enable_gradients`     | `bool` | Whether to allow parameter-shift gradients on a QPU, for PyTorch .backward(), jacobian() and gradient-based optimisers. It is off by default, because one backward pass costs at least 2 * n_weights paid tasks. When it is set, compiling for a QPU issues a CostWarning that gives this count. Simulators compute gradients in either case. | `False`                                                                                                                                                                                                                                                                                                                    |

#### `is_cloud`

Whether `device_arn` is set.

If it is, the circuit runs on Amazon Web Services (AWS), on a cloud simulator or a quantum processing unit (QPU), instead of on the local simulator.

#### `is_qpu`

Whether `device_arn` names real hardware (it contains `/qpu/`).

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type              | Description                               |
| ----------------- | ----------------------------------------- |
| `'BraketBackend'` | The BraketBackend for this configuration. |

### `eigenkit.core.backends.qiskit_runtime_backend.QiskitRuntimeConfig`

Bases: `SecretFieldsMixin`

Device configuration for the Qiskit Runtime backend.

There are two ways to choose the target backend:

- `backend_name` is looked up with `QiskitRuntimeService`. It needs credentials: a token, an environment variable or a saved account.
- `backend_instance` is a `BackendV2` that is used directly. It is useful for tests with a fake backend, or to pass any backend that is already configured.

Parameters:

| Name                   | Type        | Description                                                                                                                                                                                                                                                                                                                                                    | Default                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend_name`         | \`str       | None\`                                                                                                                                                                                                                                                                                                                                                         | The IBM backend name, for example "ibm_fez", or "least_busy" for the least busy operational device that the account can use, chosen once per compiled circuit. It is required unless backend_instance is set, and it is ignored when it is. Default: None.                                                                                                                                                                                                                                                                                                                                              |
| `backend_instance`     | `Any`       | A backend that is already configured. It takes precedence over backend_name. Default: None.                                                                                                                                                                                                                                                                    | `None`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `shots`                | `int`       | The number of shots per circuit run. Default: 1024.                                                                                                                                                                                                                                                                                                            | `1024`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `optimization_level`   | `int`       | The optimisation level passed to qiskit.transpile, from 0 to 3. Default: 1.                                                                                                                                                                                                                                                                                    | `1`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `seed_transpiler`      | \`int       | None\`                                                                                                                                                                                                                                                                                                                                                         | The seed of the random passes of the transpiler, mainly the SabreLayout and SabreSwap passes, which choose the layout and the routing. None, the default, draws a new seed for every compile, so a circuit that needs routing compiles to a different number of gates on every run. Within one compile, all the transpilations share the seed, including the shifted copies that a gradient on hardware compiles. Set it whenever two compilations must be comparable. Since compiling submits nothing, trying a few seeds and keeping the cheapest circuit is a cheap and fair way to choose a layout. |
| `primitive`            | `Primitive` | The Runtime primitive that computes the expectation values. "estimator", the default, uses EstimatorV2, with one Primitive Unified Bloc (PUB) per observable in each job. "sampler" uses SamplerV2, with one PUB per qubit-wise commuting measurement group, and reduces the raw counts locally. sample() and probabilities() use SamplerV2 with either value. | `'estimator'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `group_commuting`      | `bool`      | Whether the sampler puts qubit-wise commuting Pauli terms into shared measurement circuits. False runs one circuit per term, which runs more circuits but keeps the shot budget of each term independent. The estimator ignores it. Default: True.                                                                                                             | `True`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `token`                | \`str       | None\`                                                                                                                                                                                                                                                                                                                                                         | The token passed to QiskitRuntimeService when backend_instance is None. With None, the backend uses QISKIT_IBM_TOKEN, then the saved account file. It is secret: it is never shown by repr(), and it is never saved in .eigenkit bundles, pickles or joblib checkpoints. After a load it is None, so set QISKIT_IBM_TOKEN.                                                                                                                                                                                                                                                                              |
| `channel`              | `str`       | The service channel: "ibm_quantum_platform" (the default), "ibm_cloud" or "local". The legacy "ibm_quantum" channel was retired, and QiskitRuntimeService no longer accepts it.                                                                                                                                                                                | `'ibm_quantum_platform'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `instance`             | \`str       | None\`                                                                                                                                                                                                                                                                                                                                                         | The service instance, as a Cloud Resource Name (CRN) or a name, when one applies. Default: None.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `service_kwargs`       | `dict`      | Extra keyword arguments passed to QiskitRuntimeService, such as region, url or proxies.                                                                                                                                                                                                                                                                        | `dict()`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `poll_timeout_seconds` | `int`       | How long result() waits before it gives up, in seconds. Default: 3600.                                                                                                                                                                                                                                                                                         | `3600`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `enable_gradients`     | `bool`      | Whether to allow parameter-shift gradients on the device: PyTorch .backward(), jacobian() and gradient-based optimisers. It is off by default, because one backward pass costs at least 2 * n_weights times the jobs of a forward call. When it is on, compiling for a paid device gives a CostWarning that states this cost.                                  | `False`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

#### `__post_init__()`

Reject an unknown primitive when the configuration is built.

If the check waited for the first submission, the error would come as a confusing failure on a paid backend, after the transpilation and the cost warning.

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type                     | Description                                      |
| ------------------------ | ------------------------------------------------ |
| `'QiskitRuntimeBackend'` | The QiskitRuntimeBackend for this configuration. |

### `eigenkit.core.backends.iqm_backend.IQMConfig`

Bases: `SecretFieldsMixin`

Device configuration for the IQM backend.

There are two ways to choose a target:

- `url`, and optionally `quantum_computer`, opens an `IQMProvider` for an IQM Server. This needs a token, from `token` or from the `IQM_TOKEN` environment variable.
- `backend_instance` uses any IQM `BackendV2` directly: a fake backend for offline work, or a backend that you configured yourself. It takes precedence over `url`, and it needs no token and no network access.

Parameters:

| Name                   | Type            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Default                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`                  | \`str           | None\`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | The address of the IQM Server, for example "https://resonance.iqm.tech/". It is ignored when backend_instance is set. With None, the backend reads the address from the IQM_SERVER_URL environment variable when the circuit is compiled.                                                                                                                                                                                                                                                                                                                                                                                     |
| `quantum_computer`     | \`str           | None\`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | The machine to use when the server hosts more than one, for example "garnet". With None, the server's default is used.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `backend_instance`     | `Any`           | An IQM backend that is already configured. It takes precedence over url.                                                                                                                                                                                                                                                                                                                                                                                                                             | `None`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `shots`                | `int`           | The number of shots for each circuit run. It must be positive, because hardware cannot compute exact values.                                                                                                                                                                                                                                                                                                                                                                                         | `1024`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `optimization_level`   | `int`           | The optimisation level passed to qiskit.transpile, from 0 to 3.                                                                                                                                                                                                                                                                                                                                                                                                                                      | `1`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `seed_transpiler`      | \`int           | None\`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | The seed of the random steps of the transpiler, mainly the SabreLayout and SabreSwap passes, which choose the layout and the routing. With None, the default, a new seed is drawn for every compilation, so a circuit that needs routing compiles to a different number of gates on every run. Within one compilation, all the transpilations share the seed, including those of the shifted copies that a hardware gradient compiles. Set it whenever two compilations must be comparable. Trying a few seeds and keeping the cheapest result is a cheap and fair way to choose a layout, because compiling submits nothing. |
| `transpile_mode`       | `TranspileMode` | "parametric" transpiles once and sets the parameter values at each call. "per_call" sets the values first and transpiles at every call, which gives shallower circuits but costs one transpilation per evaluation.                                                                                                                                                                                                                                                                                   | `'parametric'`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `group_commuting`      | `bool`          | Whether to put Pauli terms that commute qubit by qubit into shared measurement circuits. With False, one circuit runs for each term: there are more jobs, but each term gets all the shots.                                                                                                                                                                                                                                                                                                          | `True`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `token`                | \`str           | None\`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | The access token for the IQM Server. It is passed on only when it is set. With None, iqm-client handles authentication on its own, from IQM_TOKEN and from its own tokens file. Do not set both token and IQM_TOKEN, because iqm-client rejects a token given in two ways at once. This field is secret: repr() never shows it, and it is never saved in .eigenkit bundles, pickles or joblib checkpoints. After a load it is None, so set IQM_TOKEN.                                                                                                                                                                         |
| `calibration_set_id`   | `Any`           | The calibration set to use, as a UUID. With None, the server's default is used.                                                                                                                                                                                                                                                                                                                                                                                                                      | `None`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `use_metrics`          | `bool`          | Whether to ask the server for the error rates of each qubit and each coupler, and load them into the InstructionProperties of the target. With False (the default of iqm-client itself), the target has no error rates, so the Qiskit layout pass does not see the noise. It then cannot prefer the better qubits, and a comparison with a backend that does have calibration data is not like for like. It costs one extra request at compile time, and it is ignored when backend_instance is set. | `False`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `provider_kwargs`      | `dict`          | Extra keyword arguments passed to IQMProvider, for example tokens_file.                                                                                                                                                                                                                                                                                                                                                                                                                              | `dict()`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `poll_timeout_seconds` | `int`           | How many seconds result() waits before giving up.                                                                                                                                                                                                                                                                                                                                                                                                                                                    | `3600`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `enable_gradients`     | `bool`          | Whether to allow parameter-shift gradients on the device, for PyTorch .backward(), jacobian() and gradient-based optimisers. It is off by default, because one backward pass runs the circuits of a forward call at least 2 * n_weights times. When it is set, compiling for a real device issues a CostWarning that gives this count.                                                                                                                                                               | `False`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

#### `__post_init__()`

Reject the settings that can never work, when the configuration is created.

If they were left to the first submission, the error would appear after the transpilation and the cost warning, which on a paid device is the wrong time to find out. Only the settings that are wrong on their own are checked here. Whether a *target* can be found depends on the environment at compile time, so `_resolve_backend` checks that.

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type           | Description                            |
| -------------- | -------------------------------------- |
| `'IQMBackend'` | The IQMBackend for this configuration. |

### `eigenkit.core.backends.cudaquantum_backend.CudaQuantumConfig`

Device configuration for the CUDA Quantum backend.

Parameters:

| Name     | Type  | Description                                                                                                                                                                                                                                                                                                           | Default                                                                                               |
| -------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `target` | `str` | The cudaq target. Common values are "qpp-cpu", a statevector simulator on the central processing unit (CPU), which is the default; "nvidia", on one graphics processing unit (GPU); "nvidia-mgpu", on several GPUs; "nvidia-mqpu", with several quantum processing units (QPUs); and "tensornet". Default: "qpp-cpu". | `'qpp-cpu'`                                                                                           |
| `shots`  | \`int | None\`                                                                                                                                                                                                                                                                                                                | None for exact expectation values, or a positive integer for a finite number of shots. Default: None. |

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type                   | Description                                    |
| ---------------------- | ---------------------------------------------- |
| `'CudaQuantumBackend'` | The CudaQuantumBackend for this configuration. |

### `eigenkit.core.backends.tensorcircuit_backend.TensorCircuitConfig`

Configuration for the tensorcircuit backend.

It has no settings yet: the contraction path is the default of tensorcircuit, and the batch axis is vectorised with `jax.vmap`. It exists for consistency with the configurations of the other backends, and so that `provider=TensorCircuitConfig()` works without a `register` call.

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type                     | Description                                      |
| ------------------------ | ------------------------------------------------ |
| `'TensorCircuitBackend'` | The TensorCircuitBackend for this configuration. |

### `eigenkit.core.backends.qulacs_backend.QulacsConfig`

Device configuration for the Qulacs backend.

The Qulacs statevector simulator for the central processing unit (CPU) needs no settings, so this configuration is currently only a marker. It makes `Circuit(provider=QulacsConfig())` select this backend, and it leaves room for future fields, for example a state on a graphics processing unit (GPU).

Pass it to `Circuit(provider=QulacsConfig())`, or pass it to `register()` under a name to reuse it.

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type              | Description                               |
| ----------------- | ----------------------------------------- |
| `'QulacsBackend'` | The QulacsBackend for this configuration. |

### `eigenkit.core.backends.qsim_backend.QsimConfig`

Device configuration for the qsim backend.

Parameters:

| Name      | Type  | Description | Default                                                                                                                                                                                                                                   |
| --------- | ----- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `threads` | \`int | None\`      | The size of the internal thread pool of qsim. None reads OMP_NUM_THREADS instead, which defaults to 1, so qsim uses one core unless you set it here or in the environment. Set it explicitly before you report any timing. Default: None. |

#### `make_backend()`

Build the backend that this configuration describes.

The provider layer calls it when a configuration is passed as `provider=`. There is no reason to call it directly.

Returns:

| Type            | Description                             |
| --------------- | --------------------------------------- |
| `'QsimBackend'` | The QsimBackend for this configuration. |
