quantum-forge 2.5.1 → 2.6.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/dist/lib/quantum.d.ts +27 -5
- package/dist/lib/quantum.js +17 -0
- package/dist/lib/quantum.js.map +1 -1
- package/dist/quantum-forge-qubit/quantum-forge-web-api.d.mts +7 -1
- package/dist/quantum-forge-qubit/quantum-forge-web-api.mjs +6 -0
- package/dist/quantum-forge-qubit/quantum-forge-web-esm.wasm +0 -0
- package/dist/quantum-forge-web-api.d.mts +7 -1
- package/dist/quantum-forge-web-api.mjs +6 -0
- package/dist/quantum-forge-web-esm.wasm +0 -0
- package/package.json +1 -1
package/dist/lib/quantum.d.ts
CHANGED
|
@@ -56,7 +56,13 @@ declare function phase_rotate(predicates: Predicate[], angle: number): void;
|
|
|
56
56
|
declare function measure_properties(props: QuantumProperty[]): number[];
|
|
57
57
|
declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
|
|
58
58
|
declare function measure_predicate(predicates: Predicate[]): number;
|
|
59
|
+
/** Force a predicate measurement to a specific outcome.
|
|
60
|
+
* If the forced value is impossible (zero probability), falls back to
|
|
61
|
+
* stochastic measurement and returns the actual outcome instead of throwing. */
|
|
59
62
|
declare function forced_measure_predicate(predicates: Predicate[], forcedValue: number): number;
|
|
63
|
+
/** Get the probability that all predicates are simultaneously satisfied.
|
|
64
|
+
* Read-only — does not collapse or modify quantum state. */
|
|
65
|
+
declare function predicate_probability(predicates: Predicate[]): number;
|
|
60
66
|
declare function probabilities(props: QuantumProperty[]): Array<{
|
|
61
67
|
probability: number;
|
|
62
68
|
qudit_values: number[];
|
|
@@ -96,7 +102,7 @@ interface BatchResult {
|
|
|
96
102
|
*/
|
|
97
103
|
declare function executeBatch(ops: BatchOp[]): BatchResult;
|
|
98
104
|
/** Numeric opcode values matching the C++ OpCode enum for tape encoding. */
|
|
99
|
-
declare const OP: {
|
|
105
|
+
declare const OP$1: {
|
|
100
106
|
readonly CYCLE: 0;
|
|
101
107
|
readonly SHIFT: 1;
|
|
102
108
|
readonly CLOCK: 2;
|
|
@@ -112,7 +118,7 @@ declare const OP: {
|
|
|
112
118
|
* [11, nq, -1, NaN, angle, 0, a[0]..a[nq-1], b[0]..b[nq-1]] */
|
|
113
119
|
readonly ROTATE_BASIS_PAIR: 11;
|
|
114
120
|
};
|
|
115
|
-
type OpNum = typeof OP[keyof typeof OP];
|
|
121
|
+
type OpNum = typeof OP$1[keyof typeof OP$1];
|
|
116
122
|
/**
|
|
117
123
|
* Fast-path batch execution using a pre-encoded Float64Array tape.
|
|
118
124
|
*
|
|
@@ -178,7 +184,6 @@ declare class QuantumForge {
|
|
|
178
184
|
|
|
179
185
|
type __quantum_forge_api_mjs_BatchOp = BatchOp;
|
|
180
186
|
type __quantum_forge_api_mjs_BatchResult = BatchResult;
|
|
181
|
-
declare const __quantum_forge_api_mjs_OP: typeof OP;
|
|
182
187
|
type __quantum_forge_api_mjs_OpCode = OpCode;
|
|
183
188
|
type __quantum_forge_api_mjs_OpNum = OpNum;
|
|
184
189
|
type __quantum_forge_api_mjs_Predicate = Predicate;
|
|
@@ -201,6 +206,7 @@ declare const __quantum_forge_api_mjs_inverse_hadamard: typeof inverse_hadamard;
|
|
|
201
206
|
declare const __quantum_forge_api_mjs_measure_predicate: typeof measure_predicate;
|
|
202
207
|
declare const __quantum_forge_api_mjs_measure_properties: typeof measure_properties;
|
|
203
208
|
declare const __quantum_forge_api_mjs_phase_rotate: typeof phase_rotate;
|
|
209
|
+
declare const __quantum_forge_api_mjs_predicate_probability: typeof predicate_probability;
|
|
204
210
|
declare const __quantum_forge_api_mjs_probabilities: typeof probabilities;
|
|
205
211
|
declare const __quantum_forge_api_mjs_reduced_density_matrix: typeof reduced_density_matrix;
|
|
206
212
|
declare const __quantum_forge_api_mjs_reset: typeof reset;
|
|
@@ -210,7 +216,7 @@ declare const __quantum_forge_api_mjs_x: typeof x;
|
|
|
210
216
|
declare const __quantum_forge_api_mjs_y: typeof y;
|
|
211
217
|
declare const __quantum_forge_api_mjs_z: typeof z;
|
|
212
218
|
declare namespace __quantum_forge_api_mjs {
|
|
213
|
-
export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult,
|
|
219
|
+
export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult, OP$1 as OP, type __quantum_forge_api_mjs_OpCode as OpCode, type __quantum_forge_api_mjs_OpNum as OpNum, __quantum_forge_api_mjs_Predicate as Predicate, __quantum_forge_api_mjs_QuantumForge as QuantumForge, __quantum_forge_api_mjs_QuantumProperty as QuantumProperty, __quantum_forge_api_mjs_QuantumSimulation as QuantumSimulation, __quantum_forge_api_mjs_clock as clock, __quantum_forge_api_mjs_cycle as cycle, __quantum_forge_api_mjs_executeBatch as executeBatch, __quantum_forge_api_mjs_executeBatchTape as executeBatchTape, __quantum_forge_api_mjs_forced_measure_predicate as forced_measure_predicate, __quantum_forge_api_mjs_forced_measure_properties as forced_measure_properties, __quantum_forge_api_mjs_hadamard as hadamard, __quantum_forge_api_mjs_i_swap as i_swap, __quantum_forge_api_mjs_inverse_hadamard as inverse_hadamard, __quantum_forge_api_mjs_measure_predicate as measure_predicate, __quantum_forge_api_mjs_measure_properties as measure_properties, __quantum_forge_api_mjs_phase_rotate as phase_rotate, __quantum_forge_api_mjs_predicate_probability as predicate_probability, __quantum_forge_api_mjs_probabilities as probabilities, __quantum_forge_api_mjs_reduced_density_matrix as reduced_density_matrix, __quantum_forge_api_mjs_reset as reset, __quantum_forge_api_mjs_shift as shift, __quantum_forge_api_mjs_swap as swap, __quantum_forge_api_mjs_x as x, __quantum_forge_api_mjs_y as y, __quantum_forge_api_mjs_z as z };
|
|
214
220
|
}
|
|
215
221
|
|
|
216
222
|
/**
|
|
@@ -494,4 +500,20 @@ declare class QuantumRecorder implements QuantumRecorderHook {
|
|
|
494
500
|
private _replayPredicates;
|
|
495
501
|
}
|
|
496
502
|
|
|
497
|
-
|
|
503
|
+
/** Numeric opcode constants for tape encoding. Matches C++ OpCode enum. */
|
|
504
|
+
declare const OP: {
|
|
505
|
+
readonly CYCLE: 0;
|
|
506
|
+
readonly SHIFT: 1;
|
|
507
|
+
readonly CLOCK: 2;
|
|
508
|
+
readonly X: 3;
|
|
509
|
+
readonly Z: 4;
|
|
510
|
+
readonly Y: 5;
|
|
511
|
+
readonly HADAMARD: 6;
|
|
512
|
+
readonly INVERSE_HADAMARD: 7;
|
|
513
|
+
readonly SWAP: 8;
|
|
514
|
+
readonly I_SWAP: 9;
|
|
515
|
+
readonly PHASE_ROTATE: 10;
|
|
516
|
+
readonly ROTATE_BASIS_PAIR: 11;
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, type PredicateSpec$1 as PredicateSpec, type QuantumOperation, QuantumPropertyManager, QuantumRecorder, type QuantumRecorderHook, type SerializedPredicate, ensureLoaded, getAttribution, getMaxDimension, getMaxQudits, getMaxStateSize, getModule, getQuantumForge, getVersion, getWasmMemoryBytes, isReady, registerServiceWorker, setWasmBasePath, startBackgroundLoad, useQuantumForgeBuild };
|
package/dist/lib/quantum.js
CHANGED
|
@@ -518,7 +518,24 @@ var QuantumRecorder = class {
|
|
|
518
518
|
return preds;
|
|
519
519
|
}
|
|
520
520
|
};
|
|
521
|
+
|
|
522
|
+
// src/quantum/index.ts
|
|
523
|
+
var OP = {
|
|
524
|
+
CYCLE: 0,
|
|
525
|
+
SHIFT: 1,
|
|
526
|
+
CLOCK: 2,
|
|
527
|
+
X: 3,
|
|
528
|
+
Z: 4,
|
|
529
|
+
Y: 5,
|
|
530
|
+
HADAMARD: 6,
|
|
531
|
+
INVERSE_HADAMARD: 7,
|
|
532
|
+
SWAP: 8,
|
|
533
|
+
I_SWAP: 9,
|
|
534
|
+
PHASE_ROTATE: 10,
|
|
535
|
+
ROTATE_BASIS_PAIR: 11
|
|
536
|
+
};
|
|
521
537
|
export {
|
|
538
|
+
OP,
|
|
522
539
|
QuantumPropertyManager,
|
|
523
540
|
QuantumRecorder,
|
|
524
541
|
ensureLoaded,
|
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\nexport function getMaxStateSize(): number {\n return getQuantumForge().getMaxStateSize();\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":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/quantum/QuantumForgeLoader.ts","../../src/quantum/QuantumPropertyManager.ts","../../src/quantum/QuantumRecorder.ts","../../src/quantum/index.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\nexport function getMaxStateSize(): number {\n return getQuantumForge().getMaxStateSize();\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","export {\n startBackgroundLoad,\n ensureLoaded,\n isReady,\n getModule,\n getQuantumForge,\n getVersion,\n getMaxDimension,\n getMaxQudits,\n getMaxStateSize,\n getWasmMemoryBytes,\n setWasmBasePath,\n useQuantumForgeBuild,\n getAttribution,\n registerServiceWorker,\n} from \"./QuantumForgeLoader\";\nexport { QuantumPropertyManager } from \"./QuantumPropertyManager\";\nexport type { PredicateSpec, QuantumRecorderHook } from \"./QuantumPropertyManager\";\nexport { QuantumRecorder } from \"./QuantumRecorder\";\nexport type { QuantumOperation, SerializedPredicate } from \"./QuantumOperationLog\";\nexport type { OpCode, BatchOp, BatchResult, OpNum } from \"./quantum-forge-api.mjs\";\n\n/** Numeric opcode constants for tape encoding. Matches C++ OpCode enum. */\nexport const OP = {\n CYCLE: 0, SHIFT: 1, CLOCK: 2,\n X: 3, Z: 4, Y: 5,\n HADAMARD: 6, INVERSE_HADAMARD: 7,\n SWAP: 8, I_SWAP: 9,\n PHASE_ROTATE: 10,\n ROTATE_BASIS_PAIR: 11,\n} as const;\n"],"mappings":"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","names":[]}
|
|
@@ -54,7 +54,13 @@ declare function phase_rotate(predicates: Predicate[], angle: number): void;
|
|
|
54
54
|
declare function measure_properties(props: QuantumProperty[]): number[];
|
|
55
55
|
declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
|
|
56
56
|
declare function measure_predicate(predicates: Predicate[]): number;
|
|
57
|
+
/** Force a predicate measurement to a specific outcome.
|
|
58
|
+
* If the forced value is impossible (zero probability), falls back to
|
|
59
|
+
* stochastic measurement and returns the actual outcome instead of throwing. */
|
|
57
60
|
declare function forced_measure_predicate(predicates: Predicate[], forcedValue: number): number;
|
|
61
|
+
/** Get the probability that all predicates are simultaneously satisfied.
|
|
62
|
+
* Read-only — does not collapse or modify quantum state. */
|
|
63
|
+
declare function predicate_probability(predicates: Predicate[]): number;
|
|
58
64
|
declare function probabilities(props: QuantumProperty[]): Array<{
|
|
59
65
|
probability: number;
|
|
60
66
|
qudit_values: number[];
|
|
@@ -174,4 +180,4 @@ declare class QuantumForge {
|
|
|
174
180
|
static getMaxStateSize(): number;
|
|
175
181
|
}
|
|
176
182
|
|
|
177
|
-
export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, Predicate, QuantumForge, QuantumProperty, QuantumSimulation, clock, cycle, executeBatch, executeBatchTape, forced_measure_predicate, forced_measure_properties, hadamard, i_swap, inverse_hadamard, measure_predicate, measure_properties, phase_rotate, probabilities, reduced_density_matrix, reset, shift, swap, x, y, z };
|
|
183
|
+
export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, Predicate, QuantumForge, QuantumProperty, QuantumSimulation, clock, cycle, executeBatch, executeBatchTape, forced_measure_predicate, forced_measure_properties, hadamard, i_swap, inverse_hadamard, measure_predicate, measure_properties, phase_rotate, predicate_probability, probabilities, reduced_density_matrix, reset, shift, swap, x, y, z };
|
|
@@ -177,6 +177,11 @@ function forced_measure_predicate(predicates, forcedValue) {
|
|
|
177
177
|
const cppPredicates = predicates.map((pred) => pred.getCppInstance());
|
|
178
178
|
return wasmModule.forced_measure_predicate(cppPredicates, forcedValue);
|
|
179
179
|
}
|
|
180
|
+
function predicate_probability(predicates) {
|
|
181
|
+
if (!wasmModule) throw new Error("QuantumForge not initialized. Call QuantumForge.initialize() first.");
|
|
182
|
+
const cppPredicates = predicates.map((pred) => pred.getCppInstance());
|
|
183
|
+
return wasmModule.predicate_probability(cppPredicates);
|
|
184
|
+
}
|
|
180
185
|
function probabilities(props) {
|
|
181
186
|
if (!wasmModule) throw new Error("QuantumForge not initialized. Call QuantumForge.initialize() first.");
|
|
182
187
|
const cppProps = props.map((prop) => prop.getCppInstance());
|
|
@@ -292,6 +297,7 @@ export {
|
|
|
292
297
|
measure_predicate,
|
|
293
298
|
measure_properties,
|
|
294
299
|
phase_rotate,
|
|
300
|
+
predicate_probability,
|
|
295
301
|
probabilities,
|
|
296
302
|
reduced_density_matrix,
|
|
297
303
|
reset,
|
|
Binary file
|
|
@@ -54,7 +54,13 @@ declare function phase_rotate(predicates: Predicate[], angle: number): void;
|
|
|
54
54
|
declare function measure_properties(props: QuantumProperty[]): number[];
|
|
55
55
|
declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
|
|
56
56
|
declare function measure_predicate(predicates: Predicate[]): number;
|
|
57
|
+
/** Force a predicate measurement to a specific outcome.
|
|
58
|
+
* If the forced value is impossible (zero probability), falls back to
|
|
59
|
+
* stochastic measurement and returns the actual outcome instead of throwing. */
|
|
57
60
|
declare function forced_measure_predicate(predicates: Predicate[], forcedValue: number): number;
|
|
61
|
+
/** Get the probability that all predicates are simultaneously satisfied.
|
|
62
|
+
* Read-only — does not collapse or modify quantum state. */
|
|
63
|
+
declare function predicate_probability(predicates: Predicate[]): number;
|
|
58
64
|
declare function probabilities(props: QuantumProperty[]): Array<{
|
|
59
65
|
probability: number;
|
|
60
66
|
qudit_values: number[];
|
|
@@ -174,4 +180,4 @@ declare class QuantumForge {
|
|
|
174
180
|
static getMaxStateSize(): number;
|
|
175
181
|
}
|
|
176
182
|
|
|
177
|
-
export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, Predicate, QuantumForge, QuantumProperty, QuantumSimulation, clock, cycle, executeBatch, executeBatchTape, forced_measure_predicate, forced_measure_properties, hadamard, i_swap, inverse_hadamard, measure_predicate, measure_properties, phase_rotate, probabilities, reduced_density_matrix, reset, shift, swap, x, y, z };
|
|
183
|
+
export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, Predicate, QuantumForge, QuantumProperty, QuantumSimulation, clock, cycle, executeBatch, executeBatchTape, forced_measure_predicate, forced_measure_properties, hadamard, i_swap, inverse_hadamard, measure_predicate, measure_properties, phase_rotate, predicate_probability, probabilities, reduced_density_matrix, reset, shift, swap, x, y, z };
|
|
@@ -177,6 +177,11 @@ function forced_measure_predicate(predicates, forcedValue) {
|
|
|
177
177
|
const cppPredicates = predicates.map((pred) => pred.getCppInstance());
|
|
178
178
|
return wasmModule.forced_measure_predicate(cppPredicates, forcedValue);
|
|
179
179
|
}
|
|
180
|
+
function predicate_probability(predicates) {
|
|
181
|
+
if (!wasmModule) throw new Error("QuantumForge not initialized. Call QuantumForge.initialize() first.");
|
|
182
|
+
const cppPredicates = predicates.map((pred) => pred.getCppInstance());
|
|
183
|
+
return wasmModule.predicate_probability(cppPredicates);
|
|
184
|
+
}
|
|
180
185
|
function probabilities(props) {
|
|
181
186
|
if (!wasmModule) throw new Error("QuantumForge not initialized. Call QuantumForge.initialize() first.");
|
|
182
187
|
const cppProps = props.map((prop) => prop.getCppInstance());
|
|
@@ -292,6 +297,7 @@ export {
|
|
|
292
297
|
measure_predicate,
|
|
293
298
|
measure_properties,
|
|
294
299
|
phase_rotate,
|
|
300
|
+
predicate_probability,
|
|
295
301
|
probabilities,
|
|
296
302
|
reduced_density_matrix,
|
|
297
303
|
reset,
|
|
Binary file
|
package/package.json
CHANGED