Code tour¶
This page shows where each part of NWQLib lives in the source and in what order to read it. Follow one scientific Problem through its configured Method, the Plan it makes, the run that collects data and the Result. Inputs and initialization are defined in separate places, so two methods may target the same Eigenproblem with different trial states.
Before reading code, set up a development environment with Set up, test and build.
The Glossary defines the words that docstrings and these pages use in a narrow sense, such as Plan, Run, Program and preparation record. The terms used only by QHD and its augmented-Lagrangian and box-refinement layers are in the QHD guide.
Conventions gives the sign, phase, qubit-order, unit, normalization and error-quantity conventions shared across families, with the module that states each one.
Find the source and reason for a line of code¶
A developer reading an unfamiliar line usually needs to know which paper and equation it implements, which assumption makes that equation applicable, and why the code differs from the paper where it does. Look in these places, in this order.
- The docstring and nearby comments. A scientific module names the paper, its arXiv version and the equation, theorem or algorithm that each function implements, together with the assumptions the result needs and the units, normalization and shape of the output. A comment next to a rearranged formula gives the step that connects it to the paper. Where NWQLib departs from the paper, the comment states the departure and its reason. Where the paper itself contains an error, the comment gives the correction and the independent check behind it.
- The family guide's source map. Each guide under
docs/algorithms/has a section that lists the implemented steps with their source equations and the functions that implement them. Use it to go from an equation to its code. References links every source map, including those of the subroutine pages. - The bibliography. References gives each citation with the paper version whose numbering the docstrings and source maps use. Equation numbers can change between arXiv versions, and occasionally between the PDF and HTML renderings of one version. Where the renderings are known to differ, the citation gives both numbers. Every page, docstring or comment that names a paper gives that paper's identifier in the same file, in the form
Ding–Lin arXiv:2211.11973v2, or with a DOI or ISBN when the work has no arXiv version. References is the library's citation catalogue. The mathematics page also ends with the paper versions that its equation and theorem locators use, and References lists each of those papers too. - The constants registry. The contribution policy requires every hardcoded tolerance, cap and default to have an entry in Engineering constants with its value, file, reason and the condition for revisiting it. Search that page for the constant's name or value.
- The design rationale. Records, the Run lifecycle, archives and backend adapters follow rules that no paper supplies. Design rationale names the failure each rule prevents, the invariant it keeps and a test that fails when the rule breaks.
To learn one family before changing it, read its guide from the problem definition to the source map, then the cited paper sections, then the modules listed under Follow a family in the order given there. Walk one expectation through the code shows the Plan, Run and Result lifecycle that every family shares. Maintenance lists the checks each kind of change needs.
Reading order¶
src/nwqlib/scientist.pydefines the public functionsplan,compare,estimate,prepare,submitandsolveand the functions that load saved results.search.pyranks a supplied finite set and can rescore its existing Comparison without replanning.problems/records.py,problems/inputs.pyandoperators/inputs.pydefine the mathematical inputs, the meaning of each output and the checked physical input data. Inputs keep coordinate, phase and normalization information, and each Method configures its own initialization.core/planning.pydefines the shared Plan with its original Problem, Method, output, saved random-number-generator state, selected construction and reconstruction data.core/analysis.pydefines Result and its attached immutable RunData. Reanalysis produces a new Result from that data.algorithms/protocol.pydefines Method planning, execution, analysis and optional verification/archive hooks.algorithms/registry.pyfinds the trusted Method implementations that a caller names explicitly, and listing the available Methods does not load external implementations. Configured Method types supply their schemas.ir/andblocks/hold the Program's definitions, ordered calls, arguments and ports, and the selected bindings to backend code.ir/validation.pychecks a Program before any other part of the library reads it, and the docstring of its checking class_Admissiongives the qubit state, coherence-epoch and correlation model.blocks/selection.pybinds each selected definition to trusted backend code by its exact content hash, andblocks/lowering.pybuilds the Qiskit circuit from that same definition body.resources/fold.pytotals resources from the applicable analytical cost rules (ResourceLaw) of the Program without building circuits, and an unknown cost stays unknown.execution.pydeclares the observation, preparation-record, submission and limit records._prepared_execution.pydefines the Run with its preparation, submission and collection, the shared caches of backend objects and the cumulative exposure. Backend connections inbackends/take the selected readout and return the backend configuration that was used._run_journal.pywrites the Run's progress to its run log on disk.backends/assessment.py,profiles.pyandtelemetry.pykeep each device-profile prediction associated with its original allocation and with the executions measured against it.inspection.py, called explicitly, inspects the backend circuits that were built, and formula estimates are not gate counts of optimized circuits.evidence/defines scoped error facts, statistical models, criteria and explicit verification relations.Result.assessdoes not turn a component bound into a total error certificate. Missing evidence remains unknown.artifacts.pyholds the immutable arrays that a Method requests.saved_evidence.pysaves and restores Results and offers a reader for the metadata-only report._choice_archive.pyrestores selected input data through known or explicitly supplied Method code, and_run_archive.pyrestores the execution frontier of a Run, the state from which it resumes. Loading does not replan, normalize arrays or perform scientific analysis.cli.pyprovides the commandsalgorithms,card,options,check-methodandreport.algorithms/authoring.pychecks a Method on one case from its author, with an independently known answer and a deliberately wrong Result that the Method's checks must reject.tests/_hadamard_method.py, the test suite's reference external Method, implements a real Hadamard expectation using shared selected subroutines and Run.
The root package and several subpackages, such as nwqlib.algorithms, nwqlib.backends and nwqlib.problems, import their exports on first use. The shared workflow functions call each Method's own hooks and do not duplicate the construction or iteration logic of any family. Saved Source descriptions import and run no code. Loading the archive of a built-in Method uses the list of known implementations, while loading an external Method requires the caller to pass its implementation.
Walk one expectation through the code¶
Use the Hadamard Method, whose complete implementation is tests/_hadamard_method.py. For the state supplied as (1, i) and observable Y, the expected normalized expectation is one. The Method adds one ancilla and uses the existing selected blocks.
- Check the input and choose the output.
scientist.planchooses the defaultNormalizedExpectationoutput and callsHadamardPauliExpectation.plan. That method checks one nonzero real Pauli coefficient and matching state dimension before selecting PREP and controlled signed-Pauli blocks.Plan._bindattaches the backend code of those blocks once. The reconstruction keeps the observable scalealpha=abs(c)and the ordered ancilla Pauli label, and declarations alone cannot recreate the bindings. See Compose blocks. - Read costs or prepare the same construction.
scientist.estimatecalls the shared computation of resource totals (fold), which reads the selected Program and its cost rules without building a circuit.scientist.prepareinstead creates a Run and invokes the Method's inheritedprepare_static.blocks/lowering.py::_lower_qiskitbuilds the Qiskit circuit from the original calls, arguments and port order, andAerBackend.preparecompiles that logical circuit for Aer and inserts the requested readout.PreparedArtifactrecords this preparation itself, not a second build made for reference. See Run on a backend. - Collect data through the Run.
scientist.submitreturns the Run after starting the work its Plan selected. The inheritedexecute_staticsubmits the prepared item and collects a completed observation before analysis._prepared_execution.pysets aside the work against the Run's limits and associates each observation with its preparation record, and the backend converts the result that its SDK returned. Exact readout, in which the simulator computes the expectation without shot sampling (shots=None), subject to numerical rounding, gives the ancilla Pauli mean, while a positive shot count gives the ancilla counts of those shots.Run.waitreturns the scientific Result once available. See Execution and storage. - Reconstruct and validate the quantity.
HadamardPauliExpectation.analyzecalls_ancilla_meanon those observations, then computesvalue = rec.alpha * mean. ForA=cP, the controlled action already includessign(c), so this multiplies the magnitude exactly once.HadamardExpectationResult.validate_planchecks the selected scientific relation, andvalidate_dataties the mean and the Result to the observation they were computed from.Result._attachchecks the content hashes of the original Plan and of the observations before attaching RunData. Neither analysis nor its summary measures the state again. - Save, reload and reuse.
saved_evidence.save_resultinvokes the Method'ssave_archivehook and saves its Result and RunData.load_result(path, method=HadamardPauliExpectation)requires that explicit trusted implementation. Itsload_archiverestores the selected inputs and known block bindings, and the common loader checks the content hash of the original Plan.Result.analyze()then interprets the same data again.read_reportfollows the separate metadata-only path. A saved Run also uses_run_archive.pyand_run_journal.pyto restore its execution frontier, and a standalone Result does not hold that state. See Save, load and reanalyze results and Continue an interrupted run.
When changing this Method, place each change in the code that defines that part. Input checks and choices belong in plan, the gate action in the selected block, the interpretation of data in analyze, and the saved choices in its archive hooks. Adaptive methods such as ADAPT replace the static execution hook with their own iteration loop in src/nwqlib/algorithms/gcim/adapt_acquisition.py, and they still use the same preparation, submission and observation code. The author check supplies an independent expected value and a deliberately wrong Result that must be rejected, but it does not certify every input supported by a Method.
Follow a family¶
Each algorithm guide has a source map from implemented steps to their paper equations and the code that implements them. References lists those maps.
- Expectation.
algorithms/expectation.pyimplements finite Pauli selection, grouped exact readout, parity/count inference and optional readout calibration.evidence/binary.pyandstatistics.pykeep the statistical assumptions chosen at planning. - Lanczos.
src/nwqlib/algorithms/lanczos/method.pyselects the signed Chebyshev walk and its readout table and analyzes moments, and its siblingreadout.pyreads signed outcomes from the histograms of the coherent SELECT-basis readout. Itsnumerical.pybuilds the raw Chebyshev Gram matrix and pencil from moments and defines the allocation and cutoff rules.src/nwqlib/_projected_eigensolver.pythresholds and solves the pencil, andworkflow.pyadvances explicit sensitivity sampling through the common Run. - GCiM / ADAPT. Read
src/nwqlib/algorithms/gcim/pencil.pyandsrc/nwqlib/_projected_eigensolver.pyfor the H/S pencil and its solve, thenfixed_basis.py, which selects normalized trial columns and interprets transition measurements. For ADAPT-GCiM continue withadapt_inputs.py(pool and commutators),adapt.py(one query space for every adaptive query),adapt_acquisition.py(basis chains, composition of the backend circuits and the resumable iteration loopdrive_adapt),bounded_growth.py(the examined extensions, CX count bound, score and sampled eligibility ofBoundedRitzGrowth), thenoptimization.pyandadapt_verification.py.src/nwqlib/subroutines/fermionic_pool.pyandfermionic_circuits.pydefine the generators and their exact circuits. The Table V test intests/test_fermionic_pool.pycompares every operator of the default spin-adapted pool with Table V of Zheng et al., arXiv:2312.07691v3, including signs and repeated indices. - LCHS.
src/nwqlib/algorithms/lchs/method.py, and its siblingselection.pyandprimary_records.py, connect LinearDynamics to selected reconstruction and Result.plan_lchsroutes the problem, andselect_densepads A and callstime_independent_terms.py, which applies the PSD rule and asksproviders.pyfor finite nodes and coefficients.parameters.pyfixes every SELECT and PREP product once.quantum.pyassembles the PREP/SELECT/readout Program, andnative.pysupplies dense, product-formula, structured and QSP leaves.host.pyevaluates the selected classical model,solution_error_budget.pypropagates component bounds to the physical output, and the refinement and verification modules hold the explicit checks. - QPE.
src/nwqlib/algorithms/qpe/method.pyselects the input, time scale and Hadamard-test Program, and its siblingpowers.pyselects each controlled power with the bounds insrc/nwqlib/subroutines/trotterization/error_budget.py.numerical.pyholds the numerical routines of the four estimators with their paper equations and departures.controller.pyadvances RWPE through the common Run, andrecords.pyties selected queries and powers to their original inputs and Method. Verification is explicit and keeps its nominal spectral scope. - QLS. Read
src/nwqlib/subroutines/qsp/phases.pyfor the Wx convention, phase solving and the sampled sup-norm bound, theninverse.pyandshortcut.pyin the same package for the two polynomial families, andevolution.pyfor the projector-phase circuit.src/nwqlib/algorithms/qls/method.py, and its siblinghost_planning.pyandprimary_records.py, select the original LinearSystem, encoding, spectrum and polynomial.quantum.pywrites the Program's named encoding, projector, phase, query and readout calls, the numerical and norm-search modules supply explicitly chosen classical models, andverification.pystates the explicit allowances. - QHD. Start with the module docstring of
src/nwqlib/algorithms/qhd/method.py, which maps the Method to Leng et al.'s Algorithm 1 (arXiv:2303.01471v1) and states each departure with its reason. Then readsrc/nwqlib/algorithms/qhd/schedules.py,grid.py,kinetic.pyandpotential.pyfor the discretized Hamiltonian, withobjective.pypreprocessing the objective for the one-hot compiler, theninitial_state.pyfor the start vectors and their structured preparation,compiler.pyfor the step order and the running phase total (the sum of the identity phases that the compiled blocks omit),binary.pyfor the binary register, its QFT kinetic step and diagonal syntheses, andsplit_step.pyfor the classical split-step variant.resources.py,evolution_bounds.pyandcircuit_errors.pyhold the rotation-count formula of the generated circuit, the budgeted T estimate, the per-circuit error sources and their bounds.method.py, its siblingrecords.pyand the decoding module connect an ordered box objective to the selected finite model, its one-hot or binary circuit, the observed candidate and the most probable point. Explicit verification keeps grid and continuum/global-optimum claims distinct. The two layers that run a sequence of QHD Plans share_outer.py, which holds their inner planning streams, remaining limits, counts and point rules.constrained.pyandconstrained_records.pyhold the augmented-Lagrangian layer for aConstrainedOptimization, including support preprocessing, inequality representation selection, slack caps and error records, projected readout and the planning-only round-0 entry, andrefinement.pyandrefinement_records.pyhold box refinement with its search model and stall split._durable.pyholds the saved directory of both layers, with its outer record written to a temporary file and then renamed into place, the exclusive lock that lets one call at a time continue the directory, the backend of its inner Runs with a saved noise model, and the reopening of inner Runs byresume_augmented_lagrangianandresume_box_refinement. - Circuit subroutines.
src/nwqlib/subroutines/_multiplexors.pyimplements the uniformly controlled rotations, phase diagonals and dependency-projected multiplexors that the other constructions reuse, together with their CX-count formulas.src/nwqlib/subroutines/state_preparation/direct.pybuilds PREP from them,src/nwqlib/subroutines/lcu/core.pycomposes PREP, SELECT and PREP†, andsrc/nwqlib/subroutines/block_encoding/core.pyplans a multiplexed Pauli, banded or dense-dilation encoding and then builds exactly that plan.controlledinsrc/nwqlib/subroutines/qiskit_compat.pyadds every control. It synthesizes a directly controlledUnitaryGatefrom its whole controlled matrix. Any other gate takes the route that the construction selects (dense control route). On the gate-wise routecontrolledreplaces each dense unitary in the definition by its exact synthesis before Qiskit controls the gates, and on the whole-matrix route, which"auto"takes for one control, it synthesizes the controlled matrix of each dense unitary.src/nwqlib/subroutines/_dense_synthesis.pyprovides both syntheses, CX and one-qubit gates that equal the matrix to rounding.
Follow the shared machinery¶
The layers below have no paper source. Design rationale indexes the failure each mechanism prevents, the code responsible for it and the test that checks it.
- Saved Run. The module docstring of
src/nwqlib/_prepared_execution.pystates the lifecycle rules and the crash windows of a static data collection. Then readsrc/nwqlib/_run_journal.pyfor atomic transitions and the file lock,src/nwqlib/_run_archive.pyfor the cache write, commit and delete order, and Execution and storage. The module docstring also coversprepare(plan, settings="all"), which prepares every experiment of a static Plan before any circuit runs, andPreparationNotRebuilt, which a Run raises instead of building again a local preparation whose work is counted against the limits but which has no preparation record. - Backends. The module docstring of
src/nwqlib/backends/connection.pystates the adapter contract thatsubmit_detachedandrefresh_submissionsrely on. Then follow one detached adapter end to end, for examplesrc/nwqlib/backends/slurm.pywithsrc/nwqlib/backends/nwqsim.py, through launch, reconciliation, refresh and result decoding. Backend adapter contract lists the provider rules. - Error evidence. A Method's Plan carries an error model listing its required error sources, and
Result.factssupplies any evaluated bound.Result.assesscombines them by the triangle inequality and a union bound and passes only on witnessed evidence of kindproved_relationorcertified_bound. An explicitverifyproduces facts that preparation records support, bound to the options it was given.src/nwqlib/evidence/error_model.pydefines these rules.
io/streaming.py writes the ordered elementary-gate recipes of supported blocks directly as QASM within the configured limits. io/materialization.py derives the construction's expansion counts, compares the construction_id of the writer's QasmWriteReceipt with the construction's content_id and refuses a mismatch, then checks those counts and the file's byte size before importing the file, which must be the unchanged output of the same writer call. Neither operation changes the original selected experiment.
Byte and work budgets¶
Many numerical functions take max_bytes, and some also take max_work or max_products. Before allocating, such a function computes from the input sizes alone the bytes of the arrays it will hold at the same time (its peak live arrays) and the number of scalar operations in its dominant steps. It compares these numbers with the limits and raises ValueError, naming the operation, the requirement and the limit, when either is exceeded. operators/access.py holds the shared checks _check_bytes and _check_products, and many modules make the same comparison inline.
The reason is that array sizes in this library grow as 2**q in the qubit count q, as D² or D³ in a dense dimension D, or polynomially in a degree or step count. A small change to an input can turn a computation of seconds into one that exhausts memory partway through. Checking the requirement first turns that failure into an immediate error, raised before the operation allocates anything and, for checks made during planning, before any preparation or submission. Work that runs after data collection but whose size the Plan alone fixes, such as the projected solve of Lanczos or FixedGCIM and the updates of the RWPE iteration, is checked during planning, so an undersized limit fails before any circuit runs. The caller can then raise the limit knowingly or choose a compact representation. The contribution policy states the general rule that the check precedes the work it limits, and Input cost controls give the size formula of each input operation.
The units are the same across the library. max_bytes counts bytes. Its default 10_000_000_000 (decimal 10 GB) is defined once in _limits.py and sized so that ordinary research inputs pass, as its registry entry explains. max_work and max_products count scalar operations according to a formula written next to the check, for example 8D³ for a dense SVD of dimension D or D² for a dense matrix-vector product. Their defaults, most of them 1_000_000_000, are registered in Engineering constants.
These limits cover only part of the cost. The byte count includes the arrays whose sizes the code knows before it allocates them and any other allocation that a formula names. It excludes other workspace inside NumPy, SciPy, LAPACK and Qiskit, other Python object overhead and the rest of the process, so passing the check does not guarantee that the process fits in memory. For example, the energy-shift relation check counts NumPy's sort buffers, and the circulant classification of a Pauli block-encoding plan counts its Python integers, Fraction wrappers and dictionary entries, as their entries in Engineering constants state. The work count is a planning quantity, not measured CPU time. Each limit applies to one operation. A Method that repeats an operation, for example once per iteration or query, accounts for the repetition separately, and a computation derived from another object scales its limit with that object, as the work limit of the resource total does.
Planning combines the requirements of phases whose selected dimensions are already known before starting those phases. Successive memory phases use the largest of their live-byte bounds, including data held across phases. A refusal distinguishes a complete known requirement from a conservative estimate or from a lower bound left by interrupted counting. Later phases can need more when their sizes depend on coefficients, selected ranks, spectra or observations. operators/access.py::refuse_known_need words such a refusal, QLS and QPE call it before their first dense phase, and QHD passes the same wording through its own planning check before it evaluates the initial state.
Comments next to the checks map each term of a formula to the arrays it counts, for example 16 * n for n complex128 entries or 8 * n for n float64 entries. When you add an array to such a function, add its bytes to the formula. When you add a function whose memory or work grows with its input, add a check before the first large allocation and register any new default.
Conventions and validation¶
- Contribution policy states the rules for mathematical domains, numerical tolerances, and the scientific and resource distinctions.
- Conventions collects the sign, phase, qubit-order, unit, normalization and error-quantity conventions shared across families, and each family's own frames and recoveries.
- Maintenance explains the checks for each kind of change, example and notebook changes, and delivery procedures.
- Algorithm guides map calculations to their source equations and describe current method controls and limitations. References catalogues the papers and their versions.
- Design rationale indexes the mechanisms that have no paper source.
- ENGINEERING_CONSTANTS.md records concrete operation bounds and their reasons.
- ROADMAP.md describes current capabilities and separately identified open work.
docs/scripts/golden_snapshot.pyanddocs/scripts/mutation_probes.pysupport scoped behavior comparisons and discriminating mutations. Passing them does not replace independent scientific evidence.
Code locations for inputs and search¶
Input relations¶
For the relations in Conventions and derivations, the named code writes each one out in its docstring or an adjacent comment.
| Relation | Justification | Code location |
|---|---|---|
Coordinate index k = sum_q b_q 2**q, qubit 0 rightmost |
Qiskit little-endian order | operators/inputs.py (ORDER) |
Stored row (x, z) means i**popcount(x & z) X**x Z**z, so both bits set is Y |
NWQLib encoding | operators/_pauli.py (PauliTerms) |
SparsePauliOp coefficient of the canonical label is coeff * (-i)**phase |
Qiskit phase convention | operators/inputs.py (operator_input) |
Dense matrix to Pauli coefficients c_P = tr(P M)/D by 2×2 block recursion |
Standard identity | operators/_pauli.py (pauli_coefficients) |
| Pauli product phase and the action of a word on a basis state | Standard Pauli algebra in the stored encoding | PauliTerms.product, apply_terms |
| Commuting test | Even symplectic product | PauliTerms.group |
| Qubit-wise-commuting test | Equal single-qubit Paulis on the shared support | PauliTerms.group |
a_j† = (prod_{k<j} Z_k)(X_j - iY_j)/2 |
Jordan–Wigner transformation | operators/_fermion.py (_ladder_image) |
Normal ordering of dΓ(B)²/2 |
Standard anticommutator algebra | operators/df.py (_contract) |
Spin orbital (p, σ) on mode 2p+σ |
NWQLib convention | operators/df.py (_rows) |
| Pauli L1 norm and spectral enclosure | Triangle inequality, unit-norm Pauli words | operators/refinement.py (_pauli_values) |
| Sparse spectral enclosure and norm bound | Gershgorin circle theorem | operators/refinement.py (_sparse_values) |
Search ranking¶
| Step | Documented rule | Code location |
|---|---|---|
| Strict dominance, Pareto front and incomparable rows | Read the ranking | search.SearchSelection |
| Objective values read from the Plans, their resource totals and forecasts | Objectives | search._objective_value |
| Association of a selection with its Comparison, and rescoring without new work | Rescore a comparison | search._comparison_identity, search.SearchSelection.validate_comparison |
| Size controls checked before evaluation | Finite search frontier envelope | search.scan, search._frontier_size |