microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/spike-3310

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/npm/qsharp/test/stateCompute.test.mjs

218lines · modecode

1import test from "node:test";
2import assert from "node:assert/strict";
3import { computeAmpMapForCircuit } from "../dist/ux/circuit-vis/state-viz/worker/stateCompute.js";
4import { evaluateAngleExpression } from "../dist/ux/circuit-vis/angleExpression.js";
5
6const approxEq = (a, b, eps = 1e-12) => Math.abs(a - b) <= eps;
7
8test("π and pi keyword", () => {
9 assert.ok(approxEq(evaluateAngleExpression("π"), Math.PI));
10 assert.ok(approxEq(evaluateAngleExpression("+π"), Math.PI));
11 assert.ok(approxEq(evaluateAngleExpression("-π"), -Math.PI));
12 assert.ok(approxEq(evaluateAngleExpression("pi"), Math.PI));
13 assert.ok(approxEq(evaluateAngleExpression("+pi"), Math.PI));
14 assert.ok(approxEq(evaluateAngleExpression("-pi"), -Math.PI));
15 assert.ok(approxEq(evaluateAngleExpression("Pi"), Math.PI));
16 assert.ok(approxEq(evaluateAngleExpression("+Pi"), Math.PI));
17 assert.ok(approxEq(evaluateAngleExpression("-Pi"), -Math.PI));
18 assert.ok(approxEq(evaluateAngleExpression("PI"), Math.PI));
19 assert.ok(approxEq(evaluateAngleExpression("+PI"), Math.PI));
20 assert.ok(approxEq(evaluateAngleExpression("-PI"), -Math.PI));
21});
22
23test("basic numbers", () => {
24 assert.ok(approxEq(evaluateAngleExpression("5"), 5));
25 assert.ok(approxEq(evaluateAngleExpression("+5"), 5));
26 assert.ok(approxEq(evaluateAngleExpression("-5"), -5));
27 assert.ok(approxEq(evaluateAngleExpression("3.5"), 3.5));
28 assert.ok(approxEq(evaluateAngleExpression("+3.5"), 3.5));
29 assert.ok(approxEq(evaluateAngleExpression("-3.5"), -3.5));
30 assert.ok(approxEq(evaluateAngleExpression("5."), 5));
31 assert.ok(approxEq(evaluateAngleExpression("+5."), 5));
32 assert.ok(approxEq(evaluateAngleExpression("-5."), -5));
33});
34
35test("arithmetic operations", () => {
36 assert.ok(approxEq(evaluateAngleExpression("π/2"), Math.PI / 2));
37 assert.ok(approxEq(evaluateAngleExpression("-π/2"), -Math.PI / 2));
38 assert.ok(approxEq(evaluateAngleExpression("2*pi"), 2 * Math.PI));
39 assert.ok(approxEq(evaluateAngleExpression("π + 2 - 3"), Math.PI - 1));
40 assert.ok(approxEq(evaluateAngleExpression("2 * (pi / 4)"), Math.PI / 2));
41});
42
43test("parentheses nesting", () => {
44 assert.ok(approxEq(evaluateAngleExpression("((π))"), Math.PI));
45});
46
47test("invalid inputs return undefined", () => {
48 assert.equal(evaluateAngleExpression("++π"), undefined);
49 assert.equal(evaluateAngleExpression("--π"), undefined);
50 assert.equal(evaluateAngleExpression("π // 2"), undefined);
51 assert.equal(evaluateAngleExpression("1..2"), undefined);
52 assert.equal(evaluateAngleExpression("(π"), undefined);
53 assert.equal(evaluateAngleExpression("π / 0"), undefined); // Infinity -> undefined
54 assert.equal(evaluateAngleExpression(""), undefined);
55 assert.equal(evaluateAngleExpression(".5"), undefined);
56 assert.equal(evaluateAngleExpression("+.5"), undefined);
57 assert.equal(evaluateAngleExpression("-.5"), undefined);
58});
59
60const colUnitaryAt = (gate, target, args, opts) => ({
61 components: [
62 {
63 kind: "unitary",
64 gate,
65 targets: [{ qubit: target }],
66 ...(opts?.controls?.length
67 ? { controls: opts.controls.map((qubit) => ({ qubit })) }
68 : null),
69 args,
70 ...(opts?.isAdjoint ? { isAdjoint: true } : null),
71 },
72 ],
73});
74const colUnitary = (gate, args, opts) => colUnitaryAt(gate, 0, args, opts);
75const colReset0 = () => ({
76 components: [{ kind: "ket", gate: "0", targets: [{ qubit: 0 }] }],
77});
78const colMeasure0 = () => ({
79 components: [
80 {
81 kind: "measurement",
82 gate: "M",
83 qubits: [{ qubit: 0 }],
84 results: [{ qubit: 0, result: 0 }],
85 },
86 ],
87});
88
89const assertAmp = (amp, re, im) => {
90 assert.ok(approxEq(amp.re, re, 1e-11), `re expected ${re} got ${amp.re}`);
91 assert.ok(approxEq(amp.im, im, 1e-11), `im expected ${im} got ${amp.im}`);
92};
93
94test("Single adjoint: S† on |1⟩ yields -i|1⟩", () => {
95 const qubits = [{ id: 0 }];
96 const componentGrid = [
97 // Prepare |1⟩ then apply S†: S†|1⟩ = -i|1⟩
98 colUnitary("X"),
99 colUnitary("S", undefined, { isAdjoint: true }),
100 ];
101 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
102 assertAmp(ampMap["1"], 0, -1);
103});
104
105test("Single adjoint: T† on |1⟩ yields e^{-iπ/4}|1⟩", () => {
106 const qubits = [{ id: 0 }];
107 const componentGrid = [
108 // Prepare |1⟩ then apply T†: T†|1⟩ = e^{-iπ/4}|1⟩
109 colUnitary("X"),
110 colUnitary("T", undefined, { isAdjoint: true }),
111 ];
112 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
113 assertAmp(ampMap["1"], Math.SQRT1_2, -Math.SQRT1_2);
114});
115
116test("Single adjoint: SX† on |0⟩ matches expected amplitudes", () => {
117 const qubits = [{ id: 0 }];
118 const componentGrid = [colUnitary("SX", undefined, { isAdjoint: true })];
119 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
120 // SX†|0⟩ = (0.5-0.5i)|0⟩ + (0.5+0.5i)|1⟩
121 assertAmp(ampMap["0"], 0.5, -0.5);
122 assertAmp(ampMap["1"], 0.5, 0.5);
123});
124
125test("Gate then adjoint returns |0⟩ (Rx(π/3))", () => {
126 const qubits = [{ id: 0 }];
127 const componentGrid = [
128 colUnitary("Rx", ["π/3"]),
129 colUnitary("Rx", ["π/3"], { isAdjoint: true }),
130 ];
131 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
132 assertAmp(ampMap["0"], 1, 0);
133});
134
135test("Single adjoint: Ry†(π/3) from |0⟩ flips |1⟩ sign", () => {
136 const qubits = [{ id: 0 }];
137 const componentGrid = [colUnitary("Ry", ["π/3"], { isAdjoint: true })];
138 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
139 const c = Math.cos(Math.PI / 6);
140 const s = Math.sin(Math.PI / 6);
141 assertAmp(ampMap["0"], c, 0);
142 assertAmp(ampMap["1"], -s, 0);
143});
144
145test("Single adjoint: Rz†(π/3) on |1⟩ applies e^{-iπ/6}", () => {
146 const qubits = [{ id: 0 }];
147 const componentGrid = [
148 colUnitary("X"),
149 colUnitary("Rz", ["π/3"], { isAdjoint: true }),
150 ];
151 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
152 assertAmp(ampMap["1"], Math.cos(-Math.PI / 6), Math.sin(-Math.PI / 6));
153});
154
155test("Single adjoint: S† after H gives |0⟩ - i|1⟩ over √2", () => {
156 const qubits = [{ id: 0 }];
157 const componentGrid = [
158 colUnitary("H"),
159 colUnitary("S", undefined, { isAdjoint: true }),
160 ];
161 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
162 assertAmp(ampMap["0"], Math.SQRT1_2, 0);
163 assertAmp(ampMap["1"], 0, -Math.SQRT1_2);
164});
165
166test("Single adjoint: controlled S† phases |11⟩ by -i", () => {
167 const qubits = [{ id: 0 }, { id: 1 }];
168 const componentGrid = [
169 colUnitaryAt("X", 0),
170 colUnitaryAt("X", 1),
171 colUnitaryAt("S", 1, undefined, { controls: [0], isAdjoint: true }),
172 ];
173 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
174 assertAmp(ampMap["11"], 0, -1);
175});
176
177test("Single adjoint: controlled Rz† no-ops when control is |0⟩", () => {
178 const qubits = [{ id: 0 }, { id: 1 }];
179 const componentGrid = [
180 // Prepare |01⟩ (control qubit 0 is 0, target qubit 1 is 1)
181 colUnitaryAt("X", 1),
182 colUnitaryAt("Rz", 1, ["π/3"], { controls: [0], isAdjoint: true }),
183 ];
184 const ampMap = computeAmpMapForCircuit(qubits, componentGrid);
185 assertAmp(ampMap["01"], 1, 0);
186});
187
188test("Reset is unsupported by stateCompute", () => {
189 const qubits = [{ id: 0 }];
190 const componentGrid = [colUnitary("H"), colReset0()];
191 assert.throws(
192 () => computeAmpMapForCircuit(qubits, componentGrid),
193 (err) => {
194 assert.equal(err?.name, "UnsupportedStateComputeError");
195 assert.equal(
196 err?.message,
197 "State visualization does not currently support measurement or ResetZ / |0⟩ reset operations.",
198 );
199 return true;
200 },
201 );
202});
203
204test("Measurement is unsupported by stateCompute", () => {
205 const qubits = [{ id: 0 }];
206 const componentGrid = [colUnitary("H"), colMeasure0()];
207 assert.throws(
208 () => computeAmpMapForCircuit(qubits, componentGrid),
209 (err) => {
210 assert.equal(err?.name, "UnsupportedStateComputeError");
211 assert.equal(
212 err?.message,
213 "State visualization does not currently support measurement or ResetZ / |0⟩ reset operations.",
214 );
215 return true;
216 },
217 );
218});
219