Skip to content

Choosing an algorithm

A circuit is applied to the state in blocks: gates are fused into an operator, and the operator is applied in one call. algorithm selects how that application is carried out.

sim = tw.TwSimulator(bonddim=128, algorithm="vmpoa")

All four algorithms compute the same product. They represent it exactly when the state fits under bonddim, and they differ only in how much of it survives when it does not. So the first thing to establish is whether the ceiling binds at all: if it does not, pick on speed alone.

The names say what each one is. The letter is the method and mpo is what it applies:

Setting Stands for
"dmpo" direct MPO application
"cmpo" canonical MPO application
"vmpoa" variational MPO application, variant a
"vmpob" variational MPO application, variant b

The four

"dmpo", direct MPO application, applies the operator in a single pass over the chain. It is the cheapest per application, and it is the algorithm the reference MPS engine uses, so it is the one to choose when you want results directly comparable with MIMIQ's incumbent simulator or with a published baseline computed on it. Where the state stays under the ceiling it is exact and nothing is faster.

"cmpo", canonical MPO application, also applies the operator in a single pass, arranged so that the weight it discards is chosen against the state's own Schmidt spectrum. The name is the distinction: the truncation happens in canonical form, which is what makes those Schmidt values the right measure. It costs about what "dmpo" costs. When the ceiling binds it keeps more of the state, and it tends to leave the state narrower afterwards, which makes the gates that follow cheaper as well. It is also the accurate choice on GPU.

"vmpoa", variational MPO application variant a and the default, refines the result with single-site variational sweeps. It is the most accurate at a given bonddim on operators with long-range structure, and it costs roughly twice a single pass. It is the default because accuracy at a fixed bonddim is usually worth more than throughput: if a cheaper algorithm forces you to raise bonddim to recover the same fidelity, it was not the cheaper option.

"vmpob", variant b, refines with two-site sweeps. It converges best of the four and does the most work per sweep. Unlike the single-site variant it can widen a bond during refinement, which matters when the initial guess is too narrow to represent the answer.

Picking one

Situation Reach for
The state stays well below bonddim "dmpo" or "cmpo". Every algorithm is exact here, so take the cheapest.
A long run at a bonddim that binds "cmpo". Single-pass cost, and the narrower state it leaves compounds over the run.
Highest accuracy at a fixed bonddim "vmpoa", or "vmpob" where the operator has structure a single-site sweep converges poorly on.
Reproducing a MIMIQ or MPSSim baseline "dmpo" for the single-pass reference, "vmpoa" for the default one.
usegpu=True "cmpo". See GPU engine.
You are not sure Leave the default. Then sweep.

Deciding it by measurement

The reliable way to choose is to run the same circuit both ways and compare the observable you actually care about, not the reported fidelity.

import tensorweaver as tw

for algorithm in ("dmpo", "cmpo", "vmpoa"):
    sim = tw.TwSimulator(bonddim=64, algorithm=algorithm, seed=1)
    state, fidelity = sim.evolve(sim.zerostate(n), sim.compile(circuit))
    print(f"{algorithm:>6}  chi {state.mps.max_used_bond_dim:>4}  "
          f"fidelity {float(fidelity):.6f}")

Two columns are worth reading, not one.

The fidelity says how much weight each algorithm kept. A larger number means less was discarded.

The final bond dimension says how wide the state it produced is. This is the column that is easy to overlook and often the more useful of the two: an algorithm that finishes narrower is not only more compact, it makes every subsequent gate cheaper, and the effect compounds across a long circuit. Two algorithms can report similar fidelities and leave states of very different width.

If the two algorithms give the same answer, take the cheaper. If they disagree, the ceiling is binding and the disagreement is telling you the run is not converged. Raise bonddim until they agree, and then decide on cost.

On the GPU

A state moved onto the device runs "dmpo" and "cmpo" there. The variational algorithms run on the host, and the simulator refuses them rather than transferring the state back and forth for every application, which would cost more than the refinement saves. Between the two that do run, prefer "cmpo".

What the choice does not affect

algorithm does not change the ceiling, the cutoffs, or the layout. It changes which weight is discarded once something has to be, and nothing else. If a run is inaccurate because bonddim is far too small for the circuit, no algorithm will rescue it; see Cutoffs and bond dimension.