quantum-forge 2.7.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Real quantum mechanics for game developers. Superposition, entanglement, and interference powered by a compiled C++ quantum simulator running via WebAssembly.
4
4
 
5
- This is the core package: WASM loader, quantum property manager, and Vite plugin. For the full game framework (engine, rendering, input, audio, and more), install [`quantum-forge-engine`](https://www.npmjs.com/package/quantum-forge-engine) instead. It depends on this package, so one install gets both.
5
+ This is the core package: WASM loader, quantum property handles, and Vite plugin. For the full game framework (engine, rendering, input, audio, and more), install [`quantum-forge-engine`](https://www.npmjs.com/package/quantum-forge-engine) instead. It depends on this package, so one install gets both.
6
6
 
7
7
  ## Install
8
8
 
@@ -26,46 +26,52 @@ export default defineConfig({
26
26
 
27
27
  > **ESM note:** If using `vite.config.js` (not `.ts` or `.mjs`), add `"type": "module"` to your `package.json`.
28
28
 
29
- ### 2. Use Quantum Mechanics
29
+ ### 2. Declare a quantum property
30
30
 
31
31
  ```typescript
32
- import { ensureLoaded, getModule, QuantumPropertyManager } from "quantum-forge/quantum";
32
+ import { ensureLoaded, quantum } from "quantum-forge/quantum";
33
33
 
34
- await ensureLoaded(); // once, before any quantum call
34
+ await ensureLoaded(); // once, before the first quantum() call
35
35
 
36
- const qpm = new QuantumPropertyManager({ dimension: 2 });
37
- const m = getModule(); // gates and measurement live here, not on the manager
38
-
39
- const qubit = qpm.acquireProperty(); // |0⟩, from the pool
40
- m.hadamard(qubit); // equal superposition
36
+ const color = quantum(["red", "green", "blue"]); // a qutrit, starts "red"
37
+ color.superpose(); // equal superposition (alias for hadamard())
41
38
 
42
39
  // Read without collapsing
43
- m.probabilities([qubit]);
44
- // [{ probability: 0.5, qudit_values: [0] }, { probability: 0.5, qudit_values: [1] }]
40
+ color.probability("green"); // 1/3
41
+ color.probabilities();
42
+ // [{ value: "red", probability: 1/3 }, { value: "green", ... }, { value: "blue", ... }]
45
43
 
46
- // Measure (collapses to 0 or 1)
47
- const [value] = m.measure_properties([qubit]);
44
+ // Measure (collapses to one value)
45
+ const seen = color.measure(); // "red", "green" or "blue"
48
46
 
49
- // Return the handle to the pool, reset to |0⟩
50
- qpm.releaseProperty(qubit, value);
47
+ // End its life. dispose() measures, then frees the qudit for the next quantum() call.
48
+ color.dispose();
51
49
  ```
52
50
 
53
- `QuantumPropertyManager` owns handles: `acquireProperty`, `releaseProperty`, `setProperty` / `getProperty` / `deleteProperty` by id, and `getModule()`. Games usually extend it and wrap the module calls in game-specific methods.
51
+ A property is declared by the values it can take, and the dimension is how many there are.
52
+ `quantum(3)` is the numeric form, with values `0`, `1`, `2`. A property needs at least two
53
+ values. A `using` declaration disposes the handle at the end of the scope; it needs TypeScript
54
+ 5.2 or newer with `"ESNext.Disposable"` in the tsconfig `lib`. Code that never writes `using`
55
+ needs neither.
54
56
 
55
57
  ### 3. Entanglement
56
58
 
59
+ Entanglement is what an interaction leaves behind. A gate that touches two properties is an
60
+ interaction:
61
+
57
62
  ```typescript
58
- const a = qpm.acquireProperty();
59
- const b = qpm.acquireProperty();
63
+ import { quantum, measure } from "quantum-forge/quantum";
60
64
 
61
- m.cycle(a); // a = |1⟩
62
- m.i_swap(a, b, 0.5); // half iSwap: exactly one of the pair ends up |1⟩
65
+ const a = quantum([false, true]).flip(); // a = true
66
+ const b = quantum([false, true]); // b = false
67
+ a.iSwap(b, 0.5); // half iSwap: exactly one of the pair ends up true
63
68
 
64
- const [va, vb] = m.measure_properties([a, b]);
65
- // va + vb === 1, every time
69
+ const [va, vb] = measure(a, b); // one step, both collapse
70
+ // va !== vb, every time
66
71
  ```
67
72
 
68
- Predicated gates entangle too. `m.shift(b, undefined, [a.is(1)])` is a CNOT: `b` flips only where `a` is `|1⟩`. Predicates are the third argument, so pass `undefined` as the fraction to get the discrete gate.
73
+ So is a gate whose predicate reads another property. `b.flip({ when: [a.is(true)] })` is a
74
+ CNOT: `b` flips only where `a` is `true`. `a.is(1)` builds the same predicate by index.
69
75
 
70
76
  ## Editions
71
77
 
@@ -103,26 +109,36 @@ Node 22 or newer.
103
109
 
104
110
  | Export | Contents |
105
111
  |--------|----------|
106
- | `quantum-forge/quantum` | `ensureLoaded`, `startBackgroundLoad`, `isReady`, `getModule`, `QuantumPropertyManager`, `QuantumRecorder`, `useQuantumForgeBuild`, `setWasmBasePath`, `getVersion`, `getMaxDimension`, `getMaxQudits`, `getMaxStateSize`, `getAttribution`, `registerServiceWorker`, `OP` |
112
+ | `quantum-forge/quantum` | `quantum`, `Quantum`, `measure`, `forcedMeasure`, `probabilities`, `densityMatrix`, `measureWhen`, `forcedMeasureWhen`, `probabilityWhen`, `phaseRotate`, `isQuantum`, `observeQuantum`, `clearQuantumCache`, `QuantumRecorder`, `ensureLoaded`, `startBackgroundLoad`, `isReady`, `useQuantumForgeBuild`, `setWasmBasePath`, `getVersion`, `getMaxDimension`, `getMaxQudits`, `getMaxStateSize`, `getAttribution`, `registerServiceWorker`, `OP` |
107
113
  | `quantum-forge/logging` | `Logger` |
108
114
  | `quantum-forge/vite-plugin` | `quantumForgeVitePlugin` |
109
115
 
110
116
  ## Gates
111
117
 
112
- All gates are functions on the module from `getModule()`. Each takes the target property, an optional `fraction`, and optional `predicates`.
113
-
114
- | Gate | Qudits | Description |
115
- |------|--------|-------------|
116
- | `hadamard` | 1 | Equal superposition |
117
- | `cycle` | 1 | \|0⟩→\|1⟩→\|2⟩→\|0⟩ (a NOT at dimension 2) |
118
- | `shift` (`x`) | 1 | Inverse of cycle; same as cycle at dimension 2 |
119
- | `clock` (`z`) | 1 | Phase rotation |
120
- | `y` | 1 | Pauli Y, dimension 2 only |
121
- | `i_swap` | 2 | Entangling swap; `fraction` is required |
122
- | `swap` | 2 | Value swap |
123
- | `phase_rotate` | any | Phase on the states matching the predicates |
124
-
125
- Measurement: `measure_properties`, `measure_predicate`, `forced_measure_properties`. Read-only: `probabilities`, `predicate_probability`, `reduced_density_matrix`. Omit `fraction` for the discrete gate; pass a number for the continuous variant (`0.5` is the square root of the gate).
118
+ Gates are methods on the handle. Each alias runs exactly the same gate as the physics name
119
+ beside it.
120
+
121
+ | Gate | Alias | Qudits | Description |
122
+ |------|-------|--------|-------------|
123
+ | `hadamard` | `superpose` | 1 | Equal superposition |
124
+ | `inverseHadamard` | | 1 | Undoes `hadamard` |
125
+ | `cycle` | `next`, and `flip` on qubits | 1 | \|0⟩→\|1⟩→\|2⟩→\|0⟩ (a NOT at dimension 2) |
126
+ | `shift` | `previous` | 1 | Inverse of cycle; same as cycle at dimension 2 |
127
+ | `clock` | `phase` | 1 | Phase rotation |
128
+ | `x`, `z` | | 1 | Pauli X (same as `shift`) and Pauli Z (same as `clock`) |
129
+ | `y` | | 1 | Pauli Y, dimension 2 only |
130
+ | `iSwap(other, fraction)` | | 2 | Entangling swap; `fraction` is required |
131
+ | `swap(other)` | | 2 | Value swap |
132
+ | `phaseRotate(angle, { when })` | | any | Free function: phase on the part of the state where the predicates hold |
133
+
134
+ Every gate except `inverseHadamard`, `swap` and `iSwap` takes an optional fraction first. An
135
+ omitted fraction, or exactly 1, is the discrete gate; any other number is the continuous
136
+ version, and 0.5 is the square root of the gate. Predicates go last, in `{ when: [...] }`.
137
+
138
+ Measurement: `prop.measure()`, `measure(...props)`, `measureWhen(preds)`, and the forced
139
+ variants for replays and tests, which throw if the forced value has zero probability.
140
+ Read-only: `prop.probability(value)`, `prop.probabilities()`,
141
+ `probabilities(...props)`, `probabilityWhen(preds)`, `densityMatrix(...props)`.
126
142
 
127
143
  ## Documentation
128
144