uniqc.simulator.mps_simulator module

Matrix-Product-State (MPS) simulator for nearest-neighbour 1D circuits.

This is a pure-NumPy MPS simulator suitable for circuits whose entanglement stays bounded by a moderate bond dimension. Compared to the C++ Simulator it trades off generality for scale: an open-boundary qubit chain at chi_max=64 and N=64 qubits is comfortably tractable here while a dense statevector at the same N is not.

When to use this simulator

  • 1D / line topology circuits where every two-qubit gate is between consecutive qubits (qubit q and qubit q+1).

  • Low-to-moderate entanglement growth (e.g. shallow brick-work, dynamical simulation of local Hamiltonians, single-excitation propagation).

  • Sampling from a chip-shaped circuit that you have already compiled into a nearest-neighbour 1D chain.

When NOT to use this simulator

  • Long-range two-qubit gates. They are refused (rather than swap-routed silently). Compile to NN first, or use the dense Simulator.

  • Circuits that need CONTROL ... ENDCONTROL blocks. Decompose to native gates first.

  • Noise simulation. The MPS path is currently noiseless; route noisy work through NoisySimulator or dummy:<platform>:<chip>.

Public API

  • MPSConfig — bond / cutoff / seed configuration.

  • MPSSimulator — front-end with the simulate_pmeasure / simulate_shots / simulate_statevector surface used elsewhere in uniqc.simulator.

The simulator does not inherit uniqc.simulator.base_simulator.BaseSimulator so as to avoid the eager C++ OpcodeSimulator import and to keep the qubit indexing 1:1 with the parsed OriginIR (no encounter-order remapping).

class uniqc.simulator.mps_simulator.MPSConfig(chi_max=64, svd_cutoff=1e-12, seed=None)[source]

Bases: object

Configuration for MPSSimulator.

Variables:
  • chi_max (int) – Maximum bond dimension after each two-qubit SVD truncation. Larger chi_max is more accurate but quadratically more memory-intensive and cubically more compute-intensive per gate.

  • svd_cutoff (float) – Singular-value cutoff (relative to the spectrum norm) below which Schmidt values are dropped even if chi_max is not yet reached.

  • seed (int | None) – Optional RNG seed used by MPSSimulator.simulate_shots().

Parameters:
chi_max: int = 64
seed: int | None = None
svd_cutoff: float = 1e-12
class uniqc.simulator.mps_simulator.MPSSimulator(config=None, *, chi_max=None, svd_cutoff=None, seed=None, available_qubits=None, available_topology=None)[source]

Bases: object

OriginIR-driven MPS simulator with the same call surface as uniqc.simulator.Simulator.

Unlike that class, this simulator:

  • is pure NumPy (no C++ extension required);

  • operates on qubits [0..n-1] exactly as written in OriginIR (no least-qubit remapping); the qubit count comes from QINIT;

  • refuses long-range two-qubit gates (use the dense simulator or compile to NN first);

  • refuses CONTROL ... ENDCONTROL blocks and DAGGER blocks around unsupported gates (the per-gate dagger flag is honoured);

  • has no noise model.

Parameters:
  • config (MPSConfig | None) – Bond / cutoff / seed configuration.

  • chi_max (int | None) – Convenience override for config.chi_max when config is not supplied.

  • svd_cutoff (float | None) – Convenience override for config.svd_cutoff.

  • seed (int | None) – Convenience override for config.seed.

  • available_qubits (list[int] | None) – Optional list of allowed qubit indices. If set, any opcode touching a qubit outside the list raises.

  • available_topology (list[list[int]] | None) – Optional list of allowed [u, v] edges. If set, NN gates that violate this list raise (this lets the same instance enforce a virtual-line / chip-shaped chain).

property max_bond: int
parser: OriginIR_BaseParser | None
property qubit_num: int
simulate_pmeasure(originir)[source]

Return exact measurement probabilities, length 2 ** k where k is the number of measured qubits (or all qubits if no MEASURE was issued).

Index convention: bit j of the integer index corresponds to the j-th measured qubit (in the order they appear in the result of _measure_order()), with qubit 0 being the LSB. This matches uniqc.simulator.Simulator.simulate_pmeasure().

For circuits with > 24 measured qubits this method raises — the dense probability vector would be infeasibly large. Use simulate_shots() instead.

Parameters:

originir (str)

Return type:

list[float]

simulate_shots(originir, shots)[source]

Sample shots measurement outcomes by per-site MPS sampling.

Returns a {int: count} dict matching uniqc.simulator.Simulator.simulate_shots(). The integer key encodes bits with the first measured qubit as the LSB.

This routes through _MPSState.sample_one() (cost O(N * chi^3) per shot) so it stays tractable for large N.

Parameters:
Return type:

dict[int, int]

simulate_statevector(originir)[source]

Materialise the full statevector. Only feasible for small n.

Parameters:

originir (str)

Return type:

ndarray

property truncation_errors: list[float]