quantum-forge 2.0.2 → 2.0.4
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/LICENSE.md +18 -0
- package/README.md +115 -0
- package/dist/lib/quantum.js +1 -1
- package/dist/lib/quantum.js.map +1 -1
- package/dist/lib/vite-plugin.js +36 -26
- package/dist/lib/vite-plugin.js.map +1 -1
- package/dist/quantum-forge-qubit/quantum-forge-web-api.d.mts +61 -0
- package/dist/quantum-forge-qubit/quantum-forge-web-api.mjs +202 -0
- package/dist/quantum-forge-qubit/quantum-forge-web-esm.mjs +14 -0
- package/dist/quantum-forge-qubit/quantum-forge-web-esm.wasm +0 -0
- package/dist/quantum-forge-web-esm.mjs +1 -1
- package/dist/quantum-forge-web-esm.wasm +0 -0
- package/package.json +3 -5
- package/LICENSING.md +0 -33
- package/dist/quantum-forge-web-0.3.0.tgz +0 -0
- /package/{LICENSE-BINARY.md → dist/LICENSE-BINARY.md} +0 -0
package/LICENSE.md
CHANGED
|
@@ -19,3 +19,21 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Split Licensing
|
|
26
|
+
|
|
27
|
+
This package uses a split licensing model:
|
|
28
|
+
|
|
29
|
+
- **TypeScript source code** is MIT licensed (this file).
|
|
30
|
+
- **Compiled binaries** (WebAssembly `.wasm` files in `dist/`) are proprietary.
|
|
31
|
+
See [`dist/LICENSE-BINARY.md`](dist/LICENSE-BINARY.md) for the full terms.
|
|
32
|
+
|
|
33
|
+
The short version: the binaries are **free** for applications under $100K/year
|
|
34
|
+
in revenue, with a "Powered by Quantum Forge" attribution requirement. Above
|
|
35
|
+
$100K, contact hello@quantum.dev for a commercial license.
|
|
36
|
+
|
|
37
|
+
The source code is the API you build with — we want it open so you can read,
|
|
38
|
+
debug, and contribute. The compiled quantum simulator is how we sustain the
|
|
39
|
+
project.
|
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# quantum-forge
|
|
2
|
+
|
|
3
|
+
Real quantum mechanics for game developers. Superposition, entanglement, and interference powered by a compiled C++ quantum simulator running via WebAssembly.
|
|
4
|
+
|
|
5
|
+
This is the core package — WASM loader, quantum property manager, and Vite plugin. For the full game framework (engine, rendering, input, audio, etc.), install [`quantum-forge-engine`](https://www.npmjs.com/package/quantum-forge-engine) instead.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install quantum-forge
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Configure Vite
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// vite.config.ts
|
|
19
|
+
import { defineConfig } from "vite";
|
|
20
|
+
import { quantumForgeVitePlugin } from "quantum-forge/vite-plugin";
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
plugins: [quantumForgeVitePlugin()],
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> **ESM note:** If using `vite.config.js` (not `.ts` or `.mjs`), add `"type": "module"` to your `package.json`.
|
|
28
|
+
|
|
29
|
+
### 2. Use Quantum Mechanics
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { ensureLoaded, QuantumPropertyManager } from "quantum-forge/quantum";
|
|
33
|
+
|
|
34
|
+
// Initialize WASM (call once at startup)
|
|
35
|
+
await ensureLoaded();
|
|
36
|
+
|
|
37
|
+
// Create a property manager
|
|
38
|
+
const qpm = new QuantumPropertyManager({ dimension: 2 });
|
|
39
|
+
|
|
40
|
+
// Create a qubit and put it in superposition
|
|
41
|
+
const qubit = qpm.acquireProperty();
|
|
42
|
+
qpm.hadamard(qubit);
|
|
43
|
+
|
|
44
|
+
// Read probabilities (no collapse)
|
|
45
|
+
const probs = qpm.probabilities(qubit); // [~0.5, ~0.5]
|
|
46
|
+
|
|
47
|
+
// Measure (collapses to 0 or 1)
|
|
48
|
+
const [value] = qpm.measureProperties([qubit]);
|
|
49
|
+
|
|
50
|
+
// Recycle for reuse
|
|
51
|
+
qpm.releaseProperty(qubit, value);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 3. Entanglement
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const a = qpm.acquireProperty();
|
|
58
|
+
const b = qpm.acquireProperty();
|
|
59
|
+
|
|
60
|
+
qpm.hadamard(a);
|
|
61
|
+
qpm.iSwap(a, b); // Entangle — measuring one determines the other
|
|
62
|
+
|
|
63
|
+
const [va, vb] = qpm.measureProperties([a, b]);
|
|
64
|
+
// va and vb are always anti-correlated
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Editions
|
|
68
|
+
|
|
69
|
+
Two WASM builds are included:
|
|
70
|
+
|
|
71
|
+
| Edition | Dimensions | Max Qudits | Use Case |
|
|
72
|
+
|---------|-----------|------------|----------|
|
|
73
|
+
| **Qutrit** (default) | 2–3 | 12 | Games using qutrits (3-state quantum digits) |
|
|
74
|
+
| **Qubit** | 2 | 20 | Games needing more qubits at dimension 2 |
|
|
75
|
+
|
|
76
|
+
To use the Qubit Edition:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { useQuantumForgeBuild, ensureLoaded } from "quantum-forge/quantum";
|
|
80
|
+
|
|
81
|
+
useQuantumForgeBuild("qubit"); // Call before ensureLoaded()
|
|
82
|
+
await ensureLoaded();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Package Exports
|
|
86
|
+
|
|
87
|
+
| Export | Contents |
|
|
88
|
+
|--------|----------|
|
|
89
|
+
| `quantum-forge/quantum` | `ensureLoaded`, `QuantumPropertyManager`, `QuantumRecorder`, `useQuantumForgeBuild` |
|
|
90
|
+
| `quantum-forge/logging` | `Logger` |
|
|
91
|
+
| `quantum-forge/vite-plugin` | `quantumForgeVitePlugin` |
|
|
92
|
+
|
|
93
|
+
## Gates
|
|
94
|
+
|
|
95
|
+
| Gate | Qudits | Description |
|
|
96
|
+
|------|--------|-------------|
|
|
97
|
+
| `hadamard` | 1 | Equal superposition |
|
|
98
|
+
| `cycle` | 1 | Deterministic rotation: \|0⟩→\|1⟩→\|2⟩→\|0⟩ |
|
|
99
|
+
| `clock` (Z) | 1 | Phase rotation |
|
|
100
|
+
| `shift` (X) | 1 | Value shift |
|
|
101
|
+
| `y` | 1 | Y gate (qubit-only) |
|
|
102
|
+
| `iSwap` | 2 | Entangling swap |
|
|
103
|
+
| `swap` | 2 | Value swap |
|
|
104
|
+
|
|
105
|
+
All gates support fractional application and conditional predicates.
|
|
106
|
+
|
|
107
|
+
## Documentation
|
|
108
|
+
|
|
109
|
+
- [Full documentation](https://docs.quantum.dev)
|
|
110
|
+
- [Developer site](https://quantum.dev)
|
|
111
|
+
- [Discord](https://discord.gg/quantumforge)
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
TypeScript source: MIT (see [LICENSE.md](./LICENSE.md)). WASM binaries: proprietary — free for apps under $100K annual revenue with attribution. See [dist/LICENSE-BINARY.md](./dist/LICENSE-BINARY.md) for binary terms.
|
package/dist/lib/quantum.js
CHANGED
|
@@ -106,7 +106,7 @@ function getWasmMemoryBytes() {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
function getAttribution() {
|
|
109
|
-
return "Powered by Quantum Forge \u2014 \xA9 Quantum
|
|
109
|
+
return "Powered by Quantum Forge \u2014 \xA9 Quantum Native \u2014 quantumnative.io";
|
|
110
110
|
}
|
|
111
111
|
async function registerServiceWorker(swPath = "/quantum-forge-sw.js") {
|
|
112
112
|
if (!("serviceWorker" in navigator)) return null;
|
package/dist/lib/quantum.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/quantum/QuantumForgeLoader.ts","../../src/quantum/QuantumPropertyManager.ts","../../src/quantum/QuantumRecorder.ts"],"sourcesContent":["/**\n * Quantum Forge Loader - Lazy loader for Quantum Forge WASM module\n *\n * Defers WASM loading from the critical path while preloading in background\n * so it's ready when needed. If not ready, callers can show loading UI.\n * \n * IMPORTANT: Quantum Forge is built from source and copied to dist/ as\n * quantum-forge-web-api.mjs (not an npm package). Run 'npm run setup' to build.\n */\n\nimport type { LoggerInterface } from \"../logging/Logger\";\n\n// Type for the quantum forge module\ntype QuantumForgeModuleType = typeof import(\"./quantum-forge-api.mjs\");\n\n// Configurable base path for WASM artifacts\nlet wasmBasePath = \"/quantum-forge\";\n\n/**\n * Set the base URL path where Quantum Forge WASM files are served.\n * Default is \"/quantum-forge\" which matches the Vite plugin's serve path.\n * Consumers using the Vite plugin don't need to call this.\n */\nexport function setWasmBasePath(path: string): void {\n wasmBasePath = path.endsWith(\"/\") ? path.slice(0, -1) : path;\n}\n\n/**\n * Select a named WASM build variant (e.g. \"d7n10\").\n * Sugar for `setWasmBasePath(\"/quantum-forge-{name}\")`.\n *\n * Must be called before `ensureLoaded()`. If the module is already loaded,\n * a warning is logged and the call is ignored.\n */\nexport function useQuantumForgeBuild(name: string): void {\n if (isInitialized) {\n logger?.warn?.(\n `useQuantumForgeBuild(\"${name}\") called after module already loaded — ignoring. Call before ensureLoaded().`,\n \"QuantumForgeLoader\",\n );\n return;\n }\n setWasmBasePath(`/quantum-forge-${name}`);\n}\n\n// Cache the module and initialization state\nlet quantumForgeModule: QuantumForgeModuleType | null = null;\nlet initPromise: Promise<void> | null = null;\nlet isInitialized = false;\nlet loadStarted = false;\n\n// Logger reference (set during startBackgroundLoad)\nlet logger: LoggerInterface | undefined;\n\n/**\n * Start loading the WASM module in the background.\n * Call this after the page has rendered (e.g., after DOMContentLoaded or initial paint).\n */\nexport function startBackgroundLoad(loggerRef?: LoggerInterface): void {\n if (loadStarted) return;\n loadStarted = true;\n logger = loggerRef;\n\n // Use requestIdleCallback if available, otherwise setTimeout\n const scheduleLoad = (callback: () => void) => {\n if (typeof requestIdleCallback === \"function\") {\n requestIdleCallback(callback, { timeout: 2000 });\n } else {\n setTimeout(callback, 100);\n }\n };\n\n scheduleLoad(() => {\n logger?.info?.(\"Starting background Quantum Forge load\", \"QuantumForgeLoader\");\n // Trigger the load but don't await - let it happen in background\n ensureLoaded().catch((err) => {\n logger?.warn?.(\n `Background Quantum Forge load failed: ${err?.message ?? err}`,\n \"QuantumForgeLoader\",\n );\n });\n });\n}\n\n/**\n * Ensure Quantum Forge is loaded and initialized.\n * Returns a promise that resolves when the module is ready.\n * Can be called multiple times - will return the same promise.\n */\nexport async function ensureLoaded(): Promise<void> {\n if (isInitialized) return;\n\n if (initPromise) {\n await initPromise;\n return;\n }\n\n initPromise = (async () => {\n const startTime = performance.now();\n logger?.info?.(\"Loading Quantum Forge WASM module...\", \"QuantumForgeLoader\");\n\n // Dynamic import of Quantum Forge WASM module from the configured base path\n const modulePath = `${wasmBasePath}/quantum-forge-web-api.mjs`;\n const mod = (await import(/* @vite-ignore */ modulePath)) as QuantumForgeModuleType;\n quantumForgeModule = mod;\n\n // Initialize the WASM\n await mod.QuantumForge.initialize();\n\n const version = mod.QuantumForge.getVersion();\n const maxDim = mod.QuantumForge.getMaxDimension();\n const maxQudits = mod.QuantumForge.getMaxQudits();\n const elapsed = (performance.now() - startTime).toFixed(0);\n\n logger?.info?.(\n `Quantum Forge v${version} ready in ${elapsed}ms (max dim: ${maxDim}, max qudits: ${maxQudits})`,\n \"QuantumForgeLoader\",\n );\n\n console.log(\n \"%c\\u269B Powered by Quantum Forge %c quantumnative.io \",\n \"background: #6366f1; color: white; padding: 2px 6px; border-radius: 3px 0 0 3px; font-weight: bold;\",\n \"background: #1e1b4b; color: #c7d2fe; padding: 2px 6px; border-radius: 0 3px 3px 0;\",\n );\n\n isInitialized = true;\n })();\n\n // Handle errors by clearing the promise so retry is possible\n initPromise.catch(() => {\n initPromise = null;\n });\n\n await initPromise;\n}\n\n/**\n * Check if Quantum Forge is ready to use (non-blocking).\n */\nexport function isReady(): boolean {\n return isInitialized;\n}\n\n/**\n * Get the loaded module. Throws if not loaded.\n * For synchronous access after ensuring it's loaded.\n */\nexport function getModule(): typeof import(\"./quantum-forge-api.mjs\") {\n if (!quantumForgeModule || !isInitialized) {\n throw new Error(\"QuantumForge not loaded. Call ensureLoaded() first and await it.\");\n }\n return quantumForgeModule;\n}\n\n/**\n * Get the QuantumForge class from the loaded module.\n */\nexport function getQuantumForge(): typeof import(\"./quantum-forge-api.mjs\").QuantumForge {\n return getModule().QuantumForge;\n}\n\n/**\n * Convenience re-exports for common operations.\n * These will throw if module not loaded.\n */\nexport function getVersion(): string {\n return getQuantumForge().getVersion();\n}\n\nexport function getMaxDimension(): number {\n return getQuantumForge().getMaxDimension();\n}\n\nexport function getMaxQudits(): number {\n return getQuantumForge().getMaxQudits();\n}\n\n/**\n * Get the WASM memory bytes (for analytics).\n */\nexport function getWasmMemoryBytes(): number | null {\n if (!isInitialized) return null;\n try {\n const qf = getQuantumForge() as any;\n return typeof qf.getMemoryBytes === \"function\" ? qf.getMemoryBytes() : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the required attribution text for display in your application.\n * Include this in a user-visible location (credits screen, about page, etc.).\n */\nexport function getAttribution(): string {\n return \"Powered by Quantum Forge \\u2014 \\u00A9 Quantum Realm Games, LLC. \\u2014 quantumnative.io\";\n}\n\n/**\n * Register the Quantum Forge service worker for offline WASM caching.\n * Call once from your game controller after page load.\n * The SW caches WASM artifacts on first fetch so subsequent loads work offline.\n *\n * @param swPath - Path to the service worker file. Default: \"/quantum-forge-sw.js\"\n */\nexport async function registerServiceWorker(\n swPath = \"/quantum-forge-sw.js\",\n): Promise<ServiceWorkerRegistration | null> {\n if (!(\"serviceWorker\" in navigator)) return null;\n try {\n const reg = await navigator.serviceWorker.register(swPath);\n logger?.info?.(`Service worker registered (scope: ${reg.scope})`, \"QuantumForgeLoader\");\n return reg;\n } catch (err) {\n logger?.warn?.(\n `Service worker registration failed: ${err instanceof Error ? err.message : err}`,\n \"QuantumForgeLoader\",\n );\n return null;\n }\n}\n","/**\n * QuantumPropertyManager — manages quantum property lifecycles.\n *\n * Handles the common pattern of acquiring, pooling, and releasing WASM\n * QuantumProperty handles. Games either extend this class or compose it\n * to add game-specific quantum operations via getModule().\n *\n * Property pooling is critical: measured/removed properties are recycled\n * to avoid growing the tensor product and hitting qudit limits.\n *\n * For opt-in operation recording, attach a QuantumRecorder via setRecorder().\n */\n\nimport { getModule } from \"./QuantumForgeLoader\";\nimport type { LoggerInterface } from \"../logging/Logger\";\nimport type { QuantumProperty as QFProperty } from \"./quantum-forge-api.mjs\";\n\nexport interface PredicateSpec {\n property: QFProperty;\n value: number;\n isEqual: boolean;\n}\n\nexport interface QuantumRecorderHook {\n onAcquire?(prop: QFProperty): void;\n onRelease?(prop: QFProperty, value: number): void;\n onSetProperty?(id: string, prop: QFProperty): void;\n onDeleteProperty?(id: string): void;\n}\n\nexport class QuantumPropertyManager {\n readonly dimension: number;\n private properties: Map<string, QFProperty> = new Map();\n private pool: QFProperty[] = [];\n protected logger?: LoggerInterface;\n private _recorder?: QuantumRecorderHook;\n\n constructor(options: { dimension?: number; logger?: LoggerInterface } = {}) {\n this.dimension = options.dimension ?? 2;\n this.logger = options.logger;\n }\n\n // -- Recorder hook --\n\n /** Attach an optional recorder for operation logging. */\n setRecorder(recorder: QuantumRecorderHook | undefined): void {\n this._recorder = recorder;\n }\n\n /** Get the currently attached recorder, if any. */\n getRecorder(): QuantumRecorderHook | undefined {\n return this._recorder;\n }\n\n // -- Property lifecycle --\n\n /**\n * Get a property at |0⟩ — reuses a pooled one if available,\n * otherwise creates a fresh standalone property.\n */\n acquireProperty(): QFProperty {\n let prop: QFProperty;\n if (this.pool.length > 0) {\n prop = this.pool.pop()!;\n } else {\n prop = getModule().QuantumForge.createQuantumProperty(this.dimension);\n }\n this._recorder?.onAcquire?.(prop);\n return prop;\n }\n\n /**\n * Return a property to the pool after resetting it to |0⟩.\n * Uses the `reset` primitive which applies non-fractional cycles —\n * correct for all dimensions (no superposition created).\n */\n releaseProperty(prop: QFProperty, measuredValue: number): void {\n this._recorder?.onRelease?.(prop, measuredValue);\n getModule().reset(prop, measuredValue);\n this.pool.push(prop);\n }\n\n // -- ID mapping --\n\n setProperty(id: string, prop: QFProperty): void {\n this._recorder?.onSetProperty?.(id, prop);\n this.properties.set(id, prop);\n }\n\n getProperty(id: string): QFProperty | undefined {\n return this.properties.get(id);\n }\n\n deleteProperty(id: string): void {\n this._recorder?.onDeleteProperty?.(id);\n this.properties.delete(id);\n }\n\n hasProperty(id: string): boolean {\n return this.properties.has(id);\n }\n\n // -- Public operations --\n\n /**\n * Remove a property by ID: measure it, pool the handle, delete the mapping.\n */\n removeProperty(id: string): void {\n const prop = this.properties.get(id);\n if (prop) {\n const [value] = getModule().measure_properties([prop]);\n this.releaseProperty(prop, value);\n }\n this.deleteProperty(id);\n }\n\n /** Clear all properties, pool, and recorder. */\n clear(): void {\n this.properties.clear();\n this.pool = [];\n }\n\n get size(): number {\n return this.properties.size;\n }\n\n get poolSize(): number {\n return this.pool.length;\n }\n\n // -- WASM module access --\n\n getModule(): ReturnType<typeof getModule> {\n return getModule();\n }\n\n // -- Internal access for QuantumRecorder replay --\n\n /** @internal — used by QuantumRecorder.replayLog() to restore pool state. */\n _setPool(pool: QFProperty[]): void {\n this.pool = pool;\n }\n\n /** @internal — used by QuantumRecorder to enumerate live handles. */\n _getProperties(): Map<string, QFProperty> {\n return this.properties;\n }\n\n /** @internal — used by QuantumRecorder to enumerate pool handles. */\n _getPool(): QFProperty[] {\n return this.pool;\n }\n}\n","/**\n * QuantumRecorder — opt-in recording and replay of quantum operations.\n *\n * Attach to a QuantumPropertyManager via `manager.setRecorder(recorder)`.\n * When recording is active, lifecycle hooks log every state-mutating\n * operation. The log can be replayed via replayLog() to recreate\n * identical quantum state — measurements are forced to their recorded\n * outcomes using forced_measure_properties.\n *\n * For gate recording, call wrapGate() around each WASM gate call.\n */\n\nimport { getModule } from \"./QuantumForgeLoader\";\nimport type { QuantumPropertyManager, QuantumRecorderHook } from \"./QuantumPropertyManager\";\nimport type { QuantumOperation, SerializedPredicate } from \"./QuantumOperationLog\";\nimport type { QuantumProperty as QFProperty, Predicate as QFPredicate } from \"./quantum-forge-api.mjs\";\n\nexport interface PredicateSpec {\n property: QFProperty;\n value: number;\n isEqual: boolean;\n}\n\nexport class QuantumRecorder implements QuantumRecorderHook {\n private _recording = false;\n private _log: QuantumOperation[] = [];\n private _handleToIndex: Map<QFProperty, number> = new Map();\n private _nextIndex = 0;\n private readonly _manager: QuantumPropertyManager;\n\n constructor(manager: QuantumPropertyManager) {\n this._manager = manager;\n }\n\n // -- QuantumRecorderHook implementation --\n\n onAcquire(prop: QFProperty): void {\n if (!this._recording) return;\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n this._log.push({ op: \"acquire\", index });\n }\n\n onRelease(prop: QFProperty, value: number): void {\n if (!this._recording) return;\n const index = this._handleToIndex.get(prop);\n if (index !== undefined) {\n this._log.push({ op: \"release\", index, value });\n }\n }\n\n onSetProperty(id: string, prop: QFProperty): void {\n if (!this._recording) return;\n const index = this._handleToIndex.get(prop);\n if (index !== undefined) {\n this._log.push({ op: \"assign\", index, id });\n }\n }\n\n onDeleteProperty(id: string): void {\n if (!this._recording) return;\n this._log.push({ op: \"unassign\", id });\n }\n\n // -- Gate recording --\n\n /**\n * Build WASM predicate objects from PredicateSpec array.\n */\n buildWasmPredicates(specs: PredicateSpec[]): QFPredicate[] {\n return specs.map((s) =>\n s.isEqual ? s.property.is(s.value) : s.property.is_not(s.value),\n );\n }\n\n /**\n * Serialize predicates for the operation log.\n */\n serializePredicates(specs: PredicateSpec[]): SerializedPredicate[] | undefined {\n if (specs.length === 0) return undefined;\n return specs.map((s) => {\n const index = this._handleToIndex.get(s.property);\n return {\n propertyIndex: index ?? -1,\n value: s.value,\n isEqual: s.isEqual,\n };\n });\n }\n\n /**\n * Record a gate operation. Call this when recording is active\n * and you want to log a gate call for replay.\n */\n recordOp(op: QuantumOperation): void {\n if (!this._recording) return;\n this._log.push(op);\n }\n\n /**\n * Get the recorded index for a property handle.\n */\n getIndex(prop: QFProperty): number | undefined {\n return this._handleToIndex.get(prop);\n }\n\n // -- Recording API --\n\n /** Begin recording quantum operations. Resets any existing log. */\n startRecording(): void {\n this._recording = true;\n this._log = [];\n this._handleToIndex.clear();\n this._nextIndex = 0;\n\n // Assign indices to all currently-live handles so operations\n // on pre-existing properties are tracked correctly.\n for (const prop of this._manager._getProperties().values()) {\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n }\n for (const prop of this._manager._getPool()) {\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n }\n }\n\n /** Stop recording and return the captured log. */\n stopRecording(): QuantumOperation[] {\n this._recording = false;\n return [...this._log];\n }\n\n /** Whether recording is currently active. */\n isRecording(): boolean {\n return this._recording;\n }\n\n /** Get a copy of the current operation log (even while recording). */\n getOperationLog(): QuantumOperation[] {\n return [...this._log];\n }\n\n /**\n * Replay an operation log to recreate quantum state from scratch.\n * Clears all existing state on the manager first. Measurements are\n * forced to their recorded outcomes via forced_measure_properties.\n */\n replayLog(operations: QuantumOperation[]): void {\n // Clear manager state\n this._manager.clear();\n this._recording = false;\n this._log = [];\n this._handleToIndex.clear();\n this._nextIndex = 0;\n\n const module = getModule();\n const dimension = this._manager.dimension;\n const indexToHandle = new Map<number, QFProperty>();\n const replayPool: QFProperty[] = [];\n\n for (const entry of operations) {\n switch (entry.op) {\n case \"acquire\": {\n let prop: QFProperty;\n if (replayPool.length > 0) {\n prop = replayPool.pop()!;\n } else {\n prop = module.QuantumForge.createQuantumProperty(dimension);\n }\n indexToHandle.set(entry.index, prop);\n break;\n }\n\n case \"release\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n module.reset(prop, entry.value);\n replayPool.push(prop);\n }\n break;\n }\n\n case \"assign\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n this._manager._getProperties().set(entry.id, prop);\n }\n break;\n }\n\n case \"unassign\": {\n this._manager._getProperties().delete(entry.id);\n break;\n }\n\n case \"cycle\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.cycle(prop);\n } else {\n module.cycle(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"shift\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.shift(prop);\n } else {\n module.shift(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"i_swap\": {\n const prop1 = indexToHandle.get(entry.index1);\n const prop2 = indexToHandle.get(entry.index2);\n if (prop1 && prop2) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.i_swap(prop1, prop2, entry.fraction, preds);\n }\n break;\n }\n\n case \"clock\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.clock(prop, entry.fraction, preds);\n }\n break;\n }\n\n case \"y\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.y(prop);\n } else {\n module.y(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"hadamard\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.hadamard(prop);\n } else {\n module.hadamard(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"inverse_hadamard\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.inverse_hadamard(prop, preds);\n }\n break;\n }\n\n case \"swap\": {\n const prop1 = indexToHandle.get(entry.index1);\n const prop2 = indexToHandle.get(entry.index2);\n if (prop1 && prop2) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.swap(prop1, prop2, preds);\n }\n break;\n }\n\n case \"phase_rotate\": {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (preds) {\n module.phase_rotate(preds, entry.angle);\n }\n break;\n }\n\n case \"measure_predicate\": {\n // During replay, we don't force measure_predicate outcomes —\n // the state should be deterministic from prior forced measurements.\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (preds) {\n module.measure_predicate(preds);\n }\n break;\n }\n\n case \"reset\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n module.reset(prop, entry.value);\n }\n break;\n }\n\n case \"measure\": {\n const props = entry.indices.map((i) => indexToHandle.get(i)).filter(Boolean) as QFProperty[];\n if (props.length === entry.indices.length) {\n module.forced_measure_properties(props, entry.outcomes);\n }\n break;\n }\n }\n }\n\n // Restore internal pool from replay pool\n this._manager._setPool(replayPool);\n\n // Rebuild _handleToIndex from indexToHandle for future recording\n this._handleToIndex.clear();\n for (const [index, handle] of indexToHandle) {\n this._handleToIndex.set(handle, index);\n }\n this._nextIndex = operations.reduce((max, op) => {\n if (\"index\" in op && typeof op.index === \"number\") return Math.max(max, op.index + 1);\n if (\"index1\" in op) {\n const dualOp = op as { index1: number; index2: number };\n return Math.max(max, dualOp.index1 + 1, dualOp.index2 + 1);\n }\n if (\"indices\" in op) {\n const measureOp = op as { indices: number[] };\n const maxIdx = Math.max(...measureOp.indices);\n return Math.max(max, maxIdx + 1);\n }\n return max;\n }, 0);\n }\n\n // -- Private helpers --\n\n private _replayPredicates(\n serialized: SerializedPredicate[] | undefined,\n indexToHandle: Map<number, QFProperty>,\n ): QFPredicate[] | undefined {\n if (!serialized || serialized.length === 0) return undefined;\n const preds: QFPredicate[] = [];\n for (const sp of serialized) {\n const prop = indexToHandle.get(sp.propertyIndex);\n if (!prop) return undefined;\n preds.push(sp.isEqual ? prop.is(sp.value) : prop.is_not(sp.value));\n }\n return preds;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/quantum/QuantumForgeLoader.ts","../../src/quantum/QuantumPropertyManager.ts","../../src/quantum/QuantumRecorder.ts"],"sourcesContent":["/**\n * Quantum Forge Loader - Lazy loader for Quantum Forge WASM module\n *\n * Defers WASM loading from the critical path while preloading in background\n * so it's ready when needed. If not ready, callers can show loading UI.\n * \n * IMPORTANT: Quantum Forge is built from source and copied to dist/ as\n * quantum-forge-web-api.mjs (not an npm package). Run 'npm run setup' to build.\n */\n\nimport type { LoggerInterface } from \"../logging/Logger\";\n\n// Type for the quantum forge module\ntype QuantumForgeModuleType = typeof import(\"./quantum-forge-api.mjs\");\n\n// Configurable base path for WASM artifacts\nlet wasmBasePath = \"/quantum-forge\";\n\n/**\n * Set the base URL path where Quantum Forge WASM files are served.\n * Default is \"/quantum-forge\" which matches the Vite plugin's serve path.\n * Consumers using the Vite plugin don't need to call this.\n */\nexport function setWasmBasePath(path: string): void {\n wasmBasePath = path.endsWith(\"/\") ? path.slice(0, -1) : path;\n}\n\n/**\n * Select a named WASM build variant (e.g. \"d7n10\").\n * Sugar for `setWasmBasePath(\"/quantum-forge-{name}\")`.\n *\n * Must be called before `ensureLoaded()`. If the module is already loaded,\n * a warning is logged and the call is ignored.\n */\nexport function useQuantumForgeBuild(name: string): void {\n if (isInitialized) {\n logger?.warn?.(\n `useQuantumForgeBuild(\"${name}\") called after module already loaded — ignoring. Call before ensureLoaded().`,\n \"QuantumForgeLoader\",\n );\n return;\n }\n setWasmBasePath(`/quantum-forge-${name}`);\n}\n\n// Cache the module and initialization state\nlet quantumForgeModule: QuantumForgeModuleType | null = null;\nlet initPromise: Promise<void> | null = null;\nlet isInitialized = false;\nlet loadStarted = false;\n\n// Logger reference (set during startBackgroundLoad)\nlet logger: LoggerInterface | undefined;\n\n/**\n * Start loading the WASM module in the background.\n * Call this after the page has rendered (e.g., after DOMContentLoaded or initial paint).\n */\nexport function startBackgroundLoad(loggerRef?: LoggerInterface): void {\n if (loadStarted) return;\n loadStarted = true;\n logger = loggerRef;\n\n // Use requestIdleCallback if available, otherwise setTimeout\n const scheduleLoad = (callback: () => void) => {\n if (typeof requestIdleCallback === \"function\") {\n requestIdleCallback(callback, { timeout: 2000 });\n } else {\n setTimeout(callback, 100);\n }\n };\n\n scheduleLoad(() => {\n logger?.info?.(\"Starting background Quantum Forge load\", \"QuantumForgeLoader\");\n // Trigger the load but don't await - let it happen in background\n ensureLoaded().catch((err) => {\n logger?.warn?.(\n `Background Quantum Forge load failed: ${err?.message ?? err}`,\n \"QuantumForgeLoader\",\n );\n });\n });\n}\n\n/**\n * Ensure Quantum Forge is loaded and initialized.\n * Returns a promise that resolves when the module is ready.\n * Can be called multiple times - will return the same promise.\n */\nexport async function ensureLoaded(): Promise<void> {\n if (isInitialized) return;\n\n if (initPromise) {\n await initPromise;\n return;\n }\n\n initPromise = (async () => {\n const startTime = performance.now();\n logger?.info?.(\"Loading Quantum Forge WASM module...\", \"QuantumForgeLoader\");\n\n // Dynamic import of Quantum Forge WASM module from the configured base path\n const modulePath = `${wasmBasePath}/quantum-forge-web-api.mjs`;\n const mod = (await import(/* @vite-ignore */ modulePath)) as QuantumForgeModuleType;\n quantumForgeModule = mod;\n\n // Initialize the WASM\n await mod.QuantumForge.initialize();\n\n const version = mod.QuantumForge.getVersion();\n const maxDim = mod.QuantumForge.getMaxDimension();\n const maxQudits = mod.QuantumForge.getMaxQudits();\n const elapsed = (performance.now() - startTime).toFixed(0);\n\n logger?.info?.(\n `Quantum Forge v${version} ready in ${elapsed}ms (max dim: ${maxDim}, max qudits: ${maxQudits})`,\n \"QuantumForgeLoader\",\n );\n\n console.log(\n \"%c\\u269B Powered by Quantum Forge %c quantumnative.io \",\n \"background: #6366f1; color: white; padding: 2px 6px; border-radius: 3px 0 0 3px; font-weight: bold;\",\n \"background: #1e1b4b; color: #c7d2fe; padding: 2px 6px; border-radius: 0 3px 3px 0;\",\n );\n\n isInitialized = true;\n })();\n\n // Handle errors by clearing the promise so retry is possible\n initPromise.catch(() => {\n initPromise = null;\n });\n\n await initPromise;\n}\n\n/**\n * Check if Quantum Forge is ready to use (non-blocking).\n */\nexport function isReady(): boolean {\n return isInitialized;\n}\n\n/**\n * Get the loaded module. Throws if not loaded.\n * For synchronous access after ensuring it's loaded.\n */\nexport function getModule(): typeof import(\"./quantum-forge-api.mjs\") {\n if (!quantumForgeModule || !isInitialized) {\n throw new Error(\"QuantumForge not loaded. Call ensureLoaded() first and await it.\");\n }\n return quantumForgeModule;\n}\n\n/**\n * Get the QuantumForge class from the loaded module.\n */\nexport function getQuantumForge(): typeof import(\"./quantum-forge-api.mjs\").QuantumForge {\n return getModule().QuantumForge;\n}\n\n/**\n * Convenience re-exports for common operations.\n * These will throw if module not loaded.\n */\nexport function getVersion(): string {\n return getQuantumForge().getVersion();\n}\n\nexport function getMaxDimension(): number {\n return getQuantumForge().getMaxDimension();\n}\n\nexport function getMaxQudits(): number {\n return getQuantumForge().getMaxQudits();\n}\n\n/**\n * Get the WASM memory bytes (for analytics).\n */\nexport function getWasmMemoryBytes(): number | null {\n if (!isInitialized) return null;\n try {\n const qf = getQuantumForge() as any;\n return typeof qf.getMemoryBytes === \"function\" ? qf.getMemoryBytes() : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the required attribution text for display in your application.\n * Include this in a user-visible location (credits screen, about page, etc.).\n */\nexport function getAttribution(): string {\n return \"Powered by Quantum Forge \\u2014 \\u00A9 Quantum Native \\u2014 quantumnative.io\";\n}\n\n/**\n * Register the Quantum Forge service worker for offline WASM caching.\n * Call once from your game controller after page load.\n * The SW caches WASM artifacts on first fetch so subsequent loads work offline.\n *\n * @param swPath - Path to the service worker file. Default: \"/quantum-forge-sw.js\"\n */\nexport async function registerServiceWorker(\n swPath = \"/quantum-forge-sw.js\",\n): Promise<ServiceWorkerRegistration | null> {\n if (!(\"serviceWorker\" in navigator)) return null;\n try {\n const reg = await navigator.serviceWorker.register(swPath);\n logger?.info?.(`Service worker registered (scope: ${reg.scope})`, \"QuantumForgeLoader\");\n return reg;\n } catch (err) {\n logger?.warn?.(\n `Service worker registration failed: ${err instanceof Error ? err.message : err}`,\n \"QuantumForgeLoader\",\n );\n return null;\n }\n}\n","/**\n * QuantumPropertyManager — manages quantum property lifecycles.\n *\n * Handles the common pattern of acquiring, pooling, and releasing WASM\n * QuantumProperty handles. Games either extend this class or compose it\n * to add game-specific quantum operations via getModule().\n *\n * Property pooling is critical: measured/removed properties are recycled\n * to avoid growing the tensor product and hitting qudit limits.\n *\n * For opt-in operation recording, attach a QuantumRecorder via setRecorder().\n */\n\nimport { getModule } from \"./QuantumForgeLoader\";\nimport type { LoggerInterface } from \"../logging/Logger\";\nimport type { QuantumProperty as QFProperty } from \"./quantum-forge-api.mjs\";\n\nexport interface PredicateSpec {\n property: QFProperty;\n value: number;\n isEqual: boolean;\n}\n\nexport interface QuantumRecorderHook {\n onAcquire?(prop: QFProperty): void;\n onRelease?(prop: QFProperty, value: number): void;\n onSetProperty?(id: string, prop: QFProperty): void;\n onDeleteProperty?(id: string): void;\n}\n\nexport class QuantumPropertyManager {\n readonly dimension: number;\n private properties: Map<string, QFProperty> = new Map();\n private pool: QFProperty[] = [];\n protected logger?: LoggerInterface;\n private _recorder?: QuantumRecorderHook;\n\n constructor(options: { dimension?: number; logger?: LoggerInterface } = {}) {\n this.dimension = options.dimension ?? 2;\n this.logger = options.logger;\n }\n\n // -- Recorder hook --\n\n /** Attach an optional recorder for operation logging. */\n setRecorder(recorder: QuantumRecorderHook | undefined): void {\n this._recorder = recorder;\n }\n\n /** Get the currently attached recorder, if any. */\n getRecorder(): QuantumRecorderHook | undefined {\n return this._recorder;\n }\n\n // -- Property lifecycle --\n\n /**\n * Get a property at |0⟩ — reuses a pooled one if available,\n * otherwise creates a fresh standalone property.\n */\n acquireProperty(): QFProperty {\n let prop: QFProperty;\n if (this.pool.length > 0) {\n prop = this.pool.pop()!;\n } else {\n prop = getModule().QuantumForge.createQuantumProperty(this.dimension);\n }\n this._recorder?.onAcquire?.(prop);\n return prop;\n }\n\n /**\n * Return a property to the pool after resetting it to |0⟩.\n * Uses the `reset` primitive which applies non-fractional cycles —\n * correct for all dimensions (no superposition created).\n */\n releaseProperty(prop: QFProperty, measuredValue: number): void {\n this._recorder?.onRelease?.(prop, measuredValue);\n getModule().reset(prop, measuredValue);\n this.pool.push(prop);\n }\n\n // -- ID mapping --\n\n setProperty(id: string, prop: QFProperty): void {\n this._recorder?.onSetProperty?.(id, prop);\n this.properties.set(id, prop);\n }\n\n getProperty(id: string): QFProperty | undefined {\n return this.properties.get(id);\n }\n\n deleteProperty(id: string): void {\n this._recorder?.onDeleteProperty?.(id);\n this.properties.delete(id);\n }\n\n hasProperty(id: string): boolean {\n return this.properties.has(id);\n }\n\n // -- Public operations --\n\n /**\n * Remove a property by ID: measure it, pool the handle, delete the mapping.\n */\n removeProperty(id: string): void {\n const prop = this.properties.get(id);\n if (prop) {\n const [value] = getModule().measure_properties([prop]);\n this.releaseProperty(prop, value);\n }\n this.deleteProperty(id);\n }\n\n /** Clear all properties, pool, and recorder. */\n clear(): void {\n this.properties.clear();\n this.pool = [];\n }\n\n get size(): number {\n return this.properties.size;\n }\n\n get poolSize(): number {\n return this.pool.length;\n }\n\n // -- WASM module access --\n\n getModule(): ReturnType<typeof getModule> {\n return getModule();\n }\n\n // -- Internal access for QuantumRecorder replay --\n\n /** @internal — used by QuantumRecorder.replayLog() to restore pool state. */\n _setPool(pool: QFProperty[]): void {\n this.pool = pool;\n }\n\n /** @internal — used by QuantumRecorder to enumerate live handles. */\n _getProperties(): Map<string, QFProperty> {\n return this.properties;\n }\n\n /** @internal — used by QuantumRecorder to enumerate pool handles. */\n _getPool(): QFProperty[] {\n return this.pool;\n }\n}\n","/**\n * QuantumRecorder — opt-in recording and replay of quantum operations.\n *\n * Attach to a QuantumPropertyManager via `manager.setRecorder(recorder)`.\n * When recording is active, lifecycle hooks log every state-mutating\n * operation. The log can be replayed via replayLog() to recreate\n * identical quantum state — measurements are forced to their recorded\n * outcomes using forced_measure_properties.\n *\n * For gate recording, call wrapGate() around each WASM gate call.\n */\n\nimport { getModule } from \"./QuantumForgeLoader\";\nimport type { QuantumPropertyManager, QuantumRecorderHook } from \"./QuantumPropertyManager\";\nimport type { QuantumOperation, SerializedPredicate } from \"./QuantumOperationLog\";\nimport type { QuantumProperty as QFProperty, Predicate as QFPredicate } from \"./quantum-forge-api.mjs\";\n\nexport interface PredicateSpec {\n property: QFProperty;\n value: number;\n isEqual: boolean;\n}\n\nexport class QuantumRecorder implements QuantumRecorderHook {\n private _recording = false;\n private _log: QuantumOperation[] = [];\n private _handleToIndex: Map<QFProperty, number> = new Map();\n private _nextIndex = 0;\n private readonly _manager: QuantumPropertyManager;\n\n constructor(manager: QuantumPropertyManager) {\n this._manager = manager;\n }\n\n // -- QuantumRecorderHook implementation --\n\n onAcquire(prop: QFProperty): void {\n if (!this._recording) return;\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n this._log.push({ op: \"acquire\", index });\n }\n\n onRelease(prop: QFProperty, value: number): void {\n if (!this._recording) return;\n const index = this._handleToIndex.get(prop);\n if (index !== undefined) {\n this._log.push({ op: \"release\", index, value });\n }\n }\n\n onSetProperty(id: string, prop: QFProperty): void {\n if (!this._recording) return;\n const index = this._handleToIndex.get(prop);\n if (index !== undefined) {\n this._log.push({ op: \"assign\", index, id });\n }\n }\n\n onDeleteProperty(id: string): void {\n if (!this._recording) return;\n this._log.push({ op: \"unassign\", id });\n }\n\n // -- Gate recording --\n\n /**\n * Build WASM predicate objects from PredicateSpec array.\n */\n buildWasmPredicates(specs: PredicateSpec[]): QFPredicate[] {\n return specs.map((s) =>\n s.isEqual ? s.property.is(s.value) : s.property.is_not(s.value),\n );\n }\n\n /**\n * Serialize predicates for the operation log.\n */\n serializePredicates(specs: PredicateSpec[]): SerializedPredicate[] | undefined {\n if (specs.length === 0) return undefined;\n return specs.map((s) => {\n const index = this._handleToIndex.get(s.property);\n return {\n propertyIndex: index ?? -1,\n value: s.value,\n isEqual: s.isEqual,\n };\n });\n }\n\n /**\n * Record a gate operation. Call this when recording is active\n * and you want to log a gate call for replay.\n */\n recordOp(op: QuantumOperation): void {\n if (!this._recording) return;\n this._log.push(op);\n }\n\n /**\n * Get the recorded index for a property handle.\n */\n getIndex(prop: QFProperty): number | undefined {\n return this._handleToIndex.get(prop);\n }\n\n // -- Recording API --\n\n /** Begin recording quantum operations. Resets any existing log. */\n startRecording(): void {\n this._recording = true;\n this._log = [];\n this._handleToIndex.clear();\n this._nextIndex = 0;\n\n // Assign indices to all currently-live handles so operations\n // on pre-existing properties are tracked correctly.\n for (const prop of this._manager._getProperties().values()) {\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n }\n for (const prop of this._manager._getPool()) {\n const index = this._nextIndex++;\n this._handleToIndex.set(prop, index);\n }\n }\n\n /** Stop recording and return the captured log. */\n stopRecording(): QuantumOperation[] {\n this._recording = false;\n return [...this._log];\n }\n\n /** Whether recording is currently active. */\n isRecording(): boolean {\n return this._recording;\n }\n\n /** Get a copy of the current operation log (even while recording). */\n getOperationLog(): QuantumOperation[] {\n return [...this._log];\n }\n\n /**\n * Replay an operation log to recreate quantum state from scratch.\n * Clears all existing state on the manager first. Measurements are\n * forced to their recorded outcomes via forced_measure_properties.\n */\n replayLog(operations: QuantumOperation[]): void {\n // Clear manager state\n this._manager.clear();\n this._recording = false;\n this._log = [];\n this._handleToIndex.clear();\n this._nextIndex = 0;\n\n const module = getModule();\n const dimension = this._manager.dimension;\n const indexToHandle = new Map<number, QFProperty>();\n const replayPool: QFProperty[] = [];\n\n for (const entry of operations) {\n switch (entry.op) {\n case \"acquire\": {\n let prop: QFProperty;\n if (replayPool.length > 0) {\n prop = replayPool.pop()!;\n } else {\n prop = module.QuantumForge.createQuantumProperty(dimension);\n }\n indexToHandle.set(entry.index, prop);\n break;\n }\n\n case \"release\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n module.reset(prop, entry.value);\n replayPool.push(prop);\n }\n break;\n }\n\n case \"assign\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n this._manager._getProperties().set(entry.id, prop);\n }\n break;\n }\n\n case \"unassign\": {\n this._manager._getProperties().delete(entry.id);\n break;\n }\n\n case \"cycle\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.cycle(prop);\n } else {\n module.cycle(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"shift\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.shift(prop);\n } else {\n module.shift(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"i_swap\": {\n const prop1 = indexToHandle.get(entry.index1);\n const prop2 = indexToHandle.get(entry.index2);\n if (prop1 && prop2) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.i_swap(prop1, prop2, entry.fraction, preds);\n }\n break;\n }\n\n case \"clock\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.clock(prop, entry.fraction, preds);\n }\n break;\n }\n\n case \"y\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.y(prop);\n } else {\n module.y(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"hadamard\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (entry.fraction === 1 && !preds) {\n module.hadamard(prop);\n } else {\n module.hadamard(prop, entry.fraction, preds);\n }\n }\n break;\n }\n\n case \"inverse_hadamard\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.inverse_hadamard(prop, preds);\n }\n break;\n }\n\n case \"swap\": {\n const prop1 = indexToHandle.get(entry.index1);\n const prop2 = indexToHandle.get(entry.index2);\n if (prop1 && prop2) {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n module.swap(prop1, prop2, preds);\n }\n break;\n }\n\n case \"phase_rotate\": {\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (preds) {\n module.phase_rotate(preds, entry.angle);\n }\n break;\n }\n\n case \"measure_predicate\": {\n // During replay, we don't force measure_predicate outcomes —\n // the state should be deterministic from prior forced measurements.\n const preds = this._replayPredicates(entry.predicates, indexToHandle);\n if (preds) {\n module.measure_predicate(preds);\n }\n break;\n }\n\n case \"reset\": {\n const prop = indexToHandle.get(entry.index);\n if (prop) {\n module.reset(prop, entry.value);\n }\n break;\n }\n\n case \"measure\": {\n const props = entry.indices.map((i) => indexToHandle.get(i)).filter(Boolean) as QFProperty[];\n if (props.length === entry.indices.length) {\n module.forced_measure_properties(props, entry.outcomes);\n }\n break;\n }\n }\n }\n\n // Restore internal pool from replay pool\n this._manager._setPool(replayPool);\n\n // Rebuild _handleToIndex from indexToHandle for future recording\n this._handleToIndex.clear();\n for (const [index, handle] of indexToHandle) {\n this._handleToIndex.set(handle, index);\n }\n this._nextIndex = operations.reduce((max, op) => {\n if (\"index\" in op && typeof op.index === \"number\") return Math.max(max, op.index + 1);\n if (\"index1\" in op) {\n const dualOp = op as { index1: number; index2: number };\n return Math.max(max, dualOp.index1 + 1, dualOp.index2 + 1);\n }\n if (\"indices\" in op) {\n const measureOp = op as { indices: number[] };\n const maxIdx = Math.max(...measureOp.indices);\n return Math.max(max, maxIdx + 1);\n }\n return max;\n }, 0);\n }\n\n // -- Private helpers --\n\n private _replayPredicates(\n serialized: SerializedPredicate[] | undefined,\n indexToHandle: Map<number, QFProperty>,\n ): QFPredicate[] | undefined {\n if (!serialized || serialized.length === 0) return undefined;\n const preds: QFPredicate[] = [];\n for (const sp of serialized) {\n const prop = indexToHandle.get(sp.propertyIndex);\n if (!prop) return undefined;\n preds.push(sp.isEqual ? prop.is(sp.value) : prop.is_not(sp.value));\n }\n return preds;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/lib/vite-plugin.js
CHANGED
|
@@ -35,11 +35,12 @@ function quantumForgeVitePlugin(options = {}) {
|
|
|
35
35
|
}
|
|
36
36
|
if (!filename.startsWith("quantum-forge-web-")) return next();
|
|
37
37
|
const localDir = subdir ? resolve(process.cwd(), wasmDir, subdir) : resolve(process.cwd(), wasmDir);
|
|
38
|
-
const
|
|
39
|
-
const candidates = [
|
|
40
|
-
|
|
41
|
-
resolve(
|
|
42
|
-
|
|
38
|
+
const nmPkgNames = ["quantum-forge", "@quantum-native/quantum-forge"];
|
|
39
|
+
const candidates = [resolve(localDir, filename)];
|
|
40
|
+
for (const pkg of nmPkgNames) {
|
|
41
|
+
const nmDir = subdir ? resolve(process.cwd(), "node_modules", ...pkg.split("/"), "dist", subdir) : resolve(process.cwd(), "node_modules", ...pkg.split("/"), "dist");
|
|
42
|
+
candidates.push(resolve(nmDir, filename));
|
|
43
|
+
}
|
|
43
44
|
const filePath = candidates.find((p) => fs.existsSync(p));
|
|
44
45
|
if (!filePath) return next();
|
|
45
46
|
const ext = filename.split(".").pop();
|
|
@@ -57,32 +58,41 @@ function quantumForgeVitePlugin(options = {}) {
|
|
|
57
58
|
},
|
|
58
59
|
writeBundle(options2) {
|
|
59
60
|
const outDir = options2.dir ?? resolve(process.cwd(), "dist");
|
|
60
|
-
const destDir = join(outDir, "quantum-forge");
|
|
61
61
|
const wasmFiles = [
|
|
62
62
|
"quantum-forge-web-esm.mjs",
|
|
63
63
|
"quantum-forge-web-esm.wasm",
|
|
64
64
|
"quantum-forge-web-api.mjs"
|
|
65
65
|
];
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
process.cwd(),
|
|
69
|
-
"node_modules",
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
const localBase = resolve(process.cwd(), wasmDir);
|
|
67
|
+
const nmBases = [
|
|
68
|
+
resolve(process.cwd(), "node_modules", "quantum-forge", "dist"),
|
|
69
|
+
resolve(process.cwd(), "node_modules", "@quantum-native", "quantum-forge", "dist")
|
|
70
|
+
];
|
|
71
|
+
const allBases = [localBase, ...nmBases];
|
|
72
|
+
const copyBuild = (srcDirs, destDir) => {
|
|
73
|
+
const resolved = wasmFiles.map((f) => {
|
|
74
|
+
for (const dir of srcDirs) {
|
|
75
|
+
const p = resolve(dir, f);
|
|
76
|
+
if (fs.existsSync(p)) return p;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}).filter((p) => p !== null);
|
|
80
|
+
if (resolved.length === 0) return;
|
|
81
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
82
|
+
for (const src of resolved) {
|
|
83
|
+
const filename = src.split("/").pop();
|
|
84
|
+
fs.copyFileSync(src, join(destDir, filename));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
copyBuild(allBases, join(outDir, "quantum-forge"));
|
|
88
|
+
for (const base of allBases) {
|
|
89
|
+
if (!fs.existsSync(base)) continue;
|
|
90
|
+
for (const entry of fs.readdirSync(base, { withFileTypes: true })) {
|
|
91
|
+
if (entry.isDirectory() && entry.name.startsWith("quantum-forge-")) {
|
|
92
|
+
const variantSrc = resolve(base, entry.name);
|
|
93
|
+
copyBuild([variantSrc], join(outDir, entry.name));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/vite-plugin.ts"],"sourcesContent":["import { type Plugin } from \"vite\";\nimport { resolve, join } from \"path\";\nimport fs from \"fs\";\n\nexport interface QuantumForgePluginOptions {\n /**\n * Directory containing the WASM build artifacts.\n * Default: \"dist\" (relative to project root)\n */\n wasmDir?: string;\n\n /**\n * URL path prefix where WASM files are served during dev.\n * Default: \"/quantum-forge\"\n */\n servePath?: string;\n}\n\n/**\n * Vite plugin that serves Quantum Forge WASM artifacts during development.\n *\n * During dev, intercepts requests to `servePath/*` and serves matching\n * `quantum-forge-web-*` files from `wasmDir/`. Also excludes the WASM\n * module from Vite's dependency optimization.\n *\n * Usage:\n * ```ts\n * import { quantumForgeVitePlugin } from \"@quantum-native/quantum-forge/vite-plugin\";\n * export default defineConfig({\n * plugins: [quantumForgeVitePlugin()],\n * });\n * ```\n */\nexport function quantumForgeVitePlugin(\n options: QuantumForgePluginOptions = {},\n): Plugin {\n const wasmDir = options.wasmDir ?? \"dist\";\n const servePath = options.servePath ?? \"/quantum-forge\";\n const prefix = servePath.endsWith(\"/\") ? servePath : servePath + \"/\";\n\n return {\n name: \"quantum-forge\",\n\n config() {\n return {\n optimizeDeps: {\n exclude: [\"quantum-forge-web-api.mjs\"],\n },\n };\n },\n\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n if (!req.url) return next();\n\n // Strip query string for matching\n const urlPath = req.url.split(\"?\")[0];\n\n // Match requests under the serve path (default and variant builds).\n // Default: /quantum-forge/file → dist/file\n // Variant: /quantum-forge-{name}/file → dist/quantum-forge-{name}/file\n if (!urlPath.startsWith(prefix) && !urlPath.startsWith(servePath + \"-\"))\n return next();\n\n let filename: string;\n let subdir: string;\n\n if (urlPath.startsWith(prefix)) {\n // Default build: /quantum-forge/file\n filename = urlPath.slice(prefix.length);\n subdir = \"\";\n } else {\n // Variant build: /quantum-forge-{name}/file\n // Extract variant name from path segment after servePath-\n const rest = urlPath.slice(servePath.length + 1); // strip \"/quantum-forge-\"\n const slashIdx = rest.indexOf(\"/\");\n if (slashIdx === -1) return next();\n const variantName = rest.slice(0, slashIdx);\n filename = rest.slice(slashIdx + 1);\n subdir = `quantum-forge-${variantName}`;\n }\n\n // Only serve quantum-forge files\n if (!filename.startsWith(\"quantum-forge-web-\")) return next();\n\n // Check project-local dist/ first, then fall back to the framework's\n // dist/ inside node_modules (consumer installs via registry)\n const localDir = subdir\n ? resolve(process.cwd(), wasmDir, subdir)\n : resolve(process.cwd(), wasmDir);\n const nmDir = subdir\n
|
|
1
|
+
{"version":3,"sources":["../../src/vite-plugin.ts"],"sourcesContent":["import { type Plugin } from \"vite\";\nimport { resolve, join } from \"path\";\nimport fs from \"fs\";\n\nexport interface QuantumForgePluginOptions {\n /**\n * Directory containing the WASM build artifacts.\n * Default: \"dist\" (relative to project root)\n */\n wasmDir?: string;\n\n /**\n * URL path prefix where WASM files are served during dev.\n * Default: \"/quantum-forge\"\n */\n servePath?: string;\n}\n\n/**\n * Vite plugin that serves Quantum Forge WASM artifacts during development.\n *\n * During dev, intercepts requests to `servePath/*` and serves matching\n * `quantum-forge-web-*` files from `wasmDir/`. Also excludes the WASM\n * module from Vite's dependency optimization.\n *\n * Usage:\n * ```ts\n * import { quantumForgeVitePlugin } from \"@quantum-native/quantum-forge/vite-plugin\";\n * export default defineConfig({\n * plugins: [quantumForgeVitePlugin()],\n * });\n * ```\n */\nexport function quantumForgeVitePlugin(\n options: QuantumForgePluginOptions = {},\n): Plugin {\n const wasmDir = options.wasmDir ?? \"dist\";\n const servePath = options.servePath ?? \"/quantum-forge\";\n const prefix = servePath.endsWith(\"/\") ? servePath : servePath + \"/\";\n\n return {\n name: \"quantum-forge\",\n\n config() {\n return {\n optimizeDeps: {\n exclude: [\"quantum-forge-web-api.mjs\"],\n },\n };\n },\n\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n if (!req.url) return next();\n\n // Strip query string for matching\n const urlPath = req.url.split(\"?\")[0];\n\n // Match requests under the serve path (default and variant builds).\n // Default: /quantum-forge/file → dist/file\n // Variant: /quantum-forge-{name}/file → dist/quantum-forge-{name}/file\n if (!urlPath.startsWith(prefix) && !urlPath.startsWith(servePath + \"-\"))\n return next();\n\n let filename: string;\n let subdir: string;\n\n if (urlPath.startsWith(prefix)) {\n // Default build: /quantum-forge/file\n filename = urlPath.slice(prefix.length);\n subdir = \"\";\n } else {\n // Variant build: /quantum-forge-{name}/file\n // Extract variant name from path segment after servePath-\n const rest = urlPath.slice(servePath.length + 1); // strip \"/quantum-forge-\"\n const slashIdx = rest.indexOf(\"/\");\n if (slashIdx === -1) return next();\n const variantName = rest.slice(0, slashIdx);\n filename = rest.slice(slashIdx + 1);\n subdir = `quantum-forge-${variantName}`;\n }\n\n // Only serve quantum-forge files\n if (!filename.startsWith(\"quantum-forge-web-\")) return next();\n\n // Check project-local dist/ first, then fall back to the framework's\n // dist/ inside node_modules (consumer installs via registry)\n const localDir = subdir\n ? resolve(process.cwd(), wasmDir, subdir)\n : resolve(process.cwd(), wasmDir);\n const nmPkgNames = [\"quantum-forge\", \"@quantum-native/quantum-forge\"];\n const candidates = [resolve(localDir, filename)];\n for (const pkg of nmPkgNames) {\n const nmDir = subdir\n ? resolve(process.cwd(), \"node_modules\", ...pkg.split(\"/\"), \"dist\", subdir)\n : resolve(process.cwd(), \"node_modules\", ...pkg.split(\"/\"), \"dist\");\n candidates.push(resolve(nmDir, filename));\n }\n const filePath = candidates.find((p) => fs.existsSync(p));\n if (!filePath) return next();\n\n const ext = filename.split(\".\").pop();\n const mimeTypes: Record<string, string> = {\n mjs: \"application/javascript\",\n wasm: \"application/wasm\",\n mts: \"application/javascript\",\n };\n res.setHeader(\n \"Content-Type\",\n mimeTypes[ext || \"\"] || \"application/octet-stream\",\n );\n fs.createReadStream(filePath).pipe(res);\n });\n },\n\n writeBundle(options) {\n const outDir = options.dir ?? resolve(process.cwd(), \"dist\");\n\n const wasmFiles = [\n \"quantum-forge-web-esm.mjs\",\n \"quantum-forge-web-esm.wasm\",\n \"quantum-forge-web-api.mjs\",\n ];\n\n const localBase = resolve(process.cwd(), wasmDir);\n const nmBases = [\n resolve(process.cwd(), \"node_modules\", \"quantum-forge\", \"dist\"),\n resolve(process.cwd(), \"node_modules\", \"@quantum-native\", \"quantum-forge\", \"dist\"),\n ];\n const allBases = [localBase, ...nmBases];\n\n // Copy a set of WASM files from a source dir to a dest dir\n const copyBuild = (srcDirs: string[], destDir: string) => {\n const resolved = wasmFiles\n .map((f) => {\n for (const dir of srcDirs) {\n const p = resolve(dir, f);\n if (fs.existsSync(p)) return p;\n }\n return null;\n })\n .filter((p): p is string => p !== null);\n\n if (resolved.length === 0) return;\n\n fs.mkdirSync(destDir, { recursive: true });\n for (const src of resolved) {\n const filename = src.split(\"/\").pop()!;\n fs.copyFileSync(src, join(destDir, filename));\n }\n };\n\n // Copy default build\n copyBuild(allBases, join(outDir, \"quantum-forge\"));\n\n // Copy any variant builds (e.g. quantum-forge-qubit/)\n for (const base of allBases) {\n if (!fs.existsSync(base)) continue;\n for (const entry of fs.readdirSync(base, { withFileTypes: true })) {\n if (entry.isDirectory() && entry.name.startsWith(\"quantum-forge-\")) {\n const variantSrc = resolve(base, entry.name);\n copyBuild([variantSrc], join(outDir, entry.name));\n }\n }\n }\n },\n };\n}\n"],"mappings":"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","names":["options"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
declare class Predicate {
|
|
2
|
+
private cppInstance;
|
|
3
|
+
constructor(cppInstance: any);
|
|
4
|
+
value(): number;
|
|
5
|
+
is_equal(): boolean;
|
|
6
|
+
getCppInstance(): any;
|
|
7
|
+
}
|
|
8
|
+
declare class QuantumProperty {
|
|
9
|
+
private cppInstance;
|
|
10
|
+
constructor(dimension: number);
|
|
11
|
+
index(): number;
|
|
12
|
+
dimension(): number;
|
|
13
|
+
is(value: number): Predicate;
|
|
14
|
+
is_not(value: number): Predicate;
|
|
15
|
+
getCppInstance(): any;
|
|
16
|
+
}
|
|
17
|
+
declare function cycle(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
18
|
+
declare function shift(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
19
|
+
declare function clock(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
20
|
+
declare function hadamard(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
21
|
+
declare function inverse_hadamard(prop: QuantumProperty, predicates?: Predicate[]): void;
|
|
22
|
+
declare function swap(prop1: QuantumProperty, prop2: QuantumProperty, predicates?: Predicate[]): void;
|
|
23
|
+
declare function i_swap(prop1: QuantumProperty, prop2: QuantumProperty, fraction: number, predicates?: Predicate[]): void;
|
|
24
|
+
declare function x(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
25
|
+
declare function z(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
26
|
+
declare function y(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
27
|
+
declare function reset(prop: QuantumProperty, currentValue: number): void;
|
|
28
|
+
declare function phase_rotate(predicates: Predicate[], angle: number): void;
|
|
29
|
+
declare function measure_properties(props: QuantumProperty[]): number[];
|
|
30
|
+
declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
|
|
31
|
+
declare function measure_predicate(predicates: Predicate[]): number;
|
|
32
|
+
declare function probabilities(props: QuantumProperty[]): Array<{
|
|
33
|
+
probability: number;
|
|
34
|
+
qudit_values: number[];
|
|
35
|
+
}>;
|
|
36
|
+
declare function reduced_density_matrix(props: QuantumProperty[]): Array<{
|
|
37
|
+
row_values: number[];
|
|
38
|
+
col_values: number[];
|
|
39
|
+
value: {
|
|
40
|
+
real: number;
|
|
41
|
+
imag: number;
|
|
42
|
+
};
|
|
43
|
+
}>;
|
|
44
|
+
declare class QuantumForge {
|
|
45
|
+
/**
|
|
46
|
+
* Initialize QuantumForge
|
|
47
|
+
* Automatically detects and loads the appropriate WASM module format
|
|
48
|
+
*/
|
|
49
|
+
static initialize(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if QuantumForge is initialized
|
|
52
|
+
*/
|
|
53
|
+
static isInitialized(): boolean;
|
|
54
|
+
static createQuantumProperty(dimension: number): QuantumProperty;
|
|
55
|
+
static getVersion(): string;
|
|
56
|
+
static getMaxDimension(): number;
|
|
57
|
+
static getMaxQudits(): number;
|
|
58
|
+
static isValidDimension(dimension: number): boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { Predicate, QuantumForge, QuantumProperty, clock, cycle, forced_measure_properties, hadamard, i_swap, inverse_hadamard, measure_predicate, measure_properties, phase_rotate, probabilities, reduced_density_matrix, reset, shift, swap, x, y, z };
|