quantum-forge 2.7.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QUANTUM_FORGE.md +203 -207
- package/README.md +54 -38
- package/dist/lib/quantum.d.ts +674 -61
- package/dist/lib/quantum.js +1054 -4
- package/dist/lib/quantum.js.map +1 -1
- package/dist/quantum-forge-qubit/quantum-forge-web-esm.wasm +0 -0
- package/dist/quantum-forge-web-esm.wasm +0 -0
- package/package.json +3 -2
- package/quantum-forge-sw.js +1 -1
- package/dist/quantum-forge-web-0.3.0.tgz +0 -0
package/dist/lib/quantum.d.ts
CHANGED
|
@@ -7,20 +7,20 @@ interface InitializeOptions {
|
|
|
7
7
|
/** Override Emscripten's default stdout handler (console.log). */
|
|
8
8
|
print?: (text: string) => void;
|
|
9
9
|
}
|
|
10
|
-
declare class Predicate {
|
|
10
|
+
declare class Predicate$1 {
|
|
11
11
|
private cppInstance;
|
|
12
12
|
constructor(cppInstance: any);
|
|
13
13
|
value(): number;
|
|
14
14
|
is_equal(): boolean;
|
|
15
15
|
getCppInstance(): any;
|
|
16
16
|
}
|
|
17
|
-
declare class QuantumProperty {
|
|
17
|
+
declare class QuantumProperty$1 {
|
|
18
18
|
private cppInstance;
|
|
19
19
|
constructor(dimension: number);
|
|
20
20
|
index(): number;
|
|
21
21
|
dimension(): number;
|
|
22
|
-
is(value: number): Predicate;
|
|
23
|
-
is_not(value: number): Predicate;
|
|
22
|
+
is(value: number): Predicate$1;
|
|
23
|
+
is_not(value: number): Predicate$1;
|
|
24
24
|
/** Number of qudits in this property's shared quantum state. */
|
|
25
25
|
num_active_qudits(): number;
|
|
26
26
|
/** Current number of basis amplitudes in the state vector (sparse size). */
|
|
@@ -31,16 +31,16 @@ declare class QuantumProperty {
|
|
|
31
31
|
is_valid(): boolean;
|
|
32
32
|
getCppInstance(): any;
|
|
33
33
|
/** @internal Create a QuantumProperty from an existing C++ instance. */
|
|
34
|
-
static _fromCpp(cppInstance: any): QuantumProperty;
|
|
34
|
+
static _fromCpp(cppInstance: any): QuantumProperty$1;
|
|
35
35
|
}
|
|
36
36
|
declare class QuantumSimulation {
|
|
37
37
|
private cppInstance;
|
|
38
38
|
constructor();
|
|
39
|
-
createProperty(dimension: number): QuantumProperty;
|
|
39
|
+
createProperty(dimension: number): QuantumProperty$1;
|
|
40
40
|
/** Factorize a property out of this simulation's shared state and destroy it.
|
|
41
41
|
* Automatically factors out any remaining qudits that became separable.
|
|
42
42
|
* Frees memory incrementally — critical for search algorithms with many ancillas. */
|
|
43
|
-
destroyProperty(prop: QuantumProperty): void;
|
|
43
|
+
destroyProperty(prop: QuantumProperty$1): void;
|
|
44
44
|
/** Factor out any separable qudits across all shared states in this simulation.
|
|
45
45
|
* Call after undo operations (e.g. i_swap reversal) that may have restored separability.
|
|
46
46
|
* Separable qudits are split into independent states, reducing entanglement overhead. */
|
|
@@ -48,40 +48,40 @@ declare class QuantumSimulation {
|
|
|
48
48
|
destroy(): void;
|
|
49
49
|
isDestroyed(): boolean;
|
|
50
50
|
}
|
|
51
|
-
declare function cycle(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
52
|
-
declare function shift(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
53
|
-
declare function clock(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
54
|
-
declare function hadamard(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
55
|
-
declare function inverse_hadamard(prop: QuantumProperty, predicates?: Predicate[]): void;
|
|
56
|
-
declare function swap(prop1: QuantumProperty, prop2: QuantumProperty, predicates?: Predicate[]): void;
|
|
57
|
-
declare function i_swap(prop1: QuantumProperty, prop2: QuantumProperty, fraction: number, predicates?: Predicate[]): void;
|
|
51
|
+
declare function cycle(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
52
|
+
declare function shift(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
53
|
+
declare function clock(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
54
|
+
declare function hadamard(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
55
|
+
declare function inverse_hadamard(prop: QuantumProperty$1, predicates?: Predicate$1[]): void;
|
|
56
|
+
declare function swap(prop1: QuantumProperty$1, prop2: QuantumProperty$1, predicates?: Predicate$1[]): void;
|
|
57
|
+
declare function i_swap(prop1: QuantumProperty$1, prop2: QuantumProperty$1, fraction: number, predicates?: Predicate$1[]): void;
|
|
58
58
|
/** Pauli X gate — alias for `shift` (C++ `qforge::x`, QuantumProperty.h).
|
|
59
59
|
* NOTE: X is `shift` (decrement mod d), NOT `cycle` (increment mod d). The two
|
|
60
60
|
* coincide only at dimension 2; for d > 2 they are inverses of each other. */
|
|
61
|
-
declare function x(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
61
|
+
declare function x(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
62
62
|
/** Pauli Z gate — alias for `clock` (C++ `qforge::z`, QuantumProperty.h). */
|
|
63
|
-
declare function z(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
63
|
+
declare function z(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
64
64
|
/** Pauli Y gate — qubit only. Composed as S · X · S† i.e.
|
|
65
65
|
* `clock(-0.5); shift(fraction?); clock(0.5)` (C++ `qforge::y`, QuantumProperty.h).
|
|
66
66
|
* @throws Error if the property dimension is not 2, mirroring the C++ guard. */
|
|
67
|
-
declare function y(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
|
|
68
|
-
declare function reset(prop: QuantumProperty, currentValue: number): void;
|
|
69
|
-
declare function phase_rotate(predicates: Predicate[], angle: number): void;
|
|
70
|
-
declare function measure_properties(props: QuantumProperty[]): number[];
|
|
71
|
-
declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
|
|
72
|
-
declare function measure_predicate(predicates: Predicate[]): number;
|
|
67
|
+
declare function y(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
|
|
68
|
+
declare function reset(prop: QuantumProperty$1, currentValue: number): void;
|
|
69
|
+
declare function phase_rotate(predicates: Predicate$1[], angle: number): void;
|
|
70
|
+
declare function measure_properties(props: QuantumProperty$1[]): number[];
|
|
71
|
+
declare function forced_measure_properties(props: QuantumProperty$1[], forcedValues: number[]): number[];
|
|
72
|
+
declare function measure_predicate(predicates: Predicate$1[]): number;
|
|
73
73
|
/** Force a predicate measurement to a specific outcome.
|
|
74
74
|
* If the forced value is impossible (zero probability), falls back to
|
|
75
75
|
* stochastic measurement and returns the actual outcome instead of throwing. */
|
|
76
|
-
declare function forced_measure_predicate(predicates: Predicate[], forcedValue: number): number;
|
|
76
|
+
declare function forced_measure_predicate(predicates: Predicate$1[], forcedValue: number): number;
|
|
77
77
|
/** Get the probability that all predicates are simultaneously satisfied.
|
|
78
78
|
* Read-only — does not collapse or modify quantum state. */
|
|
79
|
-
declare function predicate_probability(predicates: Predicate[]): number;
|
|
80
|
-
declare function probabilities(props: QuantumProperty[]): Array<{
|
|
79
|
+
declare function predicate_probability(predicates: Predicate$1[]): number;
|
|
80
|
+
declare function probabilities$1(props: QuantumProperty$1[]): Array<{
|
|
81
81
|
probability: number;
|
|
82
82
|
qudit_values: number[];
|
|
83
83
|
}>;
|
|
84
|
-
declare function reduced_density_matrix(props: QuantumProperty[]): Array<{
|
|
84
|
+
declare function reduced_density_matrix(props: QuantumProperty$1[]): Array<{
|
|
85
85
|
row_values: number[];
|
|
86
86
|
col_values: number[];
|
|
87
87
|
value: {
|
|
@@ -94,13 +94,13 @@ type OpCode = 'cycle' | 'shift' | 'clock' | 'x' | 'z' | 'y' | 'hadamard' | 'inve
|
|
|
94
94
|
/** A single gate operation descriptor for batch execution. */
|
|
95
95
|
interface BatchOp {
|
|
96
96
|
op: OpCode;
|
|
97
|
-
target?: QuantumProperty;
|
|
98
|
-
target2?: QuantumProperty;
|
|
97
|
+
target?: QuantumProperty$1;
|
|
98
|
+
target2?: QuantumProperty$1;
|
|
99
99
|
/** Gate fraction. Omit for non-fractional (discrete permutation) variant. */
|
|
100
100
|
fraction?: number;
|
|
101
101
|
/** Rotation angle (phase_rotate only). */
|
|
102
102
|
angle?: number;
|
|
103
|
-
predicates?: Predicate[];
|
|
103
|
+
predicates?: Predicate$1[];
|
|
104
104
|
}
|
|
105
105
|
/** Result of a batch execution. */
|
|
106
106
|
interface BatchResult {
|
|
@@ -175,7 +175,7 @@ type OpNum = typeof OP$1[keyof typeof OP$1];
|
|
|
175
175
|
* @param tape Pre-encoded Float64Array of operations
|
|
176
176
|
* @returns BatchResult
|
|
177
177
|
*/
|
|
178
|
-
declare function executeBatchTape(properties: QuantumProperty[], tape: Float64Array): BatchResult;
|
|
178
|
+
declare function executeBatchTape(properties: QuantumProperty$1[], tape: Float64Array): BatchResult;
|
|
179
179
|
declare class QuantumForge {
|
|
180
180
|
/**
|
|
181
181
|
* Initialize QuantumForge
|
|
@@ -188,7 +188,7 @@ declare class QuantumForge {
|
|
|
188
188
|
* Check if QuantumForge is initialized
|
|
189
189
|
*/
|
|
190
190
|
static isInitialized(): boolean;
|
|
191
|
-
static createQuantumProperty(dimension: number): QuantumProperty;
|
|
191
|
+
static createQuantumProperty(dimension: number): QuantumProperty$1;
|
|
192
192
|
static createSimulation(): QuantumSimulation;
|
|
193
193
|
static getVersion(): string;
|
|
194
194
|
static getMaxDimension(): number;
|
|
@@ -203,12 +203,8 @@ type __quantum_forge_api_mjs_BatchResult = BatchResult;
|
|
|
203
203
|
type __quantum_forge_api_mjs_InitializeOptions = InitializeOptions;
|
|
204
204
|
type __quantum_forge_api_mjs_OpCode = OpCode;
|
|
205
205
|
type __quantum_forge_api_mjs_OpNum = OpNum;
|
|
206
|
-
type __quantum_forge_api_mjs_Predicate = Predicate;
|
|
207
|
-
declare const __quantum_forge_api_mjs_Predicate: typeof Predicate;
|
|
208
206
|
type __quantum_forge_api_mjs_QuantumForge = QuantumForge;
|
|
209
207
|
declare const __quantum_forge_api_mjs_QuantumForge: typeof QuantumForge;
|
|
210
|
-
type __quantum_forge_api_mjs_QuantumProperty = QuantumProperty;
|
|
211
|
-
declare const __quantum_forge_api_mjs_QuantumProperty: typeof QuantumProperty;
|
|
212
208
|
type __quantum_forge_api_mjs_QuantumSimulation = QuantumSimulation;
|
|
213
209
|
declare const __quantum_forge_api_mjs_QuantumSimulation: typeof QuantumSimulation;
|
|
214
210
|
declare const __quantum_forge_api_mjs_clock: typeof clock;
|
|
@@ -224,7 +220,6 @@ declare const __quantum_forge_api_mjs_measure_predicate: typeof measure_predicat
|
|
|
224
220
|
declare const __quantum_forge_api_mjs_measure_properties: typeof measure_properties;
|
|
225
221
|
declare const __quantum_forge_api_mjs_phase_rotate: typeof phase_rotate;
|
|
226
222
|
declare const __quantum_forge_api_mjs_predicate_probability: typeof predicate_probability;
|
|
227
|
-
declare const __quantum_forge_api_mjs_probabilities: typeof probabilities;
|
|
228
223
|
declare const __quantum_forge_api_mjs_reduced_density_matrix: typeof reduced_density_matrix;
|
|
229
224
|
declare const __quantum_forge_api_mjs_reset: typeof reset;
|
|
230
225
|
declare const __quantum_forge_api_mjs_shift: typeof shift;
|
|
@@ -233,7 +228,7 @@ declare const __quantum_forge_api_mjs_x: typeof x;
|
|
|
233
228
|
declare const __quantum_forge_api_mjs_y: typeof y;
|
|
234
229
|
declare const __quantum_forge_api_mjs_z: typeof z;
|
|
235
230
|
declare namespace __quantum_forge_api_mjs {
|
|
236
|
-
export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult, type __quantum_forge_api_mjs_InitializeOptions as InitializeOptions, OP$1 as OP, type __quantum_forge_api_mjs_OpCode as OpCode, type __quantum_forge_api_mjs_OpNum as OpNum,
|
|
231
|
+
export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult, type __quantum_forge_api_mjs_InitializeOptions as InitializeOptions, OP$1 as OP, type __quantum_forge_api_mjs_OpCode as OpCode, type __quantum_forge_api_mjs_OpNum as OpNum, Predicate$1 as Predicate, __quantum_forge_api_mjs_QuantumForge as QuantumForge, QuantumProperty$1 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, probabilities$1 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 };
|
|
237
232
|
}
|
|
238
233
|
|
|
239
234
|
/**
|
|
@@ -306,6 +301,444 @@ declare function getAttribution(): string;
|
|
|
306
301
|
*/
|
|
307
302
|
declare function registerServiceWorker(swPath?: string): Promise<ServiceWorkerRegistration | null>;
|
|
308
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Quantum — one handle per quantum property.
|
|
306
|
+
*
|
|
307
|
+
* Declare a property by the values it can take, call gates on it as methods,
|
|
308
|
+
* and end its life with `dispose()` (or a `using` declaration). There is no
|
|
309
|
+
* manager and no `getModule()` in game code.
|
|
310
|
+
*
|
|
311
|
+
* ```typescript
|
|
312
|
+
* import { quantum, measure, ensureLoaded } from "quantum-forge/quantum";
|
|
313
|
+
*
|
|
314
|
+
* await ensureLoaded();
|
|
315
|
+
* const color = quantum(["red", "green", "blue"]); // a qutrit, starts "red"
|
|
316
|
+
* color.superpose(); // alias for hadamard()
|
|
317
|
+
* color.probability("green"); // 1/3, no collapse
|
|
318
|
+
* const c = color.measure(); // "red" | "green" | "blue"
|
|
319
|
+
*
|
|
320
|
+
* const alive = quantum([false, true]);
|
|
321
|
+
* const twin = quantum([false, true]);
|
|
322
|
+
* alive.superpose();
|
|
323
|
+
* twin.flip({ when: [alive.is(true)] }); // CNOT: the pair is now entangled
|
|
324
|
+
* measure(alive, twin); // [false, false] or [true, true]
|
|
325
|
+
* ```
|
|
326
|
+
*
|
|
327
|
+
* `dispose()` always measures the property first. What happens to the WASM
|
|
328
|
+
* property next depends on whether it still shares a state with others:
|
|
329
|
+
*
|
|
330
|
+
* - Alone in its state: it is reset to |0⟩ and kept in a private
|
|
331
|
+
* per-dimension cache, and the next `quantum()` at that dimension reuses it.
|
|
332
|
+
* - Still in a shared state with other qudits: it is destroyed, which factors
|
|
333
|
+
* it out of that state, and it is not cached. Reusing it would hand the next
|
|
334
|
+
* `quantum()` a qudit that still counts against the old state's size.
|
|
335
|
+
*
|
|
336
|
+
* Either way a disposed handle never grows anyone's tensor product.
|
|
337
|
+
*/
|
|
338
|
+
|
|
339
|
+
declare global {
|
|
340
|
+
interface SymbolConstructor {
|
|
341
|
+
readonly dispose: unique symbol;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/** A value a quantum property can be declared with: a game word, a number or a boolean. */
|
|
345
|
+
type QuantumValue = string | number | boolean;
|
|
346
|
+
/** Options accepted by every gate method. */
|
|
347
|
+
interface GateOptions {
|
|
348
|
+
/**
|
|
349
|
+
* Predicates that condition the gate. The gate acts only on the part of the
|
|
350
|
+
* state where every predicate holds. A predicate on another property makes
|
|
351
|
+
* the gate an interaction, which entangles the two.
|
|
352
|
+
*/
|
|
353
|
+
when?: QuantumPredicate[];
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* A condition on one property's value, built by `is()` or `isNot()`.
|
|
357
|
+
* Used in `{ when: [...] }` on gates and by the `*When` free functions.
|
|
358
|
+
*/
|
|
359
|
+
interface QuantumPredicate<V extends QuantumValue = QuantumValue> {
|
|
360
|
+
/** The property this predicate tests. */
|
|
361
|
+
readonly property: Quantum<V>;
|
|
362
|
+
/** The declared value being tested. */
|
|
363
|
+
readonly value: V;
|
|
364
|
+
/** The basis index of `value`. */
|
|
365
|
+
readonly index: number;
|
|
366
|
+
/** True for `is()`, false for `isNot()`. */
|
|
367
|
+
readonly isEqual: boolean;
|
|
368
|
+
/** @internal The WASM predicate. */
|
|
369
|
+
readonly raw: Predicate$1;
|
|
370
|
+
}
|
|
371
|
+
/** A predicate as it appears in observer events: handle id, basis index, polarity. */
|
|
372
|
+
interface SerializedQuantumPredicate {
|
|
373
|
+
id: number;
|
|
374
|
+
index: number;
|
|
375
|
+
isEqual: boolean;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* A gate that ran, as reported to observers.
|
|
379
|
+
*
|
|
380
|
+
* `op` is always the physics operation in the WASM `OpCode` spelling
|
|
381
|
+
* (`"hadamard"`, `"inverse_hadamard"`, `"i_swap"`, ...). Aliases report as the
|
|
382
|
+
* operation they alias: `superpose()` reports `"hadamard"`, `flip()` and
|
|
383
|
+
* `next()` report `"cycle"`, and so on. `fraction` is the value sent to WASM,
|
|
384
|
+
* and is `undefined` when the discrete gate ran.
|
|
385
|
+
*/
|
|
386
|
+
type QuantumGateEvent = {
|
|
387
|
+
op: "hadamard" | "cycle" | "shift" | "clock" | "x" | "y" | "z";
|
|
388
|
+
target: number;
|
|
389
|
+
fraction: number | undefined;
|
|
390
|
+
predicates: SerializedQuantumPredicate[];
|
|
391
|
+
} | {
|
|
392
|
+
op: "inverse_hadamard";
|
|
393
|
+
target: number;
|
|
394
|
+
predicates: SerializedQuantumPredicate[];
|
|
395
|
+
} | {
|
|
396
|
+
op: "swap";
|
|
397
|
+
targets: [number, number];
|
|
398
|
+
predicates: SerializedQuantumPredicate[];
|
|
399
|
+
} | {
|
|
400
|
+
op: "i_swap";
|
|
401
|
+
targets: [number, number];
|
|
402
|
+
fraction: number;
|
|
403
|
+
predicates: SerializedQuantumPredicate[];
|
|
404
|
+
} | {
|
|
405
|
+
op: "phase_rotate";
|
|
406
|
+
angle: number;
|
|
407
|
+
predicates: SerializedQuantumPredicate[];
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* A measurement that ran, as reported to observers. Outcomes are basis
|
|
411
|
+
* indices; predicate outcomes are 1 (all predicates held) or 0.
|
|
412
|
+
*
|
|
413
|
+
* - `"measure"`: `Quantum.measure()` and the free `measure()`.
|
|
414
|
+
* - `"forced_measure"`: `Quantum.forcedMeasure()` and the free `forcedMeasure()`.
|
|
415
|
+
* - `"measure_predicate"`: `measureWhen()`.
|
|
416
|
+
* - `"forced_measure_predicate"`: `forcedMeasureWhen()`.
|
|
417
|
+
*
|
|
418
|
+
* In both forced events the outcome always equals `forced`: forcing an
|
|
419
|
+
* outcome with zero probability throws and reports no event.
|
|
420
|
+
*/
|
|
421
|
+
type QuantumMeasureEvent = {
|
|
422
|
+
op: "measure";
|
|
423
|
+
targets: number[];
|
|
424
|
+
outcomes: number[];
|
|
425
|
+
} | {
|
|
426
|
+
op: "forced_measure";
|
|
427
|
+
targets: number[];
|
|
428
|
+
forced: number[];
|
|
429
|
+
outcomes: number[];
|
|
430
|
+
} | {
|
|
431
|
+
op: "measure_predicate";
|
|
432
|
+
predicates: SerializedQuantumPredicate[];
|
|
433
|
+
outcome: number;
|
|
434
|
+
} | {
|
|
435
|
+
op: "forced_measure_predicate";
|
|
436
|
+
predicates: SerializedQuantumPredicate[];
|
|
437
|
+
forced: number;
|
|
438
|
+
outcome: number;
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Receives every quantum operation after it succeeds in WASM. Attach with
|
|
442
|
+
* `observeQuantum()`. The measurement `dispose()` makes internally is not
|
|
443
|
+
* reported through `onMeasure`; `onDispose` carries its outcome instead.
|
|
444
|
+
*
|
|
445
|
+
* Delivery rules:
|
|
446
|
+
* - An observer that throws does not stop the others from seeing the event,
|
|
447
|
+
* and the error never reaches the code that ran the operation. It is
|
|
448
|
+
* reported with `reportError()` where the runtime has it, else `console.error`.
|
|
449
|
+
* - Events arrive in execution order. An operation run from inside an
|
|
450
|
+
* observer callback is queued, and its event is delivered once the current
|
|
451
|
+
* event has reached every observer.
|
|
452
|
+
* - Each event goes to the observers attached when the operation ran. An
|
|
453
|
+
* observer attached or detached from inside a callback changes who sees
|
|
454
|
+
* later operations, not operations already queued.
|
|
455
|
+
* - Gate and measurement events are deeply frozen, and every observer gets
|
|
456
|
+
* the same object. Copy before changing one. `onCreate` and `onDispose`
|
|
457
|
+
* receive the live handle, which is not frozen.
|
|
458
|
+
*/
|
|
459
|
+
interface QuantumObserver {
|
|
460
|
+
/** A handle was created by `quantum()`. */
|
|
461
|
+
onCreate?(prop: Quantum<any>): void;
|
|
462
|
+
/** A gate ran. */
|
|
463
|
+
onGate?(event: QuantumGateEvent): void;
|
|
464
|
+
/** A measurement ran. */
|
|
465
|
+
onMeasure?(event: QuantumMeasureEvent): void;
|
|
466
|
+
/** A handle was disposed; `value` is the declared value it measured to. */
|
|
467
|
+
onDispose?(prop: Quantum<any>, value: QuantumValue): void;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Marker present on every `Quantum` instance as an own, non-enumerable,
|
|
471
|
+
* read-only data property with value `true`. The engine uses it to find
|
|
472
|
+
* handles on an entity without walking objects it does not understand. It is
|
|
473
|
+
* a registry symbol so two copies of core still recognize each other's
|
|
474
|
+
* handles, and non-enumerable so a spread copy `{ ...handle }` is not a handle.
|
|
475
|
+
*/
|
|
476
|
+
declare const QUANTUM_HANDLE: unique symbol;
|
|
477
|
+
/**
|
|
478
|
+
* One quantum property, declared by its values. Create with `quantum()`; the
|
|
479
|
+
* constructor is private and throws a TypeError when called directly.
|
|
480
|
+
*
|
|
481
|
+
* Every gate returns `this` so calls chain. A gate on one property is
|
|
482
|
+
* evolution; a gate that takes a second property, or whose `when` predicate
|
|
483
|
+
* reads another property, is an interaction and leaves the two entangled.
|
|
484
|
+
*
|
|
485
|
+
* Gates that take a fraction take it as an optional leading number: omit it,
|
|
486
|
+
* or pass exactly 1, for the discrete gate. Options may follow the fraction or
|
|
487
|
+
* stand in its place: `b.flip({ when: [a.is(true)] })` and
|
|
488
|
+
* `b.flip(0.5, { when: [a.is(true)] })` both work.
|
|
489
|
+
*
|
|
490
|
+
* Wherever a value is accepted, pass either a declared value or its basis
|
|
491
|
+
* index. A declared value wins when a number could be both.
|
|
492
|
+
*
|
|
493
|
+
* A bare `Quantum` means `Quantum<QuantumValue>`, so a field typed `Quantum`
|
|
494
|
+
* holds any handle, named or numeric.
|
|
495
|
+
*/
|
|
496
|
+
declare class Quantum<V extends QuantumValue = QuantumValue> {
|
|
497
|
+
#private;
|
|
498
|
+
/**
|
|
499
|
+
* Marker for `isQuantum()`. Always `true`. Defined in the constructor as a
|
|
500
|
+
* non-enumerable data property, so it survives neither a spread nor
|
|
501
|
+
* `Object.assign({}, handle)`.
|
|
502
|
+
*/
|
|
503
|
+
readonly [QUANTUM_HANDLE]: true;
|
|
504
|
+
/** Unique per `quantum()` call, increasing, never reused. */
|
|
505
|
+
readonly id: number;
|
|
506
|
+
/** Declared values in basis order. Index 0 is the starting value. */
|
|
507
|
+
readonly values: readonly V[];
|
|
508
|
+
/** Number of declared values. */
|
|
509
|
+
readonly dimension: number;
|
|
510
|
+
private readonly _raw;
|
|
511
|
+
/**
|
|
512
|
+
* The WASM property behind this handle, for the batch API (`executeBatch`,
|
|
513
|
+
* `executeBatchTape`), which has no handle-level form yet.
|
|
514
|
+
*
|
|
515
|
+
* Caveats:
|
|
516
|
+
* - Operations run through `.raw` are invisible to observers, so a
|
|
517
|
+
* `QuantumRecorder` log will not contain them and a replay will diverge.
|
|
518
|
+
* - Never call `destroy()` on it. The handle still owns it, and its
|
|
519
|
+
* `dispose()` would then fail.
|
|
520
|
+
* - It is valid only while the handle is live. After `dispose()` it may back
|
|
521
|
+
* a different handle, so this getter throws.
|
|
522
|
+
* @throws Error once the handle is disposed.
|
|
523
|
+
*/
|
|
524
|
+
get raw(): QuantumProperty$1;
|
|
525
|
+
private constructor();
|
|
526
|
+
/** True once `dispose()` has run. Every other call then throws. */
|
|
527
|
+
get disposed(): boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Hadamard gate: spread the property evenly across every value.
|
|
530
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
531
|
+
*/
|
|
532
|
+
hadamard(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
533
|
+
/** Inverse Hadamard gate. Undoes `hadamard()`. */
|
|
534
|
+
inverseHadamard(opts?: GateOptions): this;
|
|
535
|
+
/**
|
|
536
|
+
* Cycle gate: move to the next value, wrapping (index + 1 mod dimension).
|
|
537
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
538
|
+
*/
|
|
539
|
+
cycle(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
540
|
+
/**
|
|
541
|
+
* Shift gate: move to the previous value, wrapping (index - 1 mod dimension).
|
|
542
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
543
|
+
*/
|
|
544
|
+
shift(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
545
|
+
/**
|
|
546
|
+
* Clock gate: rotate the phase of each value by its index.
|
|
547
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
548
|
+
*/
|
|
549
|
+
clock(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
550
|
+
/**
|
|
551
|
+
* Pauli X gate. Same as `shift()`; at dimension 2 also the same as `cycle()`.
|
|
552
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
553
|
+
*/
|
|
554
|
+
x(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
555
|
+
/**
|
|
556
|
+
* Pauli Y gate. Dimension 2 only; throws on any other dimension.
|
|
557
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
558
|
+
*/
|
|
559
|
+
y(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
560
|
+
/**
|
|
561
|
+
* Pauli Z gate. Same as `clock()`.
|
|
562
|
+
* @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
|
|
563
|
+
*/
|
|
564
|
+
z(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
565
|
+
/**
|
|
566
|
+
* Alias for `hadamard()`.
|
|
567
|
+
* Spread the property evenly across every value.
|
|
568
|
+
*/
|
|
569
|
+
superpose(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
570
|
+
/**
|
|
571
|
+
* Alias for `cycle()`.
|
|
572
|
+
* Move to the next value, wrapping. `next(0.5)` is half a step.
|
|
573
|
+
*/
|
|
574
|
+
next(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
575
|
+
/**
|
|
576
|
+
* Alias for `shift()`.
|
|
577
|
+
* Move to the previous value, wrapping.
|
|
578
|
+
*/
|
|
579
|
+
previous(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
580
|
+
/**
|
|
581
|
+
* Alias for `clock()`.
|
|
582
|
+
* Turn the phase dial.
|
|
583
|
+
*/
|
|
584
|
+
phase(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
585
|
+
/**
|
|
586
|
+
* Alias for `cycle()`, restricted to dimension 2.
|
|
587
|
+
* Swap the two values. `flip(0.5)` is the square root of NOT. Throws on any
|
|
588
|
+
* other dimension.
|
|
589
|
+
*/
|
|
590
|
+
flip(fraction?: number | GateOptions, opts?: GateOptions): this;
|
|
591
|
+
/**
|
|
592
|
+
* Swap the states of this property and `other`.
|
|
593
|
+
* @throws Error when `other` is this property, or has a different number of values.
|
|
594
|
+
*/
|
|
595
|
+
swap(other: Quantum<any>, opts?: GateOptions): this;
|
|
596
|
+
/**
|
|
597
|
+
* iSwap gate between this property and `other`. `iSwap(other, 0.5)` on
|
|
598
|
+
* a pair where one is set leaves them entangled.
|
|
599
|
+
* @param fraction Required; 1 is a full iSwap.
|
|
600
|
+
* @throws Error when `other` is this property, or has a different number of values.
|
|
601
|
+
*/
|
|
602
|
+
iSwap(other: Quantum<any>, fraction: number, opts?: GateOptions): this;
|
|
603
|
+
/**
|
|
604
|
+
* A predicate that holds when this property equals `value`.
|
|
605
|
+
* @param value A declared value or its basis index.
|
|
606
|
+
* @throws RangeError when `value` is neither.
|
|
607
|
+
*/
|
|
608
|
+
is(value: V | number): QuantumPredicate<V>;
|
|
609
|
+
/**
|
|
610
|
+
* A predicate that holds when this property does not equal `value`.
|
|
611
|
+
* @param value A declared value or its basis index.
|
|
612
|
+
* @throws RangeError when `value` is neither.
|
|
613
|
+
*/
|
|
614
|
+
isNot(value: V | number): QuantumPredicate<V>;
|
|
615
|
+
/** Measure this property, collapsing it and every entangled partner. Returns the declared value. */
|
|
616
|
+
measure(): V;
|
|
617
|
+
/**
|
|
618
|
+
* Measure this property with the outcome forced to `value`. For replays and tests.
|
|
619
|
+
* @param value A declared value or its basis index.
|
|
620
|
+
* @throws Error when `value` has zero probability in the current state. The
|
|
621
|
+
* state is left unchanged.
|
|
622
|
+
*/
|
|
623
|
+
forcedMeasure(value: V | number): V;
|
|
624
|
+
/**
|
|
625
|
+
* Probability that a measurement would give `value`. Does not collapse the state.
|
|
626
|
+
* @param value A declared value or its basis index.
|
|
627
|
+
*/
|
|
628
|
+
probability(value: V | number): number;
|
|
629
|
+
/** Probability of every declared value, in basis order. Does not collapse the state. */
|
|
630
|
+
probabilities(): Array<{
|
|
631
|
+
value: V;
|
|
632
|
+
probability: number;
|
|
633
|
+
}>;
|
|
634
|
+
/**
|
|
635
|
+
* End this property's life. Measures it first, which collapses any
|
|
636
|
+
* entangled partners. Then:
|
|
637
|
+
*
|
|
638
|
+
* - If it is alone in its state, it is reset to its first value and its
|
|
639
|
+
* WASM property goes to a private cache for the next `quantum()` at this
|
|
640
|
+
* dimension.
|
|
641
|
+
* - If it still shares a state with other qudits, its WASM property is
|
|
642
|
+
* destroyed, which factors it out of that state, and it is not cached.
|
|
643
|
+
* A partner left on its own shrinks back to one qudit.
|
|
644
|
+
*
|
|
645
|
+
* Calling it again does nothing. Works on a frozen handle.
|
|
646
|
+
*/
|
|
647
|
+
dispose(): void;
|
|
648
|
+
/** Same as `dispose()`, so a `using` declaration disposes the handle at scope exit. */
|
|
649
|
+
[Symbol.dispose](): void;
|
|
650
|
+
/** Number of qudits in the shared state this property belongs to. */
|
|
651
|
+
numActiveQudits(): number;
|
|
652
|
+
/** Number of basis amplitudes in the shared state vector. */
|
|
653
|
+
stateVectorSize(): number;
|
|
654
|
+
private _predicate;
|
|
655
|
+
/** Checks shared by swap() and iSwap(). Returns the WASM predicates. */
|
|
656
|
+
private _pair;
|
|
657
|
+
private _gate;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Create a quantum property declared by its values. The dimension is the
|
|
661
|
+
* number of values, and the property starts at the first one.
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* const color = quantum(["red", "green", "blue"]);
|
|
665
|
+
* const alive = quantum([false, true]);
|
|
666
|
+
* @throws RangeError when `values` has fewer than 2 entries or a non-finite number.
|
|
667
|
+
* @throws Error when `values` has duplicates, or more entries than the loaded build's maximum dimension.
|
|
668
|
+
*/
|
|
669
|
+
declare function quantum<V extends QuantumValue>(values: readonly V[]): Quantum<V>;
|
|
670
|
+
/**
|
|
671
|
+
* Create a quantum property with `dimension` values `0..dimension-1`, starting at 0.
|
|
672
|
+
* @throws RangeError when `dimension` is not an integer, or is less than 2.
|
|
673
|
+
* @throws Error when `dimension` exceeds the loaded build's maximum dimension.
|
|
674
|
+
*/
|
|
675
|
+
declare function quantum(dimension: number): Quantum<number>;
|
|
676
|
+
/**
|
|
677
|
+
* True when `x` is a `Quantum` handle: it has an own `QUANTUM_HANDLE` data
|
|
678
|
+
* property whose value is `true`. The marker is read through its descriptor,
|
|
679
|
+
* so a getter under that key is never invoked, and a spread copy of a handle
|
|
680
|
+
* (which drops the non-enumerable marker) is not a handle.
|
|
681
|
+
*/
|
|
682
|
+
declare function isQuantum(x: unknown): x is Quantum<any>;
|
|
683
|
+
/**
|
|
684
|
+
* Destroy every cached WASM property and empty the cache. Live handles are not
|
|
685
|
+
* affected. Meant for tests and for freeing memory between scenes.
|
|
686
|
+
*/
|
|
687
|
+
declare function clearQuantumCache(): void;
|
|
688
|
+
/**
|
|
689
|
+
* Attach an observer that sees every quantum operation after it succeeds.
|
|
690
|
+
* @returns A function that detaches the observer.
|
|
691
|
+
*/
|
|
692
|
+
declare function observeQuantum(observer: QuantumObserver): () => void;
|
|
693
|
+
/**
|
|
694
|
+
* Measure several properties together. Returns each one's declared value, in argument order.
|
|
695
|
+
* @example const [a, b] = measure(alive, twin);
|
|
696
|
+
*/
|
|
697
|
+
declare function measure(...props: Quantum<any>[]): QuantumValue[];
|
|
698
|
+
/**
|
|
699
|
+
* Measure several properties together with each outcome forced. For replays and tests.
|
|
700
|
+
* @param values One declared value or basis index per property.
|
|
701
|
+
* @throws Error when the combination of values has zero probability in the
|
|
702
|
+
* current state. The state is left unchanged.
|
|
703
|
+
*/
|
|
704
|
+
declare function forcedMeasure(props: Quantum<any>[], values: QuantumValue[]): QuantumValue[];
|
|
705
|
+
/**
|
|
706
|
+
* Joint probabilities over several properties. Each entry lists one declared
|
|
707
|
+
* value per property, in argument order. Does not collapse the state.
|
|
708
|
+
*/
|
|
709
|
+
declare function probabilities(...props: Quantum<any>[]): Array<{
|
|
710
|
+
values: QuantumValue[];
|
|
711
|
+
probability: number;
|
|
712
|
+
}>;
|
|
713
|
+
/**
|
|
714
|
+
* Reduced density matrix over several properties. Rows and columns are
|
|
715
|
+
* labelled with one declared value per property. Does not collapse the state.
|
|
716
|
+
*/
|
|
717
|
+
declare function densityMatrix(...props: Quantum<any>[]): Array<{
|
|
718
|
+
row: QuantumValue[];
|
|
719
|
+
col: QuantumValue[];
|
|
720
|
+
real: number;
|
|
721
|
+
imag: number;
|
|
722
|
+
}>;
|
|
723
|
+
/** Measure whether every predicate holds, collapsing the state to agree. */
|
|
724
|
+
declare function measureWhen(preds: QuantumPredicate[]): boolean;
|
|
725
|
+
/**
|
|
726
|
+
* Measure whether every predicate holds, with the outcome forced. For replays
|
|
727
|
+
* and tests. Returns `outcome`.
|
|
728
|
+
* @throws Error when the forced outcome has zero probability in the current
|
|
729
|
+
* state. The state is left unchanged.
|
|
730
|
+
*/
|
|
731
|
+
declare function forcedMeasureWhen(preds: QuantumPredicate[], outcome: boolean): boolean;
|
|
732
|
+
/** Probability that every predicate holds at once. Does not collapse the state. */
|
|
733
|
+
declare function probabilityWhen(preds: QuantumPredicate[]): number;
|
|
734
|
+
/**
|
|
735
|
+
* Rotate the phase of the part of the state where every predicate holds by `angle` radians.
|
|
736
|
+
* @example phaseRotate(Math.PI, { when: [a.is(1), b.is(1)] });
|
|
737
|
+
*/
|
|
738
|
+
declare function phaseRotate(angle: number, opts: {
|
|
739
|
+
when: QuantumPredicate[];
|
|
740
|
+
}): void;
|
|
741
|
+
|
|
309
742
|
/**
|
|
310
743
|
* QuantumPropertyManager — manages quantum property lifecycles.
|
|
311
744
|
*
|
|
@@ -316,20 +749,26 @@ declare function registerServiceWorker(swPath?: string): Promise<ServiceWorkerRe
|
|
|
316
749
|
* Property pooling is critical: measured/removed properties are recycled
|
|
317
750
|
* to avoid growing the tensor product and hitting qudit limits.
|
|
318
751
|
*
|
|
319
|
-
* For opt-in operation recording, attach a
|
|
752
|
+
* For opt-in operation recording, attach a LegacyQuantumRecorder via setRecorder().
|
|
320
753
|
*/
|
|
321
754
|
|
|
322
755
|
interface PredicateSpec$1 {
|
|
323
|
-
property: QuantumProperty;
|
|
756
|
+
property: QuantumProperty$1;
|
|
324
757
|
value: number;
|
|
325
758
|
isEqual: boolean;
|
|
326
759
|
}
|
|
327
760
|
interface QuantumRecorderHook {
|
|
328
|
-
onAcquire?(prop: QuantumProperty): void;
|
|
329
|
-
onRelease?(prop: QuantumProperty, value: number): void;
|
|
330
|
-
onSetProperty?(id: string, prop: QuantumProperty): void;
|
|
761
|
+
onAcquire?(prop: QuantumProperty$1): void;
|
|
762
|
+
onRelease?(prop: QuantumProperty$1, value: number): void;
|
|
763
|
+
onSetProperty?(id: string, prop: QuantumProperty$1): void;
|
|
331
764
|
onDeleteProperty?(id: string): void;
|
|
332
765
|
}
|
|
766
|
+
/**
|
|
767
|
+
* Pools raw WASM properties behind string ids.
|
|
768
|
+
*
|
|
769
|
+
* @deprecated Use `quantum()` handles from the same entry point; see
|
|
770
|
+
* docs/QUANTUM_INTEGRATION.md. Removed in 4.0.
|
|
771
|
+
*/
|
|
333
772
|
declare class QuantumPropertyManager {
|
|
334
773
|
readonly dimension: number;
|
|
335
774
|
private properties;
|
|
@@ -348,15 +787,15 @@ declare class QuantumPropertyManager {
|
|
|
348
787
|
* Get a property at |0⟩ — reuses a pooled one if available,
|
|
349
788
|
* otherwise creates a fresh standalone property.
|
|
350
789
|
*/
|
|
351
|
-
acquireProperty(): QuantumProperty;
|
|
790
|
+
acquireProperty(): QuantumProperty$1;
|
|
352
791
|
/**
|
|
353
792
|
* Return a property to the pool after resetting it to |0⟩.
|
|
354
793
|
* Uses the `reset` primitive which applies non-fractional cycles —
|
|
355
794
|
* correct for all dimensions (no superposition created).
|
|
356
795
|
*/
|
|
357
|
-
releaseProperty(prop: QuantumProperty, measuredValue: number): void;
|
|
358
|
-
setProperty(id: string, prop: QuantumProperty): void;
|
|
359
|
-
getProperty(id: string): QuantumProperty | undefined;
|
|
796
|
+
releaseProperty(prop: QuantumProperty$1, measuredValue: number): void;
|
|
797
|
+
setProperty(id: string, prop: QuantumProperty$1): void;
|
|
798
|
+
getProperty(id: string): QuantumProperty$1 | undefined;
|
|
360
799
|
deleteProperty(id: string): void;
|
|
361
800
|
hasProperty(id: string): boolean;
|
|
362
801
|
/**
|
|
@@ -368,12 +807,173 @@ declare class QuantumPropertyManager {
|
|
|
368
807
|
get size(): number;
|
|
369
808
|
get poolSize(): number;
|
|
370
809
|
getModule(): ReturnType<typeof getModule>;
|
|
371
|
-
/** @internal — used by
|
|
372
|
-
_setPool(pool: QuantumProperty[]): void;
|
|
373
|
-
/** @internal — used by
|
|
374
|
-
_getProperties(): Map<string, QuantumProperty>;
|
|
375
|
-
/** @internal — used by
|
|
376
|
-
_getPool(): QuantumProperty[];
|
|
810
|
+
/** @internal — used by LegacyQuantumRecorder.replayLog() to restore pool state. */
|
|
811
|
+
_setPool(pool: QuantumProperty$1[]): void;
|
|
812
|
+
/** @internal — used by LegacyQuantumRecorder to enumerate live handles. */
|
|
813
|
+
_getProperties(): Map<string, QuantumProperty$1>;
|
|
814
|
+
/** @internal — used by LegacyQuantumRecorder to enumerate pool handles. */
|
|
815
|
+
_getPool(): QuantumProperty$1[];
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* QuantumRecorder — opt-in recording and replay of `quantum()` handles.
|
|
820
|
+
*
|
|
821
|
+
* The recorder attaches through `observeQuantum()`, so every gate, measurement,
|
|
822
|
+
* creation and disposal is logged without the game calling anything extra.
|
|
823
|
+
* Entries name handles by their `id` and values by basis index, and the log is
|
|
824
|
+
* plain JSON: `{ "version": 1, "entries": [...] }`.
|
|
825
|
+
*
|
|
826
|
+
* ```typescript
|
|
827
|
+
* const recorder = new QuantumRecorder();
|
|
828
|
+
* recorder.startRecording();
|
|
829
|
+
* const a = quantum([false, true]);
|
|
830
|
+
* const b = quantum([false, true]);
|
|
831
|
+
* a.superpose();
|
|
832
|
+
* b.flip({ when: [a.is(true)] });
|
|
833
|
+
* measure(a, b);
|
|
834
|
+
* const text = QuantumRecorder.serialize(recorder.stopRecording());
|
|
835
|
+
*
|
|
836
|
+
* const handles = QuantumRecorder.replay(QuantumRecorder.deserialize(text));
|
|
837
|
+
* handles.get(a.id); // the replayed `a`, collapsed to the recorded outcome
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
840
|
+
|
|
841
|
+
type FractionalGateOp = "hadamard" | "cycle" | "shift" | "clock" | "x" | "y" | "z";
|
|
842
|
+
/**
|
|
843
|
+
* One recorded operation. Handles are named by `id`, values by basis index.
|
|
844
|
+
*
|
|
845
|
+
* Gate and measurement entries mirror `QuantumGateEvent` and
|
|
846
|
+
* `QuantumMeasureEvent` one to one, with op names in the WASM spelling
|
|
847
|
+
* (`"hadamard"`, `"cycle"`, `"i_swap"`, ...). A gate's `fraction` is omitted
|
|
848
|
+
* when the discrete gate ran.
|
|
849
|
+
*/
|
|
850
|
+
type QuantumLogEntry = {
|
|
851
|
+
op: "create";
|
|
852
|
+
id: number;
|
|
853
|
+
values: QuantumValue[];
|
|
854
|
+
} | {
|
|
855
|
+
op: "dispose";
|
|
856
|
+
id: number;
|
|
857
|
+
outcome: number;
|
|
858
|
+
} | {
|
|
859
|
+
op: FractionalGateOp;
|
|
860
|
+
target: number;
|
|
861
|
+
fraction?: number;
|
|
862
|
+
predicates: SerializedQuantumPredicate[];
|
|
863
|
+
} | {
|
|
864
|
+
op: "inverse_hadamard";
|
|
865
|
+
target: number;
|
|
866
|
+
predicates: SerializedQuantumPredicate[];
|
|
867
|
+
} | {
|
|
868
|
+
op: "swap";
|
|
869
|
+
targets: [number, number];
|
|
870
|
+
predicates: SerializedQuantumPredicate[];
|
|
871
|
+
} | {
|
|
872
|
+
op: "i_swap";
|
|
873
|
+
targets: [number, number];
|
|
874
|
+
fraction: number;
|
|
875
|
+
predicates: SerializedQuantumPredicate[];
|
|
876
|
+
} | {
|
|
877
|
+
op: "phase_rotate";
|
|
878
|
+
angle: number;
|
|
879
|
+
predicates: SerializedQuantumPredicate[];
|
|
880
|
+
} | {
|
|
881
|
+
op: "measure";
|
|
882
|
+
targets: number[];
|
|
883
|
+
outcomes: number[];
|
|
884
|
+
} | {
|
|
885
|
+
op: "forced_measure";
|
|
886
|
+
targets: number[];
|
|
887
|
+
forced: number[];
|
|
888
|
+
outcomes: number[];
|
|
889
|
+
} | {
|
|
890
|
+
op: "measure_predicate";
|
|
891
|
+
predicates: SerializedQuantumPredicate[];
|
|
892
|
+
outcome: number;
|
|
893
|
+
} | {
|
|
894
|
+
op: "forced_measure_predicate";
|
|
895
|
+
predicates: SerializedQuantumPredicate[];
|
|
896
|
+
forced: number;
|
|
897
|
+
outcome: number;
|
|
898
|
+
};
|
|
899
|
+
/** The log format version `serialize()` writes and `deserialize()` accepts. */
|
|
900
|
+
declare const LOG_VERSION = 1;
|
|
901
|
+
/**
|
|
902
|
+
* A recorded session: `{ version: 1, entries: [...] }`. `getLog()`,
|
|
903
|
+
* `stopRecording()` and `deserialize()` return this shape, and `serialize()`
|
|
904
|
+
* and `replay()` take it.
|
|
905
|
+
*
|
|
906
|
+
* `untrackedIds` is present only when the recording touched handles created
|
|
907
|
+
* before `startRecording()`. Such a log cannot be replayed: `replay()` throws.
|
|
908
|
+
*/
|
|
909
|
+
interface QuantumLog {
|
|
910
|
+
version: typeof LOG_VERSION;
|
|
911
|
+
entries: QuantumLogEntry[];
|
|
912
|
+
/** Ids of handles the log references but never creates, in ascending order. */
|
|
913
|
+
untrackedIds?: number[];
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Records every operation on `quantum()` handles into a JSON-safe log, and
|
|
917
|
+
* replays a log into fresh handles with the same state.
|
|
918
|
+
*
|
|
919
|
+
* Start recording before creating the handles you want replayed. When a
|
|
920
|
+
* recorded operation touches a handle created before `startRecording()`, the
|
|
921
|
+
* recorder warns once per handle through `console.warn`, keeps recording, and
|
|
922
|
+
* lists the handle's id in the log's `untrackedIds`. `replay()` refuses such a
|
|
923
|
+
* log.
|
|
924
|
+
*
|
|
925
|
+
* Replay runs every measurement as its forced variant with the recorded
|
|
926
|
+
* outcomes, so the replayed state matches the recorded one. A recorder that is
|
|
927
|
+
* running during a replay records what the replay did: the fresh handles'
|
|
928
|
+
* `create` entries and the forced measurements. So "load a save, keep
|
|
929
|
+
* recording" yields a log that replays on its own.
|
|
930
|
+
*/
|
|
931
|
+
declare class QuantumRecorder {
|
|
932
|
+
private _entries;
|
|
933
|
+
private _seen;
|
|
934
|
+
private _untracked;
|
|
935
|
+
private _detach;
|
|
936
|
+
/**
|
|
937
|
+
* @throws TypeError when given any argument. The 2.x recorder took a
|
|
938
|
+
* `QuantumPropertyManager`; that one is now `LegacyQuantumRecorder`.
|
|
939
|
+
*/
|
|
940
|
+
constructor(...args: []);
|
|
941
|
+
/** Begin recording. Clears the log. Calling it while recording restarts with an empty log. */
|
|
942
|
+
startRecording(): void;
|
|
943
|
+
/** Note created ids, and warn the first time an entry touches a handle this recording never saw created. */
|
|
944
|
+
private _track;
|
|
945
|
+
/**
|
|
946
|
+
* Stop recording and return the log, `{ version: 1, entries }`. The log
|
|
947
|
+
* carries `untrackedIds` when it touched handles created before recording.
|
|
948
|
+
*/
|
|
949
|
+
stopRecording(): QuantumLog;
|
|
950
|
+
/** True between `startRecording()` and `stopRecording()`. */
|
|
951
|
+
isRecording(): boolean;
|
|
952
|
+
/** A copy of the log so far, `{ version: 1, entries }`. Works while recording. */
|
|
953
|
+
getLog(): QuantumLog;
|
|
954
|
+
/**
|
|
955
|
+
* Replay a log into new handles. Each `create` makes a fresh handle with a
|
|
956
|
+
* new id; the returned map is keyed by the id in the log. Handles the log
|
|
957
|
+
* disposes are removed from the map, so it holds the handles still live at
|
|
958
|
+
* the end of the log.
|
|
959
|
+
*
|
|
960
|
+
* The log is validated first, as `deserialize()` does. A recorder running
|
|
961
|
+
* during the replay records it (see the class docs); the log passed in is
|
|
962
|
+
* never modified.
|
|
963
|
+
*
|
|
964
|
+
* @throws Error when the log is malformed, lists `untrackedIds`, or an entry
|
|
965
|
+
* references an id with no earlier `create` entry. No handle survives a throw.
|
|
966
|
+
*/
|
|
967
|
+
static replay(log: QuantumLog): Map<number, Quantum<any>>;
|
|
968
|
+
/** Serialize a log to JSON: `{ "version": 1, "entries": [...] }`. */
|
|
969
|
+
static serialize(log: QuantumLog): string;
|
|
970
|
+
/**
|
|
971
|
+
* Parse a log serialized by `serialize()`.
|
|
972
|
+
* @throws Error when the text is not JSON, the version is missing or
|
|
973
|
+
* unsupported, or any entry is malformed or names a basis index outside its
|
|
974
|
+
* handle's declared values.
|
|
975
|
+
*/
|
|
976
|
+
static deserialize(text: string): QuantumLog;
|
|
377
977
|
}
|
|
378
978
|
|
|
379
979
|
/**
|
|
@@ -384,11 +984,13 @@ declare class QuantumPropertyManager {
|
|
|
384
984
|
* handle values. On replay, `forced_measure_properties` reproduces the
|
|
385
985
|
* exact measurement outcomes, yielding identical quantum state.
|
|
386
986
|
*/
|
|
987
|
+
/** @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0. */
|
|
387
988
|
interface SerializedPredicate {
|
|
388
989
|
propertyIndex: number;
|
|
389
990
|
value: number;
|
|
390
991
|
isEqual: boolean;
|
|
391
992
|
}
|
|
993
|
+
/** @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0. */
|
|
392
994
|
type QuantumOperation = {
|
|
393
995
|
op: "acquire";
|
|
394
996
|
index: number;
|
|
@@ -462,7 +1064,9 @@ type QuantumOperation = {
|
|
|
462
1064
|
};
|
|
463
1065
|
|
|
464
1066
|
/**
|
|
465
|
-
*
|
|
1067
|
+
* LegacyQuantumRecorder — opt-in recording and replay of quantum operations
|
|
1068
|
+
* for QuantumPropertyManager. Superseded by QuantumRecorder, which records
|
|
1069
|
+
* `quantum()` handles.
|
|
466
1070
|
*
|
|
467
1071
|
* Attach to a QuantumPropertyManager via `manager.setRecorder(recorder)`.
|
|
468
1072
|
* When recording is active, lifecycle hooks log every state-mutating
|
|
@@ -474,25 +1078,30 @@ type QuantumOperation = {
|
|
|
474
1078
|
*/
|
|
475
1079
|
|
|
476
1080
|
interface PredicateSpec {
|
|
477
|
-
property: QuantumProperty;
|
|
1081
|
+
property: QuantumProperty$1;
|
|
478
1082
|
value: number;
|
|
479
1083
|
isEqual: boolean;
|
|
480
1084
|
}
|
|
481
|
-
|
|
1085
|
+
/**
|
|
1086
|
+
* Records and replays operations on a QuantumPropertyManager's pooled properties.
|
|
1087
|
+
*
|
|
1088
|
+
* @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0.
|
|
1089
|
+
*/
|
|
1090
|
+
declare class LegacyQuantumRecorder implements QuantumRecorderHook {
|
|
482
1091
|
private _recording;
|
|
483
1092
|
private _log;
|
|
484
1093
|
private _handleToIndex;
|
|
485
1094
|
private _nextIndex;
|
|
486
1095
|
private readonly _manager;
|
|
487
1096
|
constructor(manager: QuantumPropertyManager);
|
|
488
|
-
onAcquire(prop: QuantumProperty): void;
|
|
489
|
-
onRelease(prop: QuantumProperty, value: number): void;
|
|
490
|
-
onSetProperty(id: string, prop: QuantumProperty): void;
|
|
1097
|
+
onAcquire(prop: QuantumProperty$1): void;
|
|
1098
|
+
onRelease(prop: QuantumProperty$1, value: number): void;
|
|
1099
|
+
onSetProperty(id: string, prop: QuantumProperty$1): void;
|
|
491
1100
|
onDeleteProperty(id: string): void;
|
|
492
1101
|
/**
|
|
493
1102
|
* Build WASM predicate objects from PredicateSpec array.
|
|
494
1103
|
*/
|
|
495
|
-
buildWasmPredicates(specs: PredicateSpec[]): Predicate[];
|
|
1104
|
+
buildWasmPredicates(specs: PredicateSpec[]): Predicate$1[];
|
|
496
1105
|
/**
|
|
497
1106
|
* Serialize predicates for the operation log.
|
|
498
1107
|
*/
|
|
@@ -505,7 +1114,7 @@ declare class QuantumRecorder implements QuantumRecorderHook {
|
|
|
505
1114
|
/**
|
|
506
1115
|
* Get the recorded index for a property handle.
|
|
507
1116
|
*/
|
|
508
|
-
getIndex(prop: QuantumProperty): number | undefined;
|
|
1117
|
+
getIndex(prop: QuantumProperty$1): number | undefined;
|
|
509
1118
|
/** Begin recording quantum operations. Resets any existing log. */
|
|
510
1119
|
startRecording(): void;
|
|
511
1120
|
/** Stop recording and return the captured log. */
|
|
@@ -523,6 +1132,10 @@ declare class QuantumRecorder implements QuantumRecorderHook {
|
|
|
523
1132
|
private _replayPredicates;
|
|
524
1133
|
}
|
|
525
1134
|
|
|
1135
|
+
/** The WASM property `Quantum.raw` returns, for the batch API (`executeBatch`, `executeBatchTape`). */
|
|
1136
|
+
type QuantumProperty = QuantumProperty$1;
|
|
1137
|
+
/** The WASM predicate behind `QuantumPredicate.raw`. */
|
|
1138
|
+
type Predicate = Predicate$1;
|
|
526
1139
|
/** Numeric opcode constants for tape encoding. Matches C++ OpCode enum. */
|
|
527
1140
|
declare const OP: {
|
|
528
1141
|
readonly CYCLE: 0;
|
|
@@ -539,4 +1152,4 @@ declare const OP: {
|
|
|
539
1152
|
readonly ROTATE_BASIS_PAIR: 11;
|
|
540
1153
|
};
|
|
541
1154
|
|
|
542
|
-
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, getWasmBasePath, getWasmMemoryBytes, isReady, registerServiceWorker, setWasmBasePath, startBackgroundLoad, useQuantumForgeBuild };
|
|
1155
|
+
export { type BatchOp, type BatchResult, type GateOptions, LegacyQuantumRecorder, OP, type OpCode, type OpNum, type Predicate, type PredicateSpec$1 as PredicateSpec, QUANTUM_HANDLE, Quantum, type QuantumGateEvent, type QuantumLog, type QuantumLogEntry, type QuantumMeasureEvent, type QuantumObserver, type QuantumOperation, type QuantumPredicate, type QuantumProperty, QuantumPropertyManager, QuantumRecorder, type QuantumRecorderHook, type QuantumValue, type SerializedPredicate, type SerializedQuantumPredicate, clearQuantumCache, densityMatrix, ensureLoaded, forcedMeasure, forcedMeasureWhen, getAttribution, getMaxDimension, getMaxQudits, getMaxStateSize, getModule, getQuantumForge, getVersion, getWasmBasePath, getWasmMemoryBytes, isQuantum, isReady, measure, measureWhen, observeQuantum, phaseRotate, probabilities, probabilityWhen, quantum, registerServiceWorker, setWasmBasePath, startBackgroundLoad, useQuantumForgeBuild };
|