A mobile version of QAnsel, the stochastic quantum computer simulator, designed to run entirely locally on a phone CPU.
Find a file
amihart 74a8127030 Initial commit: QAnsel Mobile, a stochastic quantum computer simulator
- 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
2026-10-24 21:46:05 -04:00
app Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
gradle Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
help Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
icon-backup Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
.gitignore Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
build.gradle.kts Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
gradle.properties Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
gradlew Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
gradlew.bat Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
README.md Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00
settings.gradle.kts Initial commit: QAnsel Mobile, a stochastic quantum computer simulator 2026-10-24 21:46:05 -04:00

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.

  1. Install Android Studio (any recent version, e.g. Ladybug or newer): https://developer.android.com/studio
  2. During first launch it installs the Android SDK, build-tools, and a JDK. Accept the license agreements.
  3. Open this folder (QAnsel-Mobile) in Android Studio.
  4. 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 sdkmanager and 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/u3 and if (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:

  1. Quantum state — a full 2ⁿ complex amplitude vector (the "Born" layer).
  2. Hidden bits — n definite bit values, one per qubit.
  3. Classical bits — measurement results.

For a unitary gate U on k qubits (dimension d = 2^k):

  1. Compute the marginal Born distribution p_before over the gate's subspace.
  2. Apply U to the amplitude vector.
  3. Compute p_after.
  4. Build the unistochastic matrix S = |U|² (element-wise absolute square).
  5. Find the column-stochastic transition Γ = diag(u)·S·diag(v) with Γ · p_before = p_after, closest to S in 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]
    
  6. Sample the next hidden configuration from column cur of Γ (mixed with a uniform distribution when noise > 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_QUBITS can be raised if you accept more memory/time.
  • The QASM parser covers the generated subset plus u1/u2/u3 and single-register if (c==k) conditionals; custom gate definitions and crz/cu1/cu3 are not supported yet.
  • No Bloch-sphere view (v1 streams ordinary bits, not complex amplitudes).