API Reference¶
An index of the public surface. For what the knobs mean see
Concepts, for execute()'s keywords see
Circuit Execution, and for runnable code see
Examples.
Gate and operator matrix inputs
Anything taking a one- or two-qubit gate or operator (apply_gate_1q,
apply_gate_2q, expectation_1q, expectation_2q, apply_kraus_*)
accepts a numpy array of dtype complex128: (2, 2) for a 1Q gate,
(4, 4) for a 2Q gate, (n_ops, dim, dim) for a stack of Kraus operators.
On a qudit site of dimension d, the shapes are (d, d) and
(d₁·d₂, d₁·d₂).
A flat list of floats in column-major [re, im, re, im, ...] order is also
accepted, with length 8 for a 1Q gate and 32 for a 2Q gate. It is
deprecated; use numpy arrays.
Bitstring / qubit ordering
TensorWeaver is little-endian by qubit index: bitstring position i is
qubit i. This is the opposite of Qiskit's convention, so bitstrings from
mps.sample_bitstring(), mps.sample(), results.cstates, and
results.histogram() appear reversed compared to Qiskit output. The same
applies to the bitstring argument of mps.amplitude().
High-level¶
execute¶
Every keyword, with its default and when to change it, is documented in Circuit Execution.
tensorweaver.execute(circuit, nsamples=..., *, num_qubits=..., bonddim=..., entdim=..., max_bond_dim=..., sv_cutoff=..., algorithm=..., seed=..., bitstrings=..., reorderqubits=..., reorderqubits_alpha=..., fuse=..., fuse_threshold=..., canonicaldecompose=..., buffer=..., traversal=..., usemkl=...)
¶
TwSimulator¶
A reusable simulator. Configuration is fixed at construction; nsamples,
seed, and num_qubits are per call.
Bases: LocalBackend
MPS quantum circuit simulator, backed by the TensorWeaver core.
Subclasses :class:mimiqcircuits.backends.LocalBackend, so the usual
sim.execute(circuit, nsamples=..., seed=...) call works and returns a
:class:mimiqcircuits.QCSResults. :meth:capabilities lists what it can
serve.
Every knob below is set on the constructor and fixed for the life of the instance; build a new simulator to change one. Accepting them per call as well would mean distinguishing "not passed" from "passed the default" on every keyword.
Execution mode. The circuit decides, not a keyword. Trailing
measurements are split off into a classical projection and do not count.
If everything left is unitary, the state is evolved once and nsamples
bitstrings are drawn from it (sampling mode, one entry in
results.fidelities). If any surviving operation on qubits is
non-unitary (a mid-circuit Measure or Reset, a noise channel,
qubit loss), the circuit is re-evolved from scratch nsamples times
(trajectory mode, one fidelity and one cstate per trajectory).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bonddim
|
int
|
Maximum MPS bond dimension, the memory and accuracy knob.
Default |
256
|
entdim
|
int
|
Maximum bond dimension of the MPO that gates are fused into
between state updates. Default |
16
|
sv_cutoff
|
float | None
|
Singular-value floor applied when an MPO is compressed into
the state. |
None
|
mpo_cutoff
|
float | None
|
Singular-value floor applied while gates are fused into the
MPO. |
None
|
algorithm
|
Algorithm
|
How each fused MPO is applied to the state. |
'vmpoa'
|
post_compress
|
bool
|
Run the global recond and compression sweep after every
MPO application. Default |
True
|
reorderqubits
|
bool | str
|
Qubit relabelling applied in :meth: |
True
|
reorderqubits_alpha
|
float
|
Exponent α in the reordering cost
|
3.0
|
seed
|
int | None
|
Master RNG seed for every run this instance drives. |
None
|
buffer
|
int
|
Depth of the gate-fusion pipeline. |
0
|
traversal
|
Traversal
|
Order in which gates are walked while they are fused into
MPOs. |
'sequential'
|
usemkl
|
bool
|
Linear-algebra engine. |
False
|
Reordering under traversal applies only to the fusable gates between
state-reading or measuring instructions. Measurement, reset, channel,
observable (Amplitude / BondDim / SchmidtRank /
ExpectationValue), barrier and IfStatement stay put and act as
synchronisation points. Within a gate run, two gates are ordered relative
to each other only when they share a qubit.
Each engine is a separate native module, so usemkl is per instance and
an MKL and an OpenBLAS simulator can run side by side in one process. Their
objects do not interoperate: an :class:~tensorweaver.MPS,
:class:~tensorweaver.MPO, Rng or :class:~tensorweaver.TwState built
by one engine cannot be passed to a simulator or method using the other,
which raises TypeError. To carry a state across engines, round-trip it
through MPS.serialize() and MPS.deserialize(), which copies it.
Caveats
num_qubits=on :meth:executeis a TensorWeaver-specific kwarg (also accepted by :class:quantanium.QuantaniumQCS); :class:mimiqengines.MPSSimulatordoes not expose it. Code that drives the three simulators with a portablesim.execute(c, nsamples=100, seed=42)shape is unaffected.- Amplitudes requested in trajectory mode reflect the last shot's state,
not an ensemble average, whenever the circuit contains a mid-circuit
measure, reset or
IfStatement. - RNG resolution priority: a call-site
seed=beats the instanceseed, which beats fresh entropy from :mod:secrets. The free functiontensorweaver.execute(...)defaults toseed=42; this method resolves to a concrete int before forwarding, so the two surfaces never collide. - :meth:
bindsubstitutes parameters and re-runs the full compile pipeline; there is no native parametric fast path. - :meth:
evolvereturns(state, TruncationLowerBound)and never promotes toExactFidelityeven whenfid == 1.0, because each MPO application is an SVD truncation event whose fidelity is at best a lower bound.
Examples:
>>> import mimiqcircuits as mc
>>> from tensorweaver import TwSimulator
>>> sim = TwSimulator(bonddim=64)
>>> c = mc.Circuit()
>>> c.push(mc.GateH(), 0)
...
>>> c.push(mc.GateCX(), 0, 1)
...
>>> c.push(mc.Measure(), [0, 1], [0, 1])
...
>>> results = sim.execute(c, nsamples=100, seed=42)
capabilities()
¶
Capability tokens this simulator can serve.
A copy, so a caller cannot mutate the class-level set.
limits()
¶
Resource limits: the configured bonddim as max_bond_dim.
topology()
¶
Connectivity assumed by the MPS evolution: all-to-all.
Long-range gates cost more bond dimension than neighbouring ones, but no routing or SWAP insertion is required of the caller.
build_state(nq, nb=0, nz=0, **_)
¶
Allocate a fresh |0…0⟩ state on nq qubits.
The MPS is capped at this simulator's bonddim and built on this
simulator's engine, so it can only be used with this simulator.
nb and nz size the classical-bit and complex registers.
zerostate(nq, nb=0, nz=0)
¶
Back-compat alias for :meth:build_state.
evolvezerostate(circuit, *, seed=None)
¶
Evolve a fresh zero state through circuit and return it.
Returns (state, fidelity), the fidelity being a plain float
lower bound on the evolved state. This is a single evolution, so a
circuit with mid-circuit measurement or noise gives one trajectory,
not an ensemble; use :meth:execute for that.
Seed resolution: call-site seed=, then the instance seed, then
fresh cryptographic entropy from :mod:secrets.
compile(circuit)
¶
Lower circuit for the MPS evolution loop.
Populates :attr:CompileMetadata.active_qubits and, when
reorderqubits is enabled, folds an MPS-friendly qubit permutation
into the wrapped source circuit and into
:attr:CompileMetadata.qubit_permutation. Decomposition to
TensorWeaverBasis and fusion into MPOs happen later, in
:meth:evolve.
A circuit with no inter-qubit couplings to reorder passes through
untouched: the wrapped source is the input circuit itself.
default_passes()
¶
No passes run by default.
Reorder lives inside :meth:compile, so it runs whenever
reorderqubits is set without the user having to build a
:class:PassPipeline. :class:~tensorweaver.TwReorderQubitsPass is
exported as the explicit alternative: pass it through
execute(..., passes=PassPipeline([...])) to swap the reorder
strategy or to compare implementations.
expectation(state, op, *qubits)
¶
Compute ⟨ψ|op|ψ⟩ on state without mutating it.
Exact, with no sampling involved. Supports 1- and 2-qubit operators
and a :class:PauliString of any length. qubits are the 0-based
indices op acts on, in the operator's own leg order, and there
must be exactly as many as the operator has qubits.
Raises:
| Type | Description |
|---|---|
ValueError
|
if the qubit count does not match the operator, or if a dense operator acts on three or more qubits. |
evolve(state, compiled, *, rng=None, callback=None, stopped=None)
¶
Evolve state under compiled, in place.
Returns (state, TruncationLowerBound). The product of the per-step
fidelities is always wrapped as :class:TruncationLowerBound, never
collapsed to :class:ExactFidelity even at fid == 1.0, because
that scalar bounds the fidelity from below rather than claiming the
exact state was reproduced.
The state is evolved in the reordered-MPS frame, since compiled
already carries the qubit permutation :meth:compile chose, so samples
and amplitudes come back in that frame. Translation to the user frame
happens at read-out: :meth:_execute_sampling remaps the sampling
projection with the permutation on compiled.metadata.
Raises:
| Type | Description |
|---|---|
TypeError
|
if |
apply_segment(state, insts, *, rng=None)
¶
Fuse a run of loss-free instructions into MPOs and apply it.
Returns the truncation fidelity of the run. Every qubit in the run is present, so fusing it cannot bury an operation a fired loss should have dropped. The run is padded to the register width, so one that misses the high qubits still builds full-width MPOs.
apply_instruction(state, inst, *, rng=None)
¶
Apply a single instruction the driver issues around a loss boundary.
These are a reload Reset, a Check or MeasureCheck
SetBit, or a partial-loss rewrite. A multi-qubit gate has to be
fused into an MPO, so it is routed through :meth:apply_segment;
everything else applies directly to the MPS.
sample_kraus(state, channel, targets, *, rng=None)
¶
Sample one branch of a Kraus channel against the live state and apply it.
Returns (fidelity, fired_operator). The operator returned is the
original one, not a reconstruction, so a LossyOperator branch
reaches the driver with its tag intact.
execute(circuit, *, nsamples=1000, seed=None, rng=None, num_qubits=None, passes=None, fuse=False, fuse_threshold=0, canonicaldecompose=False, reorderqubits=False, remove_swaps=False, callback=None, param_grid=None, strict_pass_order=True, stopped=None, progress=False)
¶
Execute circuit and return :class:QCSResults.
The TensorWeaver configuration (bonddim, entdim, sv_cutoff,
mpo_cutoff, algorithm, post_compress, reorderqubits*,
buffer, traversal, usemkl) comes from the constructor, not
from this call. Amplitudes and expectation values are requested by
putting :class:Amplitude and :class:ExpectationValue operations in
the circuit; they write into results.zstates.
Whether the run is a single evolution plus nsamples draws, or
nsamples independent trajectories, follows from the circuit; see
the class docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
circuit
|
Circuit | list
|
One circuit, or a list of circuits to run in turn. |
required |
nsamples
|
int
|
Bitstrings to draw in sampling mode, or trajectories to
run in trajectory mode. Default |
1000
|
seed
|
int | None
|
Master RNG seed for this run. Overrides the instance
|
None
|
rng
|
Random | None
|
A :class: |
None
|
num_qubits
|
int | None
|
Width of the simulated register. |
None
|
passes
|
PassPipeline | None
|
Explicit circuit-preparation pipeline. Overrides the shorthands below, and it is an error to pass both. |
None
|
fuse
|
bool
|
Fuse runs of gates into |
False
|
fuse_threshold
|
int
|
Minimum qubit count for |
0
|
canonicaldecompose
|
bool
|
Decompose to the canonical basis before
evolution. Default |
False
|
reorderqubits
|
bool | str
|
Follows the base contract, where reordering is a
server-side pass, so setting it here raises locally. Qubit
reordering on this simulator is the constructor knob of the
same name, run natively in :meth: |
False
|
remove_swaps
|
bool
|
As |
False
|
callback
|
object | None
|
Called as |
None
|
param_grid
|
list[dict] | None
|
List of parameter dicts. Each is substituted into the circuit and executed with its own derived seed, and the return value becomes a list of results, one per grid point. |
None
|
strict_pass_order
|
bool
|
Enforce the pass pipeline's declared ordering
constraints. Default |
True
|
stopped
|
object | None
|
Cooperative cancellation handle checked during evolution. |
None
|
progress
|
bool
|
Show a progress display. Default |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
QCSResults | list[QCSResults]
|
class: |
QCSResults | list[QCSResults]
|
or |
|
QCSResults | list[QCSResults]
|
class: |
Raises:
| Type | Description |
|---|---|
TypeError
|
if both |
ValueError
|
if both |
NotImplementedError
|
if |
TwState¶
Bases: State
Composite simulation state: MPS, classical bits, and z-vars.
Subclasses :class:mimiqcircuits.backends.State. Build one with
:meth:TwSimulator.build_state or :meth:TwSimulator.evolvezerostate;
constructing it directly is for advanced use, and requires passing the
core the MPS came from.
Instructions mutate all three registers in place as a circuit is evolved:
gates and channels act on mps, measurements write into c, and the
observable operations write into z.
Attributes:
| Name | Type | Description |
|---|---|---|
mps |
PyMps
|
the tensor-network quantum register. |
c |
list[int]
|
classical-bit register. |
z |
list[complex]
|
complex z-variable register. |
classical_bits
property
¶
Live view of the classical-bit register.
complex_values
property
¶
Live view of the complex z-register.
get_loss_state()
¶
Per-qubit present/lost register.
Mutated only by the shared runtime-loss driver
(:meth:LocalBackend.evolve_with_loss), and left at all-present on
circuits without qubit loss.
amplitude(bitstring)
¶
⟨bitstring|ψ⟩. Qubit 0 is the LSB (little-endian).
bitstring is read in the same qubit frame as the underlying MPS.
Reorder passes rewrite the embedded bs of every Amplitude op
when they fire (see :func:Circuit.reorder_qubits), so a caller
issuing Amplitude(bs) from a circuit does not need to permute the
bitstring; a caller reaching into this method with a hand-built
bitstring on a reordered state does.
sample(nsamples, rng=None, *, seed=None)
¶
Sample nsamples measurement outcomes as :class:BitString\ s.
Sampling does not collapse the state, so the same state can be sampled
repeatedly. Either rng (a :class:random.Random) or seed (an
int) may be passed, but not both: the native Rng takes a single
integer, which is drawn from rng when one is given and from
:mod:secrets when neither is.
Raises:
| Type | Description |
|---|---|
TypeError
|
if both |
reset()
¶
Always raises: resetting a state in place is not supported.
Rebuilding the MPS needs the bond-dimension cap, which is simulator
configuration and not carried on the state. Call
sim.build_state(nq, nb, nz) for a fresh state instead.
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
always. |
TensorWeaverBasis¶
Bases: DecompositionBasis
Decomposition basis targeting TensorWeaver's native gate set.
Terminal operations, executed directly by TensorWeaver:
- 1Q parametric: GateRX, GateRY, GateRZ, GateU
- 1Q generic: any 1-qubit unitary gate, applied from its matrix
- 1Q identity: GateID, skipped during execution
- 2Q optimized: GateCX, GateCZ, GateISWAP
- 2Q generic: any 2-qubit unitary gate, fused into an MPO from its
matrix
- Multi-controlled: Control(n, 1Q-gate), any number of controls
- Measurement/reset: Measure, Reset, MeasureReset
- Conditional: IfStatement, terminal when its inner operation is
- Z-variable ops: Amplitude, BondDim, SchmidtRank,
VonNeumannEntropy, ExpectationValue, all of which observe the
state without changing it
- Classical: AbstractClassical logic (Not, And, Or,
Xor, ParityCheck, SetBit0/SetBit1) and the z-register
arithmetic Add, Multiply, Pow
- Noise channels: any krauschannel subclass, Kraus or mixed
unitary
- Scheduling: Barrier, a gate-fusion boundary with no effect on
the state
- Annotations: AbstractAnnotation, which carries no simulation
semantics
Anything else is decomposed through the canonical rewrite rule, which
delegates to each gate's _decompose(). A gate that neither is terminal
nor decomposes raises :class:DecompositionError.
Example
from mimiqcircuits import Circuit, GateCCX, GateH from mimiqcircuits.decomposition import decompose from tensorweaver.basis import TensorWeaverBasis c = Circuit() c.push(GateH(), 0) 1-qubit circuit with 1 instruction: └── H @ q[0]
c.push(GateCCX(), 0, 1, 2) 3-qubit circuit with 2 instructions: ├── H @ q[0] └── C₂X @ q[0:1], q[2] decomposed = decompose(c, TensorWeaverBasis()) CCX stays as Control(2, GateX), dispatched to apply_controlled_gate¶
isterminal(op)
¶
Whether op can be executed natively, without decomposing it.
decompose(op, qubits, bits, zvars)
¶
Decompose a non-terminal operation through the canonical rewrite.
Raises:
| Type | Description |
|---|---|
DecompositionError
|
if the canonical rewrite has no rule for |
Core Classes¶
MPS, MPO, and Rng are native classes. The tables below index their
methods; each method's own docstring is available with help().
MPS¶
A quantum state as a chain of tensors with bounded bond dimension.
Constructors
| Method | Description |
|---|---|
MPS.zero_state(num_qubits, max_bond_dim) |
The \|00...0⟩ state |
MPS.product_state(states, max_bond_dim) |
From a list of 0/1 values |
MPS.random_maxent_state(num_qubits, max_bond_dim, rng) |
Random maximally entangled state |
MPS.zero_state_qudits(physical_dims, max_bond_dim) |
Qudit \|0…0⟩ on sites of the given per-site dimensions (each ≥ 2) |
MPS.product_state_qudits(digits, physical_dims, max_bond_dim) |
Qudit product state from per-site levels (digits[i] < physical_dims[i]) |
MPS.deserialize(data) |
From protobuf bytes |
Sites carry any physical dimension d ≥ 2, reported per site by
mps.physical_dims. A 2×2 or 4×4 qubit gate applied to a d > 2 site acts on
the {\|0⟩, \|1⟩} subspace. See example 13.
Gate application (returns fidelity; always 1.0 for single-qubit gates)
| Method | Description |
|---|---|
mps.apply_rx(theta, qubit) |
RX rotation |
mps.apply_ry(theta, qubit) |
RY rotation |
mps.apply_rz(lmbda, qubit) |
RZ rotation |
mps.apply_u(theta, phi, lmbda, gamma, qubit) |
General U gate |
mps.apply_gate_1q(gate, qubit) |
Arbitrary 1-qubit gate |
mps.apply_gate_2q(gate, q1, q2, *, center="right") |
Arbitrary 2-qubit gate. Skips the post-application compression sweep; pair with mps.compress(). center selects which site holds the orthogonality center afterwards |
mps.apply_two_qubit_gate(...) |
Deprecated alias for apply_gate_2q; emits a DeprecationWarning |
MPO application (returns fidelity, below 1.0 when truncation discards weight)
| Method | Description |
|---|---|
mps.apply_mpo(mpo, sv_cutoff=None, algorithm=None, post_compress=True) |
Apply an operator. algorithm is "dmpo" (the default at this level), "vmpoa", or "vmpob" |
mps.apply_mpo_dmpo(mpo, sv_cutoff=None) |
Wrapper for algorithm="dmpo" |
mps.apply_mpo_vmpoa(mpo, sv_cutoff=None) |
Wrapper for algorithm="vmpoa" |
mps.apply_mpo_vmpob(mpo, sv_cutoff=None) |
Wrapper for algorithm="vmpob" |
mps.compress(sv_cutoff=None) |
Global compression sweep, restoring canonical form. None or non-positive uses the library default 1e-7 |
The default algorithm differs by level
apply_mpo defaults to "dmpo", the low-level primitive's own default.
TwSimulator and execute() default to "vmpoa", which is more accurate
at a given bond dimension. Driving the MPS yourself does not inherit the
simulator's choice.
Deferred compression
Skipping the per-call compression sweep and running one pass at a quiet point is faster for a batch of two-qubit gates:
import numpy as np
import tensorweaver as tw
mps = tw.MPS.zero_state(64, max_bond_dim=256)
mpo = tw.MPO.identity(64, max_bond_dim=16)
mpo.apply_cx(0, 1)
mpo.apply_cz(2, 3)
mps.apply_mpo(mpo, post_compress=False)
gate = np.eye(4, dtype=np.complex128) # any 4x4 unitary
mps.apply_gate_2q(gate, 4, 5)
# One sweep at quiescence: before measuring, reading an observable,
# or at the end of the circuit.
mps.compress()
Deferring the sweep leaves the state out of canonical form, so a later
truncation compares singular values that are no longer the physical Schmidt
weights. Batch only gates you know keep the bond dimension well below the cap,
and prefer "vmpoa" if unsure. See
canonical form.
Noise channels (return (fidelity, index), where index is the 0-based
sampled Kraus operator or unitary)
| Method | Description |
|---|---|
mps.apply_kraus_1q(kraus_ops, site, rng, *, validate=True) |
General 1-qubit Kraus channel |
mps.apply_kraus_2q(kraus_ops, site1, site2, rng, *, validate=True) |
General 2-qubit Kraus channel |
mps.apply_mixed_unitary_1q(unitaries, probs, site, rng, *, validate=True) |
1-qubit mixed-unitary channel |
mps.apply_mixed_unitary_2q(unitaries, probs, site1, site2, rng, *, validate=True) |
2-qubit mixed-unitary channel |
With validate=True (the default), Kraus channels check completeness
(‖Σᵢ Kᵢ† Kᵢ − I‖_F ≤ 1e-8) and mixed-unitary channels check that the
probabilities sum to 1 within 1e-8. Failures raise KrausCompletenessError.
An incomplete operator set produces a non-physical state silently, which is why
the check is on by default; validate=False is for post-selection and
projective channels, where incompleteness is intended.
Measurement and sampling
| Method | Returns |
|---|---|
mps.measure_qubit(rng, qubit) |
int, the measured bit; collapses the state |
mps.sample_bitstring(rng) |
list[int], one bitstring |
mps.sample(rng, num_samples) |
list[list[int]] |
mps.amplitude(bitstring) |
complex, ⟨bitstring\|ψ⟩ |
mps.reset_qubit(rng, qubit) |
int, the pre-reset outcome; leaves the qubit in |0⟩ |
Observables
| Method | Returns |
|---|---|
mps.expectation_1q(op, site) |
complex, ⟨ψ\|O\|ψ⟩ for a 1-qubit operator |
mps.expectation_2q(op, site1, site2) |
complex, for a 2-qubit operator |
mps.expectation_prod(ops, sites) |
complex, for a product of single-site operators |
mps.schmidt_values(bond) |
ndarray[float64], singular values at the bond, decreasing |
mps.schmidt_rank(bond, cutoff=1e-15) |
int, singular values above cutoff; minimum 1 |
mps.von_neumann_entropy(bond) |
float, S = -Σ pᵢ ln pᵢ in nats |
mps.all_entropies() |
list[float], the entropy of every interior bond |
Properties
| Property | Type |
|---|---|
mps.num_qubits |
int |
mps.physical_dims |
list[int], per-site dimension |
mps.max_bond_dim |
int, the configured cap |
mps.max_used_bond_dim |
int, the largest bond actually in use |
mps.orth_center |
int, current orthogonality center |
mps.bond_dim(i) |
int, bond dimension at cut i |
mps.all_bond_dims() |
list[int] |
mps.norm_squared() |
float |
mps.normalize() |
float, the norm before normalising |
Tensor access and copying
| Method | Description |
|---|---|
mps.tensor(site) |
ndarray[complex128] of shape (left_bond, phys, right_bond), Fortran order |
mps.set_tensor(site, arr) |
Overwrite a site tensor. Can invalidate canonical form; follow with recanonicalize() |
mps.tensor_element(site, left, phys, right) |
complex, one entry |
mps.shift_orth_center(target) |
Move the orthogonality center |
mps.recanonicalize(target=0) |
Restore canonical form with the center at target |
mps.clone_mps() |
Deep copy; copy.copy and copy.deepcopy also work |
mps.overlap(other) |
complex, ⟨ψ\|φ⟩ |
mps.fidelity(other) |
float, \|⟨ψ\|φ⟩\|² |
mps.serialize() |
bytes (protobuf) |
MPO¶
An operator as a chain of tensors, applied to a state with
mps.apply_mpo(mpo).
Constructors
| Method | Description |
|---|---|
MPO.identity(num_qubits, max_bond_dim) |
Identity operator |
MPO.identity_with_dims(physical_dims, max_bond_dim) |
Identity on sites of the given per-site dimensions (each ≥ 2) |
MPO.deserialize(data) |
From protobuf bytes |
Gate application (returns True, or False when the gate would push the
bond dimension past max_bond_dim)
Every method takes a keyword-only side selecting the physical leg the gate
multiplies into: "output" (the default) gives M' = G·M, "input" gives
M' = M·G. The two-qubit methods also take sv_cutoff.
| Method | Description |
|---|---|
mpo.apply_gate_1q(gate, site, *, side="output") |
Arbitrary 1-qubit gate |
mpo.apply_gate_2q(gate, q1, q2, *, side="output", sv_cutoff=None) |
Arbitrary 2-qubit gate |
mpo.apply_cx(control, target, *, side="output", sv_cutoff=None) |
CNOT |
mpo.apply_cz(q1, q2, *, side="output", sv_cutoff=None) |
CZ |
mpo.apply_iswap(q1, q2, *, side="output", sv_cutoff=None) |
iSWAP |
mpo.apply_rx(theta, site, *, side="output") |
RX rotation |
mpo.apply_ry(theta, site, *, side="output") |
RY rotation |
mpo.apply_rz(lmbda, site, *, side="output") |
RZ rotation |
mpo.apply_u(theta, phi, lmbda, gamma, site, *, side="output") |
General U gate |
mpo.apply_controlled_gate(unitary, controls, target, *, side="output", sv_cutoff=None) |
Multi-controlled gate, any number of controls |
Normalisation
| Method | Description |
|---|---|
mpo.ensure_operator_norm() |
Convert to operator norm (identity = δ). No-op if already there |
mpo.ensure_trace_norm() |
Convert to trace norm (Tr(A†A) = 1 per site). No-op if already there |
Properties and other methods
| Member | Description |
|---|---|
mpo.num_qubits |
int |
mpo.physical_dims |
list[int], per-site dimension |
mpo.max_bond_dim |
int, the configured cap |
mpo.max_used_bond_dim |
int, the largest bond actually in use |
mpo.bond_dim(i) |
int, bond dimension at cut i |
mpo.all_bond_dims() |
list[int] |
mpo.norm |
str, 'Operator' or 'Trace' |
mpo.tensor(site) |
ndarray[complex128] of shape (left_bond, d_in, d_out, right_bond), Fortran order |
mpo.set_tensor(site, arr) |
Overwrite a site tensor |
mpo.tensor_element(site, left, s_in, s_out, right) |
complex, one entry |
mpo.shift_orth_center(target) |
Move the orthogonality center |
mpo.clone_mpo() |
Deep copy |
mpo.dagger() |
MPO, the adjoint (the inverse for unitary operators) |
mpo.serialize() |
bytes (protobuf) |
Rng¶
A seeded generator for reproducible measurement and sampling. The same seed always produces the same sequence.
import tensorweaver as tw
mps = tw.MPS.zero_state(4, max_bond_dim=16)
rng = tw.Rng(seed=42)
bits = mps.sample_bitstring(rng)
An Rng belongs to the engine that created it and must be used with states
from that same engine.
Utility Functions¶
| Function | Description |
|---|---|
tensorweaver.optimize_ordering(pairs, num_qubits, method="greedy", alpha=1.0, seed=42, fixed_cuts=None) |
Qubit layout for a weighted interaction graph. pairs is a list of (i, j, weight); fixed_cuts lists bonds no qubit may cross. Returns (permutation, cost). Note execute() passes alpha=3.0 by default, not this function's 1.0 |
tensorweaver.extract_pairs(circuit) |
The weighted interaction graph of a circuit, as (i, j, weight) triples |
tensorweaver.reorder_qubits(circuit, perm) |
Rewrite a circuit into the layout perm |
tensorweaver.examples_dir() |
Path to the bundled example scripts |
tensorweaver.docs_dir() |
Path to the bundled documentation site |
tensorweaver.library_info() |
Build information string |
tensorweaver.rs_version() |
Version of the native core |
tensorweaver.compile_info() |
Build configuration, formatted for reading |
Instruction Dispatch¶
Applying one mimiqcircuits instruction at a time, for drivers built by hand.
| Function | Description |
|---|---|
tensorweaver.apply_instruction_mps(mps, rng, inst, cstate, zstate) |
Apply an instruction to an MPS. Returns the fidelity |
tensorweaver.apply_instruction_mpo(mpo, inst) |
Accumulate an instruction into an MPO. Returns True or False |
Exceptions¶
All inherit from TensorWeaverError.
| Exception | Raised when |
|---|---|
TensorWeaverError |
Base class for everything below |
QubitIndexError |
A qubit or site index is out of range |
BondDimensionError |
A bond dimension constraint cannot be met |
KrausCompletenessError |
A validated channel's operators do not sum to identity, or its probabilities do not sum to 1 |
GateShapeError |
A gate or operator array has the wrong shape or dtype |
SerializationError |
Protobuf encoding or decoding failed |
LicenseError |
No valid license was found |
Qiskit¶
See the Qiskit page for usage.
| Object | Description |
|---|---|
tensorweaver.qiskit.TensorWeaverBackend(**tw_options) |
A Qiskit BackendV2 backed by TwSimulator |
tensorweaver.qiskit.TensorWeaverEstimator(**tw_options) |
An EstimatorV2 reading expectation values from the MPS |