Skip to content

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. Raising it lets the state carry more entanglement before truncation, at a cost that grows steeply; lowering it truncates earlier and lowers the reported fidelity.

256
entdim int

Maximum bond dimension of the MPO that gates are fused into between state updates. Default 16. Larger values batch more gates per update. A gate whose operator rank exceeds entdim raises rather than being applied at reduced accuracy, so raise entdim if a circuit reports that.

16
sv_cutoff float | None

Singular-value floor applied when an MPO is compressed into the state. None (default) uses the library default 1e-7. Lower it toward machine precision for accuracy, raise it for speed.

None
mpo_cutoff float | None

Singular-value floor applied while gates are fused into the MPO. None (default) uses the library default 1e-15, which is essentially exact. Independent of sv_cutoff; there is rarely a reason to change it.

None
algorithm Algorithm

How each fused MPO is applied to the state. "vmpoa" (default) and "vmpob" run single- and two-site variational sweeps seeded by a zip-up; "dmpo" is the bare zip-up, roughly 2× faster and markedly less accurate. On a 16-qubit brick-layer at bonddim=64 the variational sweep is worth about 4× in fidelity. The default matches MPSSim's (MPO1z), so results are comparable with the incumbent MIMIQ engine without tuning.

'vmpoa'
post_compress bool

Run the global recond and compression sweep after every MPO application. Default True. The sweep restores canonical form, which is what keeps the next zip-up's singular values equal to the physical Schmidt weights. Turning it off defers one sweep to end of circuit: faster on circuits that stay well below bonddim, but bond dimension then creeps on zip-up noise until the zipper's intermediate, which carries the MPO bond index and not the state's, crosses bonddim, and truncation in the wrong gauge corrupts the state. Measured on a 16-qubit QFT at bonddim=64: mirror fidelity 1.0 with it on, 0.535 with it off, and the reported fidelity reads 1.0 either way.

True
reorderqubits bool | str

Qubit relabelling applied in :meth:compile to bring interacting qubits closer together, which lowers bond-dimension growth. True (default) selects the greedy method; the other spellings are "greedy", "sa" / "simulated_annealing" and "multilevel". False leaves the layout alone. Samples and amplitudes are translated back to the user's qubit frame on read-out.

True
reorderqubits_alpha float

Exponent α in the reordering cost Cα(π) = Σ |π(i) − π(j)|^α · w(i, j), where w counts the gates coupling a pair. Default 3.0; higher values penalise long-range couplings harder.

3.0
seed int | None

Master RNG seed for every run this instance drives. None (default) draws fresh entropy per run. A seed= on :meth:execute overrides it.

None
buffer int

Depth of the gate-fusion pipeline. 0 (default) fuses and applies inline; a positive value runs fusion on a background thread that prepares up to buffer MPOs ahead while evolution applies them, overlapping the fusion of the next block with the application of the current one. Results are identical to buffer=0. The overlap is real parallelism because mps.apply_mpo releases the GIL, and a depth of 2 to 4 is enough because only one or two MPOs are ever in flight.

0
traversal Traversal

Order in which gates are walked while they are fused into MPOs. "sequential" (default) is the circuit's insertion order; "bfs" is a breadth-first topological order that groups mutually independent gates into layers; "dfs" is depth-first, following one dependency chain to its end before backtracking. All three produce the same simulated state and differ only in how gates batch into MPOs, which shifts the intermediate bond dimension and therefore the runtime. "bfs" tends to pack each MPO with more commuting gates, which helps on wide, shallow layers.

'sequential'
usemkl bool

Linear-algebra engine. False (default) links OpenBLAS, which the wheel vendors, so it works from a plain pip install. True links Intel MKL, whose runtime the wheel cannot bundle and must come from the environment; if it is absent, the first use raises :class:ImportError with installation instructions.

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:execute is a TensorWeaver-specific kwarg (also accepted by :class:quantanium.QuantaniumQCS); :class:mimiqengines.MPSSimulator does not expose it. Code that drives the three simulators with a portable sim.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 instance seed, which beats fresh entropy from :mod:secrets. The free function tensorweaver.execute(...) defaults to seed=42; this method resolves to a concrete int before forwarding, so the two surfaces never collide.
  • :meth:bind substitutes parameters and re-runs the full compile pipeline; there is no native parametric fast path.
  • :meth:evolve returns (state, TruncationLowerBound) and never promotes to ExactFidelity even when fid == 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 compiled is not a :class:CompiledCircuit.

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.

1000
seed int | None

Master RNG seed for this run. Overrides the instance seed. Mutually exclusive with rng.

None
rng Random | None

A :class:random.Random to draw the run's seeds from. Mutually exclusive with seed.

None
num_qubits int | None

Width of the simulated register. None (default) infers it from the circuit. This keyword is TensorWeaver-specific.

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 GateCustom blocks before evolution (the client-side FusePass). Default False. This is distinct from, and usually redundant with, the MPO fusion this simulator does internally while evolving.

False
fuse_threshold int

Minimum qubit count for fuse to act. Default 0.

0
canonicaldecompose bool

Decompose to the canonical basis before evolution. Default False.

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:compile; alternatively pass passes=PassPipeline([TwReorderQubitsPass(...)]).

False
remove_swaps bool

As reorderqubits: server-side only, raises when set locally.

False
callback object | None

Called as callback(applied, total) as the evolution progresses. total is None because MPOs are fused lazily and the count is not known up front.

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.

True
stopped object | None

Cooperative cancellation handle checked during evolution.

None
progress bool

Show a progress display. Default False.

False

Returns:

Name Type Description
A QCSResults | list[QCSResults]

class:QCSResults, or a list of them when circuit is a list

QCSResults | list[QCSResults]

or param_grid is given. cstates are always

QCSResults | list[QCSResults]

class:BitString, in both sampling and trajectory mode.

Raises:

Type Description
TypeError

if both seed and rng are given.

ValueError

if both passes and the shorthands are given.

NotImplementedError

if reorderqubits or remove_swaps is set on this call.

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 rng and seed are given.

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 op, which means the circuit cannot be lowered onto this basis.


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