- Native Android app (Kotlin + Jetpack Compose), 1-16 qubits - Stochastic hidden-variable engine (ordinary bits + stochastic transition law) - Full gate set incl. Givens G, beam splitter BS, CSWAP - LaTeX-built help PDF viewable from Settings - Launcher icon (white border removed) with old icon backed up - Published by foleosoft |
||
|---|---|---|
| app | ||
| gradle | ||
| help | ||
| icon-backup | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
QAnsel Mobile
A Stochastic Quantum Computer Simulator
A self-contained native Android app (Kotlin + Jetpack Compose) that simulates quantum circuits entirely on the device, with no server and no network. It treats every qubit as an ordinary bit with a definite value at all times, and evolves those bits through a stochastic transition law that reproduces the Born statistics over many shots.
Published by foleosoft.
What to install
You need a JDK and the Android SDK. The easiest path is Android Studio, which bundles the SDK and downloads Gradle automatically via the wrapper.
Option A — Android Studio (recommended)
- Install Android Studio (any recent version, e.g. Ladybug or newer): https://developer.android.com/studio
- During first launch it installs the Android SDK, build-tools, and a JDK. Accept the license agreements.
- Open this folder (
QAnsel-Mobile) in Android Studio. - Let the Gradle sync finish, then press Run (▶) with an emulator or a plugged-in phone (USB debugging enabled).
Gradle JDK note: this project pins Gradle 8.9, which runs on JDK 17–21. Recent Android Studio releases bundle a newer JDK (e.g. 25) as their embedded runtime. If Gradle sync reports an "unsupported class file version" or "unrecognized JDK" error, set the Gradle JVM to a 17–21 JDK: Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JVM and pick your system's JDK 17/21 (on Debian/Ubuntu that is
/usr/lib/jvm/java-21-openjdk-amd64).
Option B — command line (no IDE)
You need:
- JDK 17 or newer (JDK 21 works):
sudo apt install openjdk-17-jdk # Debian/Ubuntu - Android SDK command-line tools — install
sdkmanagerand then the platform + build-tools this project uses:sdkmanager "platforms;android-35" "build-tools;35.0.0" "platform-tools" sdkmanager --licenses - Point Gradle at your SDK (
local.properties, created automatically by Android Studio, or manually):sdk.dir=/path/to/Android/Sdk
Then build and install:
./gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk
The Gradle wrapper (gradlew) downloads the correct Gradle (8.9) and all
dependencies on first run, so no global Gradle install is needed.
Project layout
QAnsel-Mobile/
├── gradle/ # wrapper + version catalog
├── app/
│ ├── build.gradle.kts
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── res/ # theme, strings, launcher icon
│ │ └── java/com/qansel/mobile/
│ │ ├── MainActivity.kt
│ │ ├── engine/ # pure Kotlin simulator (no Android deps)
│ │ │ ├── Complex.kt # complex numbers + matrices
│ │ │ ├── Rng.kt # seeded xorshift128+ PRNG
│ │ │ ├── Gates.kt # gate catalogue + unitaries
│ │ │ ├── Circuit.kt # circuit/grid data model
│ │ │ ├── Qasm.kt # OpenQASM 2.0 parser + generator
│ │ │ └── Simulator.kt # hidden-variable VM + IPF
│ │ └── ui/ # Jetpack Compose UI
│ │ ├── App.kt, HomeScreen.kt, CircuitViewModel.kt
│ │ ├── CircuitView.kt # orientation-aware circuit canvas
│ │ ├── GatePalette.kt, CodeEditor.kt
│ │ ├── ResultsPanel.kt, SettingsSheet.kt
│ │ └── theme/Theme.kt
│ └── test/ # JUnit tests for the engine
└── README.md
Features
- On-device CPU simulation up to 16 qubits. Memory is the 2ⁿ state vector (16 qubits = 65,536 amplitudes ≈ 1 MB) and each gate is O(2ⁿ), so 16 qubits is comfortable on any modern phone.
- Stochastic hidden-variable engine — definite bits per qubit evolving via unistochastic transitions (IPF), with a per-hop noise / decoherence control.
- Circuit editor — tap-to-place gates on a grid of qubit wires, including multi-qubit gates (tap control(s) then target in one column), rotation angles, measurement, reset, and barrier.
- Gate set — H, X, Y, Z, S, S†, T, T†, I; RX/RY/RZ; CX, CZ, CY, CH, SWAP, CCX, CSWAP; Givens G(θ) and beam splitter BS; measure, reset, set, barrier.
- Single vs Shots run modes — single streams a per-instruction trace (hidden bits → classical bits); shots builds an outcome histogram.
- OpenQASM 2.0 editor — generate the circuit to source, edit it, and rebuild
the grid from source (a supported subset, incl.
u1/u2/u3andif (c==k)). - Settings — qubit count, time steps, shots, random seed, noise, bit order (q[0] = MSB or LSB), theme (auto/light/dark), track direction, playback speed.
- Save / load — save and restore the full state (circuit, code, results) under a name, plus PNG circuit export and CSV results export.
- Built-in help — a LaTeX-built PDF manual viewable from Settings.
The mobile layout (the hard part)
The app presents a lot of information, so it is organized into collapsible sections, each with a show/hide toggle in the toolbar: Gates, Code, and Results. The circuit canvas always keeps the remaining flexible space.
The circuit's tracks rotate with the phone orientation:
| Orientation | Tracks | Time flows | Why |
|---|---|---|---|
| Portrait | vertical wires | top → bottom | the tall axis holds circuit depth |
| Landscape | horizontal wires | left → right | the wide axis holds circuit depth |
Auto follows the sensor; you can force H (horizontal) or V (vertical)
from the toolbar or Settings. The canvas pans in both axes for larger circuits.
How the engine works
The VM keeps three things per shot:
- Quantum state — a full 2ⁿ complex amplitude vector (the "Born" layer).
- Hidden bits — n definite bit values, one per qubit.
- Classical bits — measurement results.
For a unitary gate U on k qubits (dimension d = 2^k):
- Compute the marginal Born distribution
p_beforeover the gate's subspace. - Apply U to the amplitude vector.
- Compute
p_after. - Build the unistochastic matrix
S = |U|²(element-wise absolute square). - Find the column-stochastic transition
Γ = diag(u)·S·diag(v)withΓ · p_before = p_after, closest toSin KL-divergence, via IPF:v[0] = 1 u[i] = p_after[i] / Σⱼ S[i][j]·v[j]·p_before[j] v[j] = 1 / Σᵢ S[i][j]·u[i] - Sample the next hidden configuration from column
curofΓ(mixed with a uniform distribution whennoise > 0).
Measurement is a passive reveal — it copies the already-definite hidden bit
into the classical register and collapses the amplitude vector, never resampling.
This is the same semantics as desktop QAnsel's qvm.
Tests
Engine unit tests (pure JVM, run with ./gradlew test):
GatesTest— every built-in gate is unitary; CX/SWAP matrices spot-checked.SimulatorTest— Bell → only 00/11, X flips, H is uniform, GHZ → only 000/111, seed reproducibility, and a 16-qubit smoke test.QasmTest— parser, angle expressions, and code ↔ circuit round-trip.
Known limitations / future work
- Qubit limit is 16; the engine constant
Gates.MAX_QUBITScan be raised if you accept more memory/time. - The QASM parser covers the generated subset plus
u1/u2/u3and single-registerif (c==k)conditionals; customgatedefinitions andcrz/cu1/cu3are not supported yet. - No Bloch-sphere view (v1 streams ordinary bits, not complex amplitudes).