SIA — Simplified Integrated Architecture
sia-script is the Python library of Sia Software Innovations Private Limited. It provides an offline quantum simulator, a client for the HDQS quantum server, a declarative entity module, and an ABAP-style enterprise logic interpreter, all behind short, chainable APIs.
from sia import hdqs
q = hdqs(2).h(0).cx(0, 1)
print(q.sample(1000)) # {'00': ~500, '11': ~500}
One import is all a program needs.
Contents
- Installation
- Components
- Quantum simulation:
hdqs - HDQS server client
- Entities:
ntt - Enterprise logic:
els - Optional dependencies
- Conventions
- Licensing
- Citation
- Support
Installation
pip install sia-script
Requires Python 3.9 or newer. The install brings NumPy, Requests, Matplotlib and openqasm3, so figures, animations, paper figures, worksheets and QASM work straight away. Heavier features are extras:
pip install "sia-script[torch]" # trainable quantum layers, CUDA acceleration
pip install "sia-script[full]" # torch and SciPy
pip install "sia-script[all]" # everything, including Qiskit/Aer/PennyLane adapters
Components
| Import | What it is | Needs network |
|---|---|---|
from sia import hdqs |
Offline quantum simulator (hdqs(n)), plus the server client through the same name |
No (simulator) |
from sia import ntt |
SiaNTT declarative entities with safe, AST-checked expressions | No |
from sia import els |
SIA Enterprise Logic Studio, an ABAP-style interpreter | No |
The simulator runs entirely on your machine. Importing sia makes no network
call; only the server client contacts the HDQS server, and only when you create
a client.
Quantum simulation: hdqs
Chainable circuits
Every gate returns the register, so programs stay short:
from sia import hdqs
q = hdqs(3).h(0).cx(0, 1).cx(1, 2) # GHZ state
q.show_state() # amplitude table
print(q.sample(1000)) # measurement counts
print(q.estimator("ZZI")["value"]) # <ZZI> = 1.0
print(q.resources()["depth"]) # 3
Gates: h x y z s sdg t tdg rx ry rz p u3 cx cy cz cp crx cry crz swap ccx
cswap mcx (cnot and toffoli are aliases), the cx_chain() ladder, plus
barrier, reset_qubit, measure and custom unitary.
Noise
Density-matrix mode supports CPTP-verified channels:
from sia import hdqs
q = hdqs.dm(2).h(0).cx(0, 1).depolarizing(0, 0.05).amplitude_damping(1, 0.1)
print(q.purity(), q.concurrence())
noisy = hdqs(2).h(0).cx(0, 1).with_noise("depolarizing", 0.01) # replay with noise
Channels: bit flip, phase flip, depolarizing, amplitude damping, phase damping, generalized amplitude damping, thermal relaxation, coherent over-rotation, amplitude–phase coupling, correlated two-qubit noise, and classical readout error.
Programs: replay, feed-forward, undo
The register remembers its own program, so the same object can be rerun, drawn, optimized, exported or undone:
from sia import hdqs
q = hdqs(3).h(0).cx(0, 1).ry(2, 0.4)
print(q.run(500).counts) # rerun as a program
print(q.copy().compose(q.inverse()).probability_of("000")) # undo: 1.0
ff = hdqs(2).h(0).measure(0, key="m").if_x("m", 1) # mid-circuit feed-forward
print(ff.records, ff.run(1000).counts)
measure(qubit, key="m") keeps the chain going and stores the outcome in
q.records["m"]; if_x, if_z and if_gate record their condition, so
run(), draw() and to_qasm3() reproduce the program exactly. Branch with
these, not with a Python if. Plain measure(qubit) still returns the outcome
as a string.
Large registers and simulation modes
A register too large for a full state (above the 1 GiB default budget) records its program instead of failing, and can run on the stabilizer or MPS simulator:
from sia import hdqs
print(hdqs(200).h(0).cx_chain().stabilizer().sample(5)) # 200-qubit GHZ
print(hdqs(40).h(0).cx_chain().mps().summary()["max_bond_dimension"]) # 2
| Mode | Call | Use for |
|---|---|---|
| statevector | hdqs(n) (default) |
Exact pure-state simulation |
| density matrix | hdqs.dm(n) |
Exact mixed states and noise |
| trajectory | q.run(mode="trajectory", noise=...) |
Sampled noise at statevector memory cost |
| stabilizer | q.stabilizer() |
Large Clifford-only circuits |
| MPS | q.mps(max_bond_dim=...) |
Low-entanglement circuits |
For parameterized templates reused with different values, use
hdqs.Circuit with hdqs.Parameter and run(bindings=...) or sweep(...).
Algorithms and protocols
from sia import hdqs
print(hdqs.grover(3, ["101"])["best"]) # '101'
print(hdqs.simon("110")["recovered"]) # '110'
print(sorted(hdqs.shor_demo(15)["factors"])) # [3, 5]
print(hdqs.teleport()["fidelity"]) # 1.0
print(hdqs.bb84(256, eavesdrop=True)["eavesdropping_suspected"]) # True
Included: Deutsch, Deutsch–Jozsa, Bernstein–Vazirani, Grover, Simon, QFT (qft_demo),
phase estimation, order finding and a small Shor demonstration, teleportation,
superdense coding, VQE, QAOA, a repetition code, and the BB84, E91 and QSS
protocols (educational simulations, not production key distribution). Every
result can animate itself with .draw() (see Algorithm visuals).
Analysis and mitigation
Observables and Pauli sums, sampled estimates with standard errors, Trotter
evolution, entropy, concurrence, negativity, mutual information, state
tomography, readout-error mitigation, zero-noise extrapolation, and CRIA
interference accessibility (interference_report, interference_profile,
recover_interference).
Machine learning (requires [torch])
import torch
from sia import hdqs
layer = hdqs.quantum_layer(4, layers=2) # an ordinary torch.nn.Module
out = layer(torch.rand(8, 4, dtype=torch.float64)) # (8, 4) Pauli-Z expectations
hdqs.quantum_layer(..., diff="parameter_shift") gives hardware-style
gradients instead. The underlying classes are BackpropQuantumLayer,
QuantumLayer, MidCircuitQuantumLayer, QASMQuantumLayer, and
CircuitQuantumLayer (any Circuit, including exact gradients through
mid-circuit measurement).
Visuals: one call, letter codes
from sia import hdqs
q = hdqs(3).h(0).cx(0, 1).ry(2, 0.7).cx(1, 2)
q.draw("b") # Bloch spheres, shown inline or in a window
q.draw("b,a,e", "state.png") # several views in one figure
q.draw("all", "lesson.html") # offline interactive page with a gate-by-gate slider
q.draw("a,b", "steps.gif") # animation over the gates
q.draw("b,q,d", "model.glb") # 3D for Blender
q.draw("b", "bloch.3mf") # colour 3D print, with a print report
q.draw("c,b,a", "fig.pdf", preset="paper") # journal figure + caption
q.draw("c", "circuit.tex") # LaTeX (quantikz)
q.export_bundle("experiment.zip") # everything needed to publish or reproduce it
q.code() # the hdqs chain that rebuilds q
New to the mathematics? hdqs.cnum, hdqs.vec, hdqs.mat and hdqs.practice cover complex numbers, vectors, matrices, eigenvalues and tensor products, with practice problems (see Quantum maths).
| Code | View |
|---|---|
c |
Circuit diagram (controls, targets, angles, measurements, conditions) |
p |
Exact probabilities |
h |
Measured counts (shots=), with ±1σ error bars and the exact values |
a |
Amplitudes & phase: bar height = magnitude, colour and a clock hand = phase |
b |
Bloch sphere for every qubit, with coordinates and purity |
q |
Q-sphere: basis states by number of 1s, coloured by phase |
d |
Density matrix, real and imaginary parts (up to 5 qubits, or qubits=[...]) |
e |
Entanglement map: mutual information and concurrence for every qubit pair |
i |
CRIA interference profile with the best helper sets |
s |
Step-through: the state after every gate |
u |
Each step as a matrix: U · |ψ⟩ = |ψ′⟩ with exact entries (1/√2, i/√2, …), up to 4 qubits |
v |
State vector table: amplitude, probability and phase of every basis state |
t |
Timeline: each qubit's entropy, the register's purity and every ⟨Z⟩ after each step |
all |
Every 2D view (c p h a b q d e i v) |
Codes combine with commas ("b,a,e"), and several outputs can be written at
once ("x.png,x.html,x.glb"). The file extension picks the output:
| Extension | Output | Needs |
|---|---|---|
.png .jpg .svg .pdf .webp |
Combined figure, light or dark (theme="dark"); preset="paper" for publications |
— |
.gif |
Animation over the gates | — |
.html |
Interactive page: step slider, rotatable spheres, exact values on hover, table view, data download. One file, works offline and on phones | — |
.json .csv |
The numbers behind every view | — |
.tex |
The circuit as LaTeX quantikz (standalone=False for the bare environment) |
— |
.glb .obj |
3D scene for Blender, Maya, Unity or web viewers, with every part a named object | — |
.3mf |
Print-ready colour model in millimetres: one named, coloured part per piece, print report inside | — |
.stl |
Watertight, print-ready model in millimetres | — |
The e view also tests every split of the register, so a GHZ state is reported as
entangled as a whole, not in pairs. In the .html page, stepping animates between
states, each Bloch sphere shows its qubit's 2×2 reduced density matrix, and the density
matrix can be shown as |ρ| with phase colour or as real and imaginary parts.
3D files are produced only when a 3D extension is named, so "all" never
writes one by accident. The 3D views are b, q and d. q.draw("bell.png")
still draws the circuit, and q.plot(...) still returns a Matplotlib figure.
3D printing
q = hdqs(2).h(0).cx(0, 1).ry(1, 0.4)
q.draw("b", "bell.3mf", diameter=60) # 60 mm spheres, FDM settings
q.draw("b", "bell.stl", preset="resin", wall=0.6) # finer resin print
q.last_print_report["min_feature_mm"]
3D print report — bell.3mf (3MF, preset fdm)
✓ watertight / manifold
✓ minimum feature: 1.2 mm (target wall 1.2 mm)
• size: 153 × 66 × 76.4 mm
• volume: ≤ 32.71 cm³ (overlapping parts are merged by the slicer)
• 34 parts, 49,456 triangles, 6 colours
• overhangs: 6.5% of surface — supports recommended
| Option | Meaning |
|---|---|
diameter= |
Sphere diameter in mm (otherwise scale= × 60 mm) |
wall= |
Thinnest printed feature in mm; tubes and letters are thickened to it |
preset= |
"fdm" (wall 1.2 mm, medium detail, the default) or "resin" (0.5 mm, high detail) |
detail= |
"low", "medium", "high": fewer or more triangles |
base= |
Stand with an embossed label plate (False for none) |
labels= |
True / "embossed" or "none"; labels too small for the wall are enlarged a little or left out with a note |
report= |
False to skip printing the report (it is still in q.last_print_report) |
3MF keeps units, colours and part names (bloch_q0_equator, bloch_q0_state_arrow,
…), so multi-colour slicers can assign a filament per part. The report checks
each part for closed, consistently oriented edges and measures the thinnest
feature, size, volume and overhang share.
Publication figures
q.draw("c,b,a,e", "figure.pdf", preset="paper") # double column (7.16 in)
q.draw("a", "amps.png", preset="paper", column="single") # 3.5 in, 600 dpi
q.draw("a,d", "bw.pdf", preset="paper", palette="grayscale") # prints in black and white
print(q.last_caption) # also in figure.caption.txt
The paper preset uses serif (STIX) type, removes the dashboard header, scales lines and fonts to the real page size (never below 6 pt), uses a colour-blind-safe palette by default and writes a caption generated from the run: what is shown, the gates, exact versus sampled data and the version.
Research bundles
q = hdqs(2, seed=42).h(0).cx(0, 1)
q.export_bundle("bell_experiment") # a folder, or "bell.zip"
hdqs.grover(3, ["101"], seed=3).export_bundle("grover.zip")
The two kinds of bundle differ, because an algorithm is told in stages rather than one figure:
Register bundle (q.export_bundle) |
Algorithm bundle (r.export_bundle) |
|
|---|---|---|
| Figures | figure.pdf, figure.svg (paper preset), figure.caption.txt |
stages.pdf (one page per stage), summary.png (the answer) |
| Data | data.json, data.csv: state, probabilities, Bloch vectors, entanglement |
data.json: every recorded stage |
| Circuit | circuit.qasm, circuit.tex |
circuit.qasm, circuit.tex (sections boxed) |
| Re-run | experiment.py: the hdqs chain with its seed |
experiment.py: the one-line algorithm call plus the explicit circuit |
| Interactive | explorer.html |
player.html (live player) |
| Record | metadata.json, environment.txt, README.md |
the same, with the algorithm's inputs and result |
metadata.json holds the engine version, seed, shots, mode, inputs, circuit hash and the provenance of every file.
In notebooks
In Jupyter and VS Code a register or algorithm result shows itself: a summary
card with the interactive explorer (or live player) embedded, no .draw()
needed. hdqs.rich_display(False) switches it off.
Browser playground
hdqs.playground("playground.html") # an empty playground with examples
hdqs.playground("mine.html", q) # starts from q.code()
One offline HTML file with an editor that runs hdqs chains in the browser:
gates, measure, if_x/if_z, unitary, load_state, for loops, lists,
complex numbers and print, up to 10 qubits. The circuit, amplitudes, Bloch
spheres, Q-sphere and entanglement update with a gate-by-gate slider, and
errors point at the line. The same code runs unchanged in Python. Algorithm
players have a Playground tab too: Edit & run in the playground loads
r.code().
Algorithm visuals: how it works, not just the circuit
Every algorithm returns its usual result dictionary, which now also has
.draw(), .code() and .circuit. The animation explains the idea behind the
algorithm using the states recorded during that very run, so every picture
matches the returned numbers, and it changes with whatever inputs you give it.
from sia import hdqs
r = hdqs.grover(3, ["101"])
r.draw("grover.gif") # the circuit, then inversion about the mean and the rotation picture
r.draw("grover.html") # live player: change the inputs and re-run, right in the browser
r.draw("grover.png", summary=True) # one slide with the answer
r.code() # the hdqs chain that builds this run's circuit
r.draw("grover.tex") # the circuit in LaTeX, sections boxed (standalone=False: bare environment)
r.lesson("grover.html") # predict, then reveal: a question before each key stage
r.worksheet("grover.pdf") # printable worksheet with a solutions page
r.export_frames("frames", "svg") # every stage as a numbered image
Each animation opens with the circuit built for your input, with the oracle
and other parts labelled. Grover, Deutsch–Jozsa and Simon use real gate-level
oracles (X gates around a multi-controlled Z; one Z per bit when f is linear;
CNOT copies for Simon). r.code() prints that circuit as a runnable
one-import chain (repeated Grover iterations become a loop), and r.circuit
is the program itself.
The last frame carries a result banner (FOUND 101, 15 = 3 × 5,
ABORT · QBER 25%) and every panel says where its numbers come from:
EXACT (from the state), SAMPLED (measurement shots), CLASSICAL (ordinary
computation) or THEORY (a formula).
| Algorithm | What the animation shows |
|---|---|
grover |
Amplitudes reflected about the mean, the 2D rotation picture with its mirrors, success probability |
deutsch, deutsch_jozsa |
Phase kickback turning f(x) into signs, then interference deciding constant vs balanced |
bernstein_vazirani |
Each oracle CNOT flipping one qubit to |−⟩; Hadamards turning the phases into the hidden bits |
simon |
Equations y·s = 0 accumulating while the candidate secrets are crossed out |
qft_demo |
Output qubits turning at ½, ¼, ⅛ … turn per +1, and the output phasors |
phase_estimation |
Kickback onto each counting qubit, the outcome distribution sharpening with precision |
order_finding, shor_demo |
The period of aˣ mod N, QPE peaks at s/r, continued fractions, gcd to the factors |
teleport |
Three Bloch spheres, entanglement links, two classical bits travelling, Bob's correction |
superdense |
Alice's operation choosing one of four Bell states, Bob decoding two bits |
vqe |
Energy converging towards the exact ground energy, the path over the energy landscape |
qaoa_maxcut |
The (γ, β) landscape search, sampled cut sizes, the best cut drawn on the graph |
bb84, e91, qss |
Bases and photons, sifting and the QBER alarm; the CHSH value passing 2; GHZ parity |
repetition_code_demo |
Encoding, a bit flip, the syndrome lighting up, correction and decoding |
interference_report (CRIA) |
Interference recovered as more helper qubits are read |
| Extension | Output | Needs |
|---|---|---|
.html |
Live player: plays the run; the reader can change the inputs and re-run the algorithm in the browser (a built-in simulator, no internet, no Python); Code and Playground tabs; light/dark; SVG and JSON download | — |
.gif |
Animation (speed=, tween= for in-between frames) |
— |
.png .jpg .webp |
Storyboard of every stage, one stage with scene=k, or one slide with summary=True |
— |
.pdf |
One page per stage | — |
.json |
The recorded stages as data | — |
.tex |
The executed circuit as LaTeX quantikz, sections as labelled boxes | — |
.mp4 |
Video, when ffmpeg is installed | ffmpeg |
Teaching. r.lesson("x.html") turns the live player into a lesson: before
each key stage the student predicts what happens (multiple choice, built from
this run's numbers), reads why, and only then sees the stage; the inputs tab
unlocks at the end. r.worksheet("x.pdf") prints the same questions on A4 with
the stage before each one, answer space and a solutions section
(solutions=False for the student copy).
The recording costs only a few numbers per stage; the pictures are made when
.draw() is called. In the browser player, a seed gives a repeatable run, but
sampled results use the browser's own random numbers, not Python's.
Quantum maths: numbers, vectors, matrices and practice
The mathematics underneath quantum computing, with the same one import:
from sia import hdqs
z = hdqs.cnum(1, 1)
(z * 1j).draw() # both arrows on the complex plane; the angles add
z.explain() # modulus √2, argument π/4, polar form √2·e^(iπ/4), conjugate
hdqs.vec([1, 1j]).normalize() # vec(1/√2, i/√2)
hdqs.mat([[2, 1], [1, 2]]).draw() # the grid, unit circle and square it transforms; eigen directions
hdqs.mat([[0, -1j], [1j, 0]]).eig() # eigenvalues ±1 with their eigenvectors
Values are shown exactly ((1+i)/√2, 3√13, 3π/4), inner products follow the
physics convention ⟨u|v⟩ = Σ ūₖvₖ, and every object has .draw() and .explain().
Practice problems with exact answers and worked solutions:
ps = hdqs.practice("complex", n=10, level=2, seed=7)
print(ps) # the problems
ps.check(1, "(1+i)/√2") # Correct ✓ / Not yet
ps.solution(1) # the worked steps
ps.draw("complex.html") # interactive page: type answers, check, see solutions, print
hdqs.practice("matrices", n=8, students=40, seed=1).draw("class.pdf,key.csv") # one set per student + keys
| Topic | Level 1 | Level 2 | Level 3 |
|---|---|---|---|
complex |
add, subtract, multiply, conjugate, modulus, ×i | divide, argument, polar form, r·e^(iθ) | De Moivre |
vectors |
inner product, norm, linear combination, orthogonality | normalise (complex entries) | projection onto a unit vector |
matrices |
product, matrix × vector, determinant, trace | inverse, dagger, Hermitian?, unitary? | commutators of Pauli matrices |
eigen |
eigenvalues | eigenvectors | Hermitian eigenvalues |
tensor |
basis-state index, u ⊗ v | A ⊗ B, product or entangled? |
topic="mixed" draws from all of them. Problems never repeat within a set and
are new across a class while the pool allows; only clean values are used, so no
answer is a long decimal. Students may type 1+2i, (1+i)/√2, sqrt(2), 3π/4
or 3pi/4, e^(iπ/4), or a decimal such as 0.707; eigenvectors are accepted as
any non-zero multiple and eigenvalues in any order. The same seed always gives the
same set, so a key can be regenerated at any time.
Hindi and Telugu. English is the default. lang="hi" or lang="te" (on
practice(), .draw() of a problem set, and .explain()) uses the terms of the
school and intermediate textbooks (NCERT Hindi medium; Telugu Akademi), keeping the
English term in brackets where a quantum term has no settled form; hdqs.glossary("te")
lists them. PDF worksheets are English; for Hindi or Telugu, print the HTML page.
Dirac notation and quantum mechanics
Kets, bras and operators use the same exact display and .draw() / .explain()
as the maths objects. Units: ħ = 1; hdqs.pauli("X") is σx, and hdqs.spin("x") is the
spin observable along x, measured as ±1.
from sia import hdqs
plus, minus = hdqs.ket("+"), hdqs.ket("-") # also "0", "1", "+i", "-i", "01+", "phi+", "psi-", "ghz", "w"
plus.dag() @ minus # ⟨+|−⟩ = 0
hdqs.ket("0") @ hdqs.bra("1") # outer product |0⟩⟨1|, a matrix
hdqs.HDQS(2).h(0).cx(0, 1).ket() # '(1/√2)|00⟩ + (1/√2)|11⟩' (latex=True for \ket{})
Z = hdqs.pauli("Z")
Z.expect("+"), Z.variance("+") # 0, 1
hdqs.spin("x").measure("0").explain().draw() # outcomes, Born probabilities, states after
hdqs.evolve("X", "0", times=hdqs.np.linspace(0, 3.14, 60)).draw() # Rabi curve and Bloch path
hdqs.uncertainty("X", "Y", "0") # ΔA·ΔB ≥ ½|⟨[A, B]⟩|, checked
hdqs.stern_gerlach(["z", "x", "z"]).draw() # sequential analysers, every path and its probability
Checking and research tools
q = hdqs.HDQS(2).h(0).cx(0, 1)
q.matrix() # the circuit's unitary, column j = result on |j⟩
hdqs.equivalent(hdqs.HDQS(1).h(0).z(0).h(0), hdqs.HDQS(1).x(0)) # True (global phase ignored)
hdqs.compare(q, "phi+").explain().draw() # fidelity, trace distance, probabilities, Bloch vectors
hdqs.sweep(lambda t: hdqs.HDQS(2).ry(0, t).cx(0, 1),
hdqs.np.linspace(0, 6.28, 41), observables=["ZI", "ZZ", "XX"]).draw().save("sweep.csv")
hdqs.selfcheck(q) # same program through every engine: they must agree
selfcheck replays one chain with the density-matrix, MPS and (for Clifford circuits)
stabilizer engines, checks that optimize() keeps the matrix, that the inverse
returns |0…0⟩, the OpenQASM 3 round trip, and agreement with Qiskit when it is
installed. Checks that do not apply, or need a package you do not have, are listed as
skipped.
Practice beyond maths, and a whole course
hdqs.practice also takes "dirac" (inner and outer products of named kets, Born
probabilities, change of basis, density matrices, partial trace) and "physics"
(expectation values, variance, measurement on unnormalised states, relative phase,
spin at an angle, Rabi evolution, uncertainty products), at levels 1-3, with the same
checking, class sets and languages.
hdqs.course("my_course") # open my_course/index.html
hdqs.course("my_course_te", lang="te")
course() writes one offline folder: an index page that walks from quantum maths
(5 topics × 3 levels) through Dirac notation and quantum mechanics to quantum computing,
the eleven explorers, the circuit playground, eleven algorithm lessons and a three-language glossary. Each
practice page links back to the index, and the index shows your best score on each page
(kept in the browser).
Explorers: touch, drag and rotate
Each explorer is one offline HTML page. 3D views turn with a drag or a finger, zoom with a pinch or the wheel, and reset with a double tap; they work on phones.
hdqs.explore() # the list
hdqs.explore("phasor") # rotating e^(iωt) draws cosine and sine waves; two phasors: beats, cancelling
hdqs.explore("phasor", state="square") # Fourier series: phasors at 1, 3, 5… × ω, head to tail, build a square wave (Gibbs ripple)
hdqs.explore("complex") # drag z and w: add, multiply (angles add), divide, conjugate, powers
hdqs.explore("matrix") # drag the columns of M: grid, determinant as area, eigen directions
hdqs.explore("double_slit") # a 2D Schrödinger wave through two slits: ripples, phase, |ψ|², 3D surface
hdqs.explore("bloch", state="+") # gates as rotations, U·ψ = ψ′ as matrices, ρ = |ψ⟩⟨ψ|, measurement and collapse
hdqs.explore("entanglement") # product → Bell, 4×4 ρ and both partial traces, Alice then Bob, CHSH
hdqs.explore("hilbert") # 1–4 qubits: gates acting on the state vector and the density matrix
hdqs.explore("wavepacket") # 1D Schrödinger: free spreading, tunnelling, particle in a box, oscillator
hdqs.explore("fourier") # the QFT as sums of phasors; period finding peaks at multiples of N/r
hdqs.explore("rabi") # a spin in a field: Larmor precession, Rabi oscillation, Ramsey fringes
hdqs.explore("stern_gerlach") # one atom at a time through 1–3 magnets; z → x → z forgets the first result
hdqs(2).h(0).cx(0, 1).explore() # any 1–4 qubit register opens in the Hilbert-space explorer
hdqs.mat([[0, 1], [1, 0]]).explore() # also hdqs.cnum(...).explore()
Hilbert space ("hilbert"): choose a qubit and press a gate. The page shows the full
2ⁿ×2ⁿ matrix multiplying the state vector, one output amplitude built from its
contributions (arrows head to tail, so cancellation is visible), the amplitudes as phase
wheels or waves, each qubit's reduced Bloch vector, the Q-sphere, the state-vector table
and the density matrix (whole register or one qubit) with purity and entropies. Gates
include H, X, Y, Z, S, T, √X, Rx/Ry/Rz/P(θ), controlled versions and SWAP; noise channels
(dephasing, depolarizing, amplitude damping) and measurement act on ρ. Every step can be
undone, examples load in one tap (Bell, GHZ, Grover, QFT, decoherence…), and
"copy as code" gives the hdqs chain that rebuilds the circuit.
Double slit: the wave is a real solution of the 2D Schrödinger equation (Visscher's staggered leapfrog, absorbing edges), shown as ripples (crest and trough), as brightness and phase, as |ψ|², or as a lit 3D surface. One slit, both, or a which-path detector: the path qubit's coherence γ sets the fringe visibility, and the predicted and measured visibility are shown side by side. Particles arrive one at a time and build the pattern.
Every explorer has a toolbar: light/dark, undo, copy link (the link restores the
exact settings), picture (PNG of all panels) and record video (WebM).
lang="hi" or "te" translates the title, guidance and every control label, using the
standard scientific terms (with the English term in brackets where it helps); symbols
and formulas stay as they are. hdqs.course() includes all eleven explorers, each placed
with the step it belongs to.
Interoperability
OpenQASM 3 via hdqs.from_qasm3(source) and q.to_qasm3().
Optional adapters: hdqs.to_qiskit, hdqs.run_aer, hdqs.to_pennylane.
HDQS server client
The same hdqs name reaches the HDQS quantum server. A whole number builds the
local simulator; any other call connects to the server:
from sia import hdqs
client = hdqs(api_key="YOUR_TOKEN")
client.qbt_create(num_qubits=2)
client.qbt_run(["h 0", "cnot 0 1"])
print(client.qbt_measure([0, 1]))
An API token is issued by Sia Software Innovations. The server address can be
changed without reinstalling, using the SIA_HDQS_HOST and SIA_HDQS_PORT
environment variables. If the server is unreachable, client calls raise
hdqs.HDQSError; the offline simulator is unaffected.
Entities: ntt
from sia import ntt
Person = ntt("name", "age").computed("group", "if (1) > 17: adult | else: minor")
p = Person("Ravi", 20)
print(p.name, p.group) # Ravi adult
Templates refer to attributes by position, (0), (1), and so on. Conditions
and validators are evaluated through a restricted expression checker, never
eval.
Enterprise logic: els
from sia import els
program = """
*sia
DATA total TYPE I.
total = 40 + 2.
WRITE total.
sia*
"""
print(els(program)) # 42
For multi-block programs, share state with env = els.make_env() and call
els(block, env). An interactive prompt is available through els.repl().
Optional dependencies
| Extra | Installs | Enables |
|---|---|---|
torch |
PyTorch | Trainable layers, CUDA acceleration |
scipy |
SciPy | Sparse observable matrices |
interop |
Qiskit, Qiskit Aer, PennyLane | Adapters |
full |
torch, scipy | Everything except the adapters |
all |
Everything above | Everything |
Matplotlib and openqasm3 are regular dependencies since 1.5.4; the old
[plot] and [qasm] extras still install without error.
A feature whose dependency is missing raises an ImportError naming the
package to install. hdqs.capabilities() reports what is available.
Conventions
- Qubit 0 is the most significant bit: in
'01', qubit 0 is0. Qiskit uses the opposite order; the adapters convert automatically. measure()collapses the state;sample()andprobabilities()do not.- Memory grows exponentially with qubit count in the statevector and
density-matrix modes. Above the 1 GiB default budget a register becomes
program-only (
q.is_lazy): useq.stabilizer()orq.mps(), or passmax_memory_mb=to allow a larger full state.
Licensing
sia-script is proprietary software of Sia Software Innovations Private Limited,
with one exception: the quantum simulator, sia/hdqs_engine.py, is released
under the MIT License. See LICENSE.md for the full terms of both.
Citation
If you use the CRIA interference-accessibility tools in research, please cite:
Seshabattara Venkata, N. S. D. N. Cardinality-Resolved Interference Accessibility in Multipartite Quantum Systems. Zenodo (2026). https://doi.org/10.5281/zenodo.23180889
Support
Sia Software Innovations Private Limited
Email: info@siasoftwareinnovations.com
Website: https://www.siasoftwareinnovations.com
Metadata
Release files for sia-script 1.5.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sia_script-1.5.6.tar.gz | 568.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sia_script-1.5.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / sia_script-1.5.6.tar.gz
| Download URL | sia_script-1.5.6.tar.gz |
|---|---|
| Size | 568.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab835ec9660cf4ca1f3d49a555b7128060bda34d540020d7f4344de40ebb02e4
|
|
BLAKE2b-256 checksum How to use checksums |
c63341bfe0a02bfe3e7aefc4a1486b2d5c1655c621d1e2f08ed973713310e7c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.4
|
Release files / sia_script-1.5.6-py3-none-any.whl
| Download URL | sia_script-1.5.6-py3-none-any.whl |
|---|---|
| Size | 545.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
50e08334cd06bba72269622b543f62a3f0c80faf00a0ee75f96433091ed6600b
|
|
BLAKE2b-256 checksum How to use checksums |
559b713c65c98a0ef0b22a9e6f3fb748949a0516a2498f0bdd454b3666463ce6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.4
|