LintQ demo ← Main site

LintQ live demo

Pick one of three sample Qiskit programs. The page reimplements the LintQ extractor + three analyses (OpAfterMeas, DoubleMeas, GhostCompose) in the browser and lints the code live — no server, no Qiskit install. Results are verified against the real Soufflé 2.5 pipeline as ground truth.

Program

Extracted facts (EDB)

# click "Run LintQ"

Warnings

    How to read LintQ facts

    LintQ turns your Qiskit source into a set of facts (rows in tables), then applies Datalog rules to those facts to produce warnings. There are three layers. You do not need to read a specific example to read facts — every fact has the same shape and meaning regardless of the circuit.

    1. EDB — input facts (the .facts files)

    These are extracted directly from the source by extractor/ast_to_facts.py, one relation per quantum/AST abstraction. The demo shows them in the “Extracted facts (EDB)” box: Stmt, CFGEdge, Assign, CircuitAlloc, GateOp, MeasureOp, CircuitCall. Each row is tab-separated; the first column is almost always a statement id (the extractor numbers statements in source order — the module docstring is statement 1). Use the Stmt table to map a statement id back to its source line.

    2. IDB — derived / intermediate facts

    The engine computes extra relations on top of the EDB before it can decide whether a warning fires. These are the “derived facts”: they are not written to disk by the extractor, but the rules in engine/lintq.dl build them and the final warning rules read them. The most important ones:

    • AssignedStmt(stmt) — every stmt that is also an assignment. A compose() whose stmt is not in this set is discarded → GhostCompose.
    • ModifiedQubit(circuit, qubit, stmt)stmt applies a gate to qubit. This breaks a DoubleMeas path: if a modification sits between two measurements, they are not redundant.
    • ReachableAfterMeasure(circuit, qubit, stmt) — all statements reachable along the control-flow graph from a measurement of qubit. If one of them is a GateOp on the same qubit, you get an OpAfterMeas warning.
    • MeasReachesMeas(circuit, qubit, first, cur)cur is reachable from measurement first without any qubit-modifying gate in between. When cur is itself a measurement of the same qubit, the engine emits DoubleMeas.

    Tick “Show derived facts” above to see exactly which of these rows your current program produces. A warning is simply the engine's conclusion that one of these derived relations crosses a threshold (e.g. a reachable gate after a measure).

    3. Output warnings (the Warn*.csv files)

    These are what the linter reports. Each warning row records the statement ids involved; look them up in Stmt to find the source lines. The columns are:

    • WarnOpAfterMeas(gate_stmt, circuit, gate, qubit, meas_stmt)
    • WarnDoubleMeas(second_meas, circuit, qubit, first_meas)
    • WarnGhostCompose(stmt, circuit, subcircuit)

    The live demo renders these as plain sentences with line numbers (see the Warnings box). The MCP server does the same and then shuffles the sentence list so an agent is not biased by detection order — the shuffle only reorders the readable strings; it does not change which warnings exist.

    Reference — every relation the demo knows

    The in-browser analyzer (demo.js) is a faithful port of extractor/ast_to_facts.py + engine/lintq.dl, covered by demo.test.js against the real Soufflé 2.5 outputs (ground truth: 3, 2, 0 warnings on the three samples — all reproduced exactly).