Plan Explanation
Result.explain() returns a plain-text report of how a job was planned and what happened. It is available from the native API and the command line.
An annotated report
MENOS EXECUTION REPORT
circuit qubits=4 clbits=4 operations=8 depth=3 global_phase=0
light_cone qubits 4->4 operations 8->8
candidate 0strategy=direct_dense feasible=true winner=false peak_bytes=256 work_units=224
candidate 1strategy=direct_stabilizer feasible=true winner=false peak_bytes=72 work_units=56
candidate 2strategy=direct_mps feasible=true winner=false peak_bytes=256 work_units=68
candidate 3strategy=factorized feasible=true winner=true peak_bytes=40 work_units=32
strategy factorized (exact)
region 0 qubits=[0,1] engine=stabilizer backend=cpu why="stabilizer (pauli rejected: …)"
region 1 qubits=[2,3] engine=stabilizer backend=cpu why="stabilizer (pauli rejected: …)"
estimated state_bytes=40 work_units=32
actual state_bytes=40 execute_s=0.000006 sample_s=0.000010| Line | Meaning |
|---|---|
circuit | Facts about the original circuit: qubits, classical bits, operation count, depth, global phase |
noise | channels=… readout_errors=… in the original circuit. Only present when the job contains noise (Noise Models) |
light_cone | Qubits and operations before and after light-cone reduction |
time_budget | The budget in seconds. Only present when the job set one |
candidate i | One per enumerated candidate: strategy, feasible, winner, peak bytes, work units. A refused candidate shows reason="…" instead. With a time budget each feasible one also shows est_seconds |
strategy | The chosen strategy and (exact) or (approximate) |
region i | A region's qubits, engine and backend; for factorized plans why= explains the engine choice |
cut | Present for cut_and_recombine: cuts, fragments, branches, distinct evaluations, peak bytes |
estimated | The plan's predicted bytes and work units |
replan i | Present only after a replan; see below |
actual | What was measured: bytes used, seconds executing and sampling |
expectation | The expectation value, when one was requested |
Extra detail can appear on a region line: accumulated_error_bound for an approximating MPS run, and actual_peak_bytes for a tensor-network region.
A formatting detail
Labels are padded to 11 characters. Labels that are already 11 or more characters (candidate 0, time_budget) therefore run straight into their value: candidate 0strategy=…, time_budget5 s. That is the format as shipped.
Determinism
The report is byte-identical across runs of the same job, except the two wall-clock fields, execute_s and sample_s. Estimated seconds are machine-dependent, so est_seconds and the time_budget line are printed only when a time budget was set. Without one, a report does not depend on the machine's speed.
Why losers are listed
A plan report keeps every candidate, including infeasible ones, with the reason:
candidate 0strategy=direct_dense feasible=false winner=false reason="checked_pow2: n = 100 exceeds the maximum of 62"
candidate 1strategy=direct_stabilizer feasible=false winner=false reason="operation 0 (ry) is not a Clifford gate"That is usually all you need to understand why a large job was planned the way it was.
After a replan
If a run overran its time budget and was restarted, the report gains a block before the actual line. The threshold, the observed time, the prediction, the reason and the old and new plans are all there:
replan 0 threshold=0.2 s crossed at elapsed=0.224734 s
abandoned after 194 safe boundaries on engine=mps backend=cpu
was strategy=direct_mps predicted=0.000835369 s
reason="observed runtime exceeded the time budget; mps on cpu is excluded by an observed floor of 0.224734 s"
now strategy=direct_denseThis is real output from the replanning example. A run that never replans produces a report with no such block, byte-identical to one produced without a budget apart from the budget lines. See Replanning.
Reading it from Python
explain() returns a string. To pick out a value, search for the line you want:
from menos import Circuit, Opcode, RunOptions, run
circuit = Circuit(2, 2)
circuit.append(Opcode.H, [0])
circuit.append(Opcode.CX, [0, 1])
circuit.append_measure(0, 0)
circuit.append_measure(1, 1)
options = RunOptions()
options.shots = 10
options.seed = 1
report = run(circuit, options).explain()
strategy = next(line for line in report.splitlines() if line.startswith("strategy"))
print(strategy)
assert "direct_stabilizer" in strategyThe text format is meant for people. There is no structured Plan object in Python.
