Steven GellerQuantum Computing, End to End

Book contents

Current section

Part V. Practical Software

  1. Python and Quantum Programming Workflow
  2. Building a Small Simulator From Scratch
  3. Qiskit, Primitives, and Circuit Execution
  4. Cirq and Alternative Toolchains
  5. Transpilation and Hardware-Aware Compilation
  6. Noise Models and Noisy Simulation
  7. Benchmarking Quantum Programs
  8. Resource Estimation for Fault-Tolerant Algorithms
  9. Reproducible Quantum Labs

Part V. Practical Software · Chapter 39

Cirq and Alternative Toolchains

Every quantum SDK can run a Bell circuit. They differ in what they make easy, what they hide, and how much maintenance they will cost you over two years. This chapter turns SDK choice from a taste question into an evidence question.

Lab
In this chapter 10 sections

Compare one fixed circuit contract across tools using explicit qubit order, native result objects, simulator mode, compilation target, versions, and identical statistical tests; choose a tool from workload fit and maintenance cost, not feature counts or popularity.

Portability begins with a test oracle that belongs to neither SDK. The comparison then measures the translation tax instead of mistaking two different APIs for two different algorithms.

Two adapters converge on one normalized recordBell contractCirq adaptersecond adapternormalized JSONshared assertions
Figure 39.1. The native records remain available for diagnosis. The normalized record is deliberately smaller: only fields whose meaning has been reconciled cross the adapter boundary.

Freeze the circuit contract before choosing syntax

The fixture declares two qubits, q0 as the most-significant displayed bit, H(q0), CNOT(q0,q1), computational-basis measurement, exact support {00,11}, probabilities 0.5/0.5, seed, shots, and an acceptance rule. It also declares simulator mode: exact state-vector comparison and sampled comparison are separate.

Write this as plain data and assertions. If the contract is embedded in one adapter’s result types, the second adapter will be judged against the first SDK rather than against the circuit. OpenQASM 3 may supply an interchange representation, but serialized equivalence does not erase backend-specific compilation or execution [OpenQASM 3 specification].

Cirq's qubits, moments, and simulator result

Cirq asks the programmer to choose explicit qubit objects, organizes scheduled operations into moments, and returns native simulator and measurement result objects [Cirq documentation]. Preserve those concepts in the adapter. Record ordered qubits, moment structure, simulator type, resolver options, measurement key, repetitions, seed, version, and dependency lock hash.

Normalization happens after inspection. Convert the native measurement array to book-visible strings using a tested qubit-column map. Store both that map and the native shape. A two-qubit Bell histogram can look correct after an accidental reversal because 00 and 11 are palindromes; include asymmetric basis fixtures 01 and 10 so ordering errors cannot hide.

Consider the native row [0,1] returned for ordered qubits (q1,q0). It denotes q1=0 and q0=1, so the book’s q0-most-significant string is 10, not 01. The repair is a column permutation derived from qubit identities. Reversing every string happens to repair this two-qubit case, but it is not a general adapter: measurement keys may cover subsets of qubits, appear in a different order, or be concatenated from multiple registers.

Moments also carry semantics that a flat operation list loses. Operations in one moment are intended to coexist under Cirq’s scheduling model; a second tool may express the same partial order through dependencies or barriers. Preserve the native schedule and compare only a declared derived quantity, such as critical-path layers after both adapters apply the same dependency rule.

A second adapter under the same assertions

Qiskit’s execution abstraction and result conventions warrant a separate adapter [Qiskit documentation]. The second adapter may use different qubit identifiers, scheduling concepts, and transpilation hooks. It must still emit a normalized record with circuit ID, displayed-bit convention, exact or sampled mode, support/probability or counts, shots, seed, SDK version, and native-record hash.

The shared harness first tests deterministic basis circuits, then the exact Bell state, then seeded samples. It refuses unknown result fields rather than guessing. An adapter can be unavailable without making the core contract fail, but the comparison record must say unavailable and why.

The failure sequence matters. The 01 and 10 cases diagnose bit and qubit order before entanglement is involved. A phase fixture such as H–Z–H on one qubit diagnoses whether a simulator preserved relative phase. Only then does the Bell case exercise the two-qubit operation and sampling path. When a port fails, this ladder identifies the first semantic layer that diverged instead of producing one unhelpful “histograms differ” message.

Cross-SDK Bell conformance harness

Fields normalized only after semantics are reconciled
fieldCirq sourcesecond-tool sourceshared meaning
bit_orderordered qubits/columnsclassical mapq0-most-significant
supportstate or measurement arrayquasi/count resultdisplay strings with nonzero mass
schedulemomentstranspiled depthkept native; not equated
provenanceversion + lockversion + lockrequired independently
contract = {"order": ("q0", "q1"), "support": {"00", "11"}, "p": {"00": .5, "11": .5}}
def canonical_counts(record):
    columns = record.get("columns")
    counts = record.get("counts", {})
    if (type(columns) is not tuple or len(columns) != len(set(columns)) or
            set(columns) != set(contract["order"]) or not counts):
        raise ValueError("adapter columns must be a permutation of the contract order")
    output = {}
    for bitstring, count in counts.items():
        if len(bitstring) != len(columns) or type(count) is not int or count < 0:
            raise ValueError("counts must use fixed-width bit strings and integer counts")
        by_qubit = dict(zip(columns, bitstring))
        canonical = "".join(by_qubit[qubit] for qubit in contract["order"])
        output[canonical] = output.get(canonical, 0) + count
    return output

cirq_bell = canonical_counts({"columns": ("q0", "q1"), "counts": {"00": 501, "11": 499}})
second_bell = canonical_counts({"columns": ("q1", "q0"), "counts": {"00": 501, "11": 499}})
cirq_asymmetric = canonical_counts({"columns": ("q0", "q1"), "counts": {"01": 700, "10": 300}})
second_asymmetric = canonical_counts({"columns": ("q1", "q0"), "counts": {"10": 700, "01": 300}})
wrong_declaration = canonical_counts({"columns": ("q0", "q1"), "counts": {"10": 700, "01": 300}})
invalid_rejected = False
try:
    canonical_counts({"columns": ("q0", "q0"), "counts": {"00": 1}})
except ValueError:
    invalid_rejected = True
assert set(cirq_bell) == contract["support"] and cirq_bell == second_bell
assert cirq_asymmetric == second_asymmetric == {"01": 700, "10": 300}
assert wrong_declaration != cirq_asymmetric and invalid_rejected
print(f"PASS: 39 adapter Bell={cirq_bell} asymmetric={cirq_asymmetric} wrong_order={wrong_declaration}")

Differences the equality test cannot erase

Equal ideal probabilities say nothing about compilation target, native gates, scheduling, cloud access, parameter binding, noise model, dynamic-circuit support, or maintenance surface. Measure code and dependency size in files or bytes; compile and run time in seconds; shots as counts. Report serialized size and whether round-trip parsing preserves the contract. Do not convert moments into depth unless the scheduling definitions truly match.

Artifact comparison needs runnable evidence and declared environment boundaries, not feature-matrix checkmarks [ACM artifact review guidance]. The most expensive difference may be organizational: which SDK the target hardware supports, how often APIs migrate, and who owns the adapter when they do.

Noise simulators are particularly easy to compare badly. A channel attached “after each gate” depends on how each compiler decomposes the circuit; equal channel parameters do not imply equal noisy processes when native gate counts differ. Either compare an agreed compiled operation trace or label each noisy result as tool-specific. Likewise, a state-vector simulator and a tensor-network simulator may agree on a small fixture while having radically different tractable circuit families.

A workload-specific selection record

A teaching simulator values readability, deterministic local execution, and a small dependency boundary. A hardware characterization project values target integration, calibration access, pulse or schedule controls, and result metadata. State the workload, weighted requirements, measured adapter costs, chosen version, and reversal conditions. “More popular” is not a requirement; “maintained by the target team and exposes required calibration fields” can be.

Make reversal conditions measurable. A choice can be revisited if the pinned environment stops receiving security fixes, the target backend drops the integration, median compilation time exceeds the project’s CI budget, or a required dynamic-circuit feature becomes available only through the other adapter. Recording the owner and next review date turns tool choice from folklore into a maintainable engineering decision.

The GHZ extension strengthens, but does not replace, asymmetric fixtures. Exact support {000,111} tests a three-qubit entangling chain and normalized qubit order, while prepared 001 and 100 still expose a full reversal that GHZ cannot. The conformance report therefore names which defect each case can reveal. Test portfolios should be designed for identifiability, not chosen because their output looks recognizably quantum.

Portability is earned at a boundary. The project promises that each pinned adapter maps the declared circuit contract into the common semantic record; it does not promise identical native schedules, noise attachments, intermediate representations, or future APIs. That narrower promise is testable and useful. A broad claim that “the code runs everywhere” is neither.

Retain native exceptions too. Normalizing every failure to “adapter unavailable” would erase whether construction, simulation, measurement extraction, or bit-order translation failed.

GHZ adapter extension

Prompt: Add a GHZ circuit to both adapters and make the shared harness test exact ideal support plus seeded sampled support.

Deliverable: Two implementations, normalized records, shared tests, and a one-page choice memo for a named research or teaching workload.

Pass condition: Both implementations satisfy the same semantic oracle, all convention translations are explicit, and the choice memo cites measured maintenance or compilation differences.

Reference comparison

Format: Reference GHZ adapters, expected normalized result records, and selection-memo rubric.

Verification: Run both pinned test environments and compare normalized exact probabilities within tolerance and count support against the shared oracle.

The normalized GHZ records have exact support on 000 and 111 with probability one half each, while each native record retains its own column ordering and schedule metadata. The selection memo chooses a tool only for the named workload and lists the integration or maintenance measurement that would reverse that choice.

Companion work

Artifacts for this chapter

These entries resolve to checked-in local source. Commands are reproduced exactly from the chapter manifest, and source-embedded fixtures are exported as direct downloads.

  1. Reproduce or test

    python3 tools/validate_briefs.py --briefs data/editorial_briefs_36_63.json --from 36 --through 63 --check-rewritten-sources --execute-artifacts

Provenance

Sources and review

  1. Google Quantum AI. Cirq documentation. Google. 2026official documentation
  2. IBM Quantum. Qiskit documentation. IBM. 2026official documentation
  3. OpenQASM Technical Steering Committee. OpenQASM 3 specification. Linux Foundation Joint Development Foundation. 2026official technical specification
  4. Association for Computing Machinery. Artifact Review and Badging. ACM Publications. 2026official reproducibility policy

The load-bearing claims in the chapter are mapped inline to this registered source set. A citation supports only the bounded claim beside it.

Cite this chapter