Files

543 lines
22 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Numex Quantum Lab — Çekirdek motor testleri.
*
* Bu testler SIMÜLASYONUN GERÇEKTEN ÇALIŞTIĞINI kanıtlar; UI'a bağımlı değildir.
* Kapsam: kompleks aritmetik, matris/tensör işlemleri, tüm kapılar,
* CNOT kontrol-hedef doğruluğu, Bell/GHZ durumları, norm korunumu,
* ölçüm dağılımı, geçersiz qubit kontrolü, kaydet/yükle.
*/
import { describe, it, expect } from 'vitest';
import {
c, add, mul, div, conj, abs, abs2, phase, expI, equals, format,
} from '../src/core/complex.js';
import {
zeros, identity, matMul, matVec, kron, kronAll, dagger, matEquals,
} from '../src/core/matrix.js';
import {
X, Y, Z, H, S, T, CNOT, SWAP, CZ, rx, ry, rz, gateMatrix, gateArity, GATE_REGISTRY,
} from '../src/core/gates.js';
import {
initialState, applySingleQubitGate, applyTwoQubitGate, runCircuit,
normOf, totalProbability, sampleHistogram, basisLabel, makeRng, assertQubitCount,
} from '../src/core/simulator.js';
import {
createCircuit, addGate, removeGate, clearCircuit, circuitDepth, gateCount,
serializeCircuitToString, deserializeCircuit, buildExperiment, EXPERIMENTS,
} from '../src/circuit/circuit.js';
import {
checkBellState, checkGhzState, checkNorm, checkProbabilitySum,
checkMeasurementTotal, checkGateQubits, checkTwoQubitReference,
checkGateUnitarity, checkAllGatesUnitary, entanglementEntropy, validateRun,
} from '../src/analysis/validators.js';
/* ================================================================== */
/* 1–3: Kompleks sayı işlemleri */
/* ================================================================== */
describe('Kompleks sayı işlemleri', () => {
it('1) çarpma ve toplama doğru: (1+2i)(3-1i) = 5+5i', () => {
const r = mul(c(1, 2), c(3, -1));
expect(r.re).toBeCloseTo(5, 12);
expect(r.im).toBeCloseTo(5, 12);
expect(add(c(1, 2), c(3, -1))).toEqual({ re: 4, im: 1 });
});
it('2) bölme doğru: (5+5i)/(1+2i) = 3-1i', () => {
const r = div(c(5, 5), c(1, 2));
expect(r.re).toBeCloseTo(3, 12);
expect(r.im).toBeCloseTo(-1, 12);
});
it('3) modül, eşlenik ve faz: |3+4i| = 5, (1+i)* = 1-i', () => {
expect(abs(c(3, 4))).toBeCloseTo(5, 12);
expect(abs2(c(3, 4))).toBeCloseTo(25, 12);
expect(conj(c(1, 1))).toEqual({ re: 1, im: -1 });
expect(phase(c(0, 1))).toBeCloseTo(Math.PI / 2, 12);
const e = expI(Math.PI);
expect(e.re).toBeCloseTo(-1, 12);
expect(e.im).toBeCloseTo(0, 12);
});
it('3b) sıfıra bölme hata fırlatır (sessiz NaN yok)', () => {
expect(() => div(c(1, 1), c(0, 0))).toThrow(/sıfıra bölme/);
});
});
/* ================================================================== */
/* 4–5: Matris ve tensör işlemleri */
/* ================================================================== */
describe('Matris / tensör işlemleri', () => {
it('4) matris çarpımı ve birim matris: A·I = A', () => {
const A = [[c(1, 1), c(2, 0)], [c(0, -1), c(3, 2)]];
const I2 = identity(2);
expect(matEquals(matMul(A, I2), A)).toBe(true);
});
it('4b) tensör çarpımı boyutu ve değeri doğru: I ⊗ I (2x2) → 4x4', () => {
const K = kron(identity(2), identity(2));
expect(K.length).toBe(4);
expect(K[0].length).toBe(4);
expect(matEquals(K, identity(4))).toBe(true);
const HK = kron(H, identity(2));
expect(HK.length).toBe(4);
});
it('4c) kronAll üç matrisi birleştirir: 2x2 ⊗ 2x2 ⊗ 2x2 = 8x8', () => {
const K = kronAll([identity(2), identity(2), identity(2)]);
expect(K.length).toBe(8);
expect(matEquals(K, identity(8))).toBe(true);
});
it('5) matris-vektör çarpımı: X|0> = |1>', () => {
const v0 = [{ re: 1, im: 0 }, { re: 0, im: 0 }];
const out = matVec(X, v0);
expect(out[0].re).toBeCloseTo(0, 12);
expect(out[1].re).toBeCloseTo(1, 12);
});
it('5b) her kapı üniterdir (U†U = I)', () => {
const r = checkAllGatesUnitary();
expect(r.ok).toBe(true);
expect(r.detay).toMatch(/hepsi üniter/);
});
it('5c) parametreli Rx(π) ≈ -iX', () => {
const r = checkGateUnitarity('rx', { theta: Math.PI });
expect(r.ok).toBe(true);
const M = rx(Math.PI);
expect(M[0][0].re).toBeCloseTo(0, 12);
expect(M[1][0].im).toBeCloseTo(-1, 12);
});
});
/* ================================================================== */
/* 6–10: Kapı davranışları */
/* ================================================================== */
describe('Kuantum kapıları', () => {
it('6) X kapısı: |0> → |1> ve tekrar X → |0>', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'x');
expect(abs2(s[1])).toBeCloseTo(1, 12);
s = applySingleQubitGate(s, 1, 0, 'x');
expect(abs2(s[0])).toBeCloseTo(1, 12);
});
it('7) H kapısı: |0> → eşit süperpozisyon (her biri 0.5)', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'h');
expect(abs2(s[0])).toBeCloseTo(0.5, 12);
expect(abs2(s[1])).toBeCloseTo(0.5, 12);
// genlikler +1/√2 olmalı (faz 0)
expect(s[0].re).toBeCloseTo(1 / Math.SQRT2, 12);
expect(s[1].re).toBeCloseTo(1 / Math.SQRT2, 12);
});
it('8) H·H = I: iki Hadamard |0> durumunu geri getirir', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'h');
s = applySingleQubitGate(s, 1, 0, 'h');
expect(abs2(s[0])).toBeCloseTo(1, 12);
expect(abs2(s[1])).toBeCloseTo(0, 12);
});
it('9) Z kapısı: |1> bileşenine −1 faz yazar, olasılık değişmez', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'x'); // |1>
s = applySingleQubitGate(s, 1, 0, 'z'); // -|1>
expect(s[1].re).toBeCloseTo(-1, 12);
expect(abs2(s[1])).toBeCloseTo(1, 12);
});
it('10) S ve T faz kapıları: doğru açılar (π/2, π/4)', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'x');
s = applySingleQubitGate(s, 1, 0, 's');
expect(phase(s[1])).toBeCloseTo(Math.PI / 2, 12);
let t = initialState(1);
t = applySingleQubitGate(t, 1, 0, 'x');
t = applySingleQubitGate(t, 1, 0, 't');
expect(phase(t[1])).toBeCloseTo(Math.PI / 4, 12);
});
it('10b) Ry(π) |0> → |1>', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'ry', { theta: Math.PI });
expect(abs2(s[1])).toBeCloseTo(1, 12);
});
it('10c) Rz fazı doğru: Rz(π/2) ile |1> fazı π/2 olur', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'x');
s = applySingleQubitGate(s, 1, 0, 'rz', { theta: Math.PI / 2 });
// global faz −π/4, göreli faz π/2 → |amp| = 1 korunur
expect(abs2(s[1])).toBeCloseTo(1, 12);
expect(normOf(s)).toBeCloseTo(1, 12);
});
});
/* ================================================================== */
/* 11–14: İki qubit — CNOT, SWAP, tensör gömme */
/* ================================================================== */
describe('İki qubit kapıları ve dolanıklık', () => {
it('11) CNOT |10> → |11> (kontrol q0=1, hedef q1)', () => {
let s = initialState(2);
s = applySingleQubitGate(s, 2, 0, 'x'); // |10>
expect(basisLabel(2, 2)).toBe('10');
s = applyTwoQubitGate(s, 2, 0, 1, 'cnot', { control: 0 });
expect(abs2(s[3])).toBeCloseTo(1, 12); // |11>
expect(abs2(s[2])).toBeCloseTo(0, 12);
});
it('11b) CNOT kontrol 0 iken hedef değişmez: |00> → |00>', () => {
let s = initialState(2);
s = applyTwoQubitGate(s, 2, 0, 1, 'cnot', { control: 0 });
expect(abs2(s[0])).toBeCloseTo(1, 12);
});
it('12) CNOT ters yön (kontrol q1, hedef q0): |01> → |11>', () => {
let s = initialState(2);
s = applySingleQubitGate(s, 2, 1, 'x'); // |01> (q1 = 1)
expect(abs2(s[1])).toBeCloseTo(1, 12);
s = applyTwoQubitGate(s, 2, 0, 1, 'cnot', { control: 1 });
expect(abs2(s[3])).toBeCloseTo(1, 12); // |11>
});
it('13) SWAP: |01> ↔ |10>', () => {
let s = initialState(2);
s = applySingleQubitGate(s, 2, 0, 'x'); // |10>
s = applyTwoQubitGate(s, 2, 0, 1, 'swap', {});
expect(abs2(s[1])).toBeCloseTo(1, 12); // |01>
});
it('14) Bell state: H+CNOT → yalnızca |00> ve |11>, her biri 0.5', () => {
const c1 = createCircuit(2);
addGate(c1, { type: 'h', qubits: [0] });
addGate(c1, { type: 'cnot', qubits: [0, 1], control: 0 });
const r = runCircuit(c1);
expect(abs2(r.state[0])).toBeCloseTo(0.5, 10);
expect(abs2(r.state[3])).toBeCloseTo(0.5, 10);
expect(abs2(r.state[1])).toBeCloseTo(0, 10);
expect(abs2(r.state[2])).toBeCloseTo(0, 10);
const kontrol = checkBellState(r.state);
expect(kontrol.ok).toBe(true);
});
it('14b) Bell state dolanıktır (qubit entropisi = 1 bit)', () => {
const c1 = buildExperiment('bell');
const r = runCircuit(c1);
const ent = entanglementEntropy(r.state, 2);
expect(ent[0].p1).toBeCloseTo(0.5, 10);
expect(ent[0].entropi).toBeCloseTo(1, 10);
expect(ent[1].entropi).toBeCloseTo(1, 10);
});
});
/* ================================================================== */
/* 15–18: GHZ, norm korunumu, ölçüm dağılımı */
/* ================================================================== */
describe('GHZ, norm ve ölçüm', () => {
it('15) GHZ-3: yalnızca |000> ve |111> (0.5 / 0.5)', () => {
const c1 = buildExperiment('ghz3');
const r = runCircuit(c1);
expect(abs2(r.state[0])).toBeCloseTo(0.5, 10); // |000>
expect(abs2(r.state[7])).toBeCloseTo(0.5, 10); // |111>
const k = checkGhzState(r.state, 3);
expect(k.ok).toBe(true);
// aradaki hiçbir durum genlik taşımamalı
for (const i of [1, 2, 3, 4, 5, 6]) {
expect(abs2(r.state[i])).toBeLessThan(1e-12);
}
});
it('15b) GHZ-4: yalnızca |0000> ve |1111>', () => {
const c1 = buildExperiment('ghz4');
const r = runCircuit(c1);
expect(abs2(r.state[0])).toBeCloseTo(0.5, 10);
expect(abs2(r.state[15])).toBeCloseTo(0.5, 10);
expect(checkGhzState(r.state, 4).ok).toBe(true);
});
it('16) Norm korunumu: HER kapı dizisinden sonra ||ψ|| = 1', () => {
for (const exp of EXPERIMENTS) {
const circ = exp.kur();
const r = runCircuit(circ);
expect(normOf(r.state), `${exp.id} normu`).toBeCloseTo(1, 9);
expect(totalProbability(r.state), `${exp.id} olasılık toplamı`).toBeCloseTo(1, 9);
for (const step of r.steps) {
expect(step.norm, `${exp.id} → ${step.type} sonrası norm`).toBeCloseTo(1, 9);
}
}
});
it('17) Ölçüm dağılımı Bell için ~%50/%50 ve toplam %100', () => {
const c1 = buildExperiment('bell');
const r = runCircuit(c1, { shots: 4000, seed: 7 });
const h = r.histogram;
const toplam = h.counts.reduce((a, b) => a + b, 0);
expect(toplam).toBe(4000);
expect(h.counts[1]).toBe(0);
expect(h.counts[2]).toBe(0);
expect(h.counts[0] / 4000).toBeGreaterThan(0.45);
expect(h.counts[0] / 4000).toBeLessThan(0.55);
expect(h.counts[3] / 4000).toBeGreaterThan(0.45);
expect(h.counts[3] / 4000).toBeLessThan(0.55);
expect(checkMeasurementTotal(h).ok).toBe(true);
});
it('17b) Ölçüm dağılımı GHZ-3 için yalnızca 000 ve 111 üretir', () => {
const c1 = buildExperiment('ghz3');
const r = runCircuit(c1, { shots: 2000, seed: 11 });
const h = r.histogram;
for (const i of [1, 2, 3, 4, 5, 6]) expect(h.counts[i]).toBe(0);
expect(h.counts[0] + h.counts[7]).toBe(2000);
});
it('17c) Deterministik PRNG: aynı seed → aynı histogram', () => {
const c1 = buildExperiment('ghz3');
const a = runCircuit(c1, { shots: 500, seed: 99 });
const b = runCircuit(c1, { shots: 500, seed: 99 });
expect(a.histogram.counts).toEqual(b.histogram.counts);
const rng = makeRng(5);
expect(rng()).toBe(makeRng(5)());
});
it('17d) Ölçüm saf olasılık dağılımından gelir — |1> durumu %100 |1> verir', () => {
const c1 = createCircuit(1);
addGate(c1, { type: 'x', qubits: [0] });
const r = runCircuit(c1, { shots: 300, seed: 3 });
expect(r.histogram.counts[1]).toBe(300);
expect(r.histogram.counts[0]).toBe(0);
});
it('18) Süperpozisyon ölçümü ~%50/%50 (tek qubit)', () => {
const c1 = buildExperiment('superposition');
const r = runCircuit(c1, { shots: 3000, seed: 21 });
const h = r.histogram;
expect(Math.abs(h.counts[0] / 3000 - 0.5)).toBeLessThan(0.05);
expect(Math.abs(h.counts[1] / 3000 - 0.5)).toBeLessThan(0.05);
});
});
/* ================================================================== */
/* 19–22: Hata yönetimi, sınırlar, kaydet/yükle */
/* ================================================================== */
describe('Geçersiz girdi, sınırlar ve kalıcılık', () => {
it('19a) Geçersiz qubit sayısı hata fırlatır (0, 9, 2.5)', () => {
expect(() => assertQubitCount(0)).toThrow(/Geçersiz qubit sayısı/);
expect(() => assertQubitCount(9)).toThrow(/Geçersiz qubit sayısı/);
expect(() => assertQubitCount(2.5)).toThrow(/Geçersiz qubit sayısı/);
expect(() => assertQubitCount(8)).not.toThrow();
});
it('19b) Geçersiz qubit indeksi hata fırlatır (devre sınırı dışı)', () => {
const c1 = createCircuit(2);
expect(() => addGate(c1, { type: 'h', qubits: [2] })).toThrow(/Geçersiz qubit indeksi/);
expect(() => addGate(c1, { type: 'x', qubits: [-1] })).toThrow(/Geçersiz qubit indeksi/);
});
it('19c) CNOT aynı qubit üzerine eklenemez', () => {
const c1 = createCircuit(2);
expect(() => addGate(c1, { type: 'cnot', qubits: [1, 1], control: 1 })).toThrow(/aynı qubit/);
});
it('19d) Bilinmeyen kapı türü hata fırlatır', () => {
const c1 = createCircuit(2);
expect(() => addGate(c1, { type: 'fredkin', qubits: [0, 1] })).toThrow(/Bilinmeyen kapı türü/);
expect(() => gateArity('qft')).toThrow(/Bilinmeyen kapı türü/);
});
it('19e) Sütun çakışması hata fırlatır (aynı qubit iki kez)', () => {
const c1 = createCircuit(2);
addGate(c1, { type: 'h', qubits: [0] });
expect(() => addGate(c1, { type: 'x', qubits: [0], columnIndex: 0 })).toThrow(/çakışması/);
});
it('19f) Doğrulama katmanı geçersiz qubit ve kontrol rolünü yakalar', () => {
const bozuk = { nQubits: 2, columns: [] };
const c1 = createCircuit(2);
addGate(c1, { type: 'h', qubits: [0] });
// elle bozulmuş kapı simülasyonu
bozuk.columns.push({ gates: [{ id: 'x1', type: 'h', qubits: [5], params: {} }] });
const r = checkGateQubits(bozuk);
expect(r.ok).toBe(false);
expect(r.detay).toMatch(/Geçersiz kapılar/);
const kontrolsuz = { nQubits: 2, columns: [{ gates: [{ id: 'g', type: 'cnot', qubits: [0, 1], params: {}, control: 7 }] }] };
expect(checkTwoQubitReference(kontrolsuz).ok).toBe(false);
expect(checkTwoQubitReference(c1).ok).toBe(true);
});
it('20) Devre kaydet → yükle: aynı durum vektörünü üretir (round-trip)', () => {
const ozgun = buildExperiment('ghz3');
const json = serializeCircuitToString(ozgun);
expect(typeof json).toBe('string');
const parsed = JSON.parse(json);
expect(parsed.format).toBe('numex-quantum-circuit');
expect(parsed.nQubits).toBe(3);
expect(parsed.gateCount).toBe(3);
const yuklenen = deserializeCircuit(json);
expect(yuklenen.nQubits).toBe(3);
expect(gateCount(yuklenen)).toBe(gateCount(ozgun));
expect(circuitDepth(yuklenen)).toBe(circuitDepth(ozgun));
const a = runCircuit(ozgun);
const b = runCircuit(yuklenen);
for (let i = 0; i < a.state.length; i++) {
expect(b.state[i].re).toBeCloseTo(a.state[i].re, 12);
expect(b.state[i].im).toBeCloseTo(a.state[i].im, 12);
}
});
it('20b) Bozuk JSON yükleme sessizce geçmez — hata fırlatır', () => {
expect(() => deserializeCircuit('{ bozuk json')).toThrow();
expect(() => deserializeCircuit({ nQubits: 3 })).not.toThrow();
expect(() => deserializeCircuit({ nQubits: 0 })).toThrow(/Geçersiz qubit sayısı/);
expect(() => deserializeCircuit({
nQubits: 2,
columns: [{ gates: [{ type: 'bilinmeyen', qubits: [0] }] }],
})).toThrow(/Bilinmeyen kapı türü/);
expect(() => deserializeCircuit({
nQubits: 2,
columns: [{ gates: [{ type: 'cnot', qubits: [0] }] }],
})).toThrow(/qubit listesi geçersiz/);
});
it('20c) Kontrol qubit farklı olan CNOT kaydedilip doğru yüklenir', () => {
const c1 = createCircuit(2);
addGate(c1, { type: 'x', qubits: [1] });
addGate(c1, { type: 'cnot', qubits: [0, 1], control: 1 });
const json = serializeCircuitToString(c1);
const yuklenen = deserializeCircuit(json);
const g = yuklenen.columns.flatMap((c) => c.gates).find((x) => x.type === 'cnot');
expect(g.control).toBe(1);
const r = runCircuit(yuklenen);
expect(abs2(r.state[3])).toBeCloseTo(1, 12); // |01> → |11>
});
it('21) Kapı ekleme / silme / temizleme devreyi doğru yönetir', () => {
const c1 = createCircuit(3);
const g1 = addGate(c1, { type: 'h', qubits: [0] });
addGate(c1, { type: 'x', qubits: [1] });
expect(gateCount(c1)).toBe(2);
// KRONOLOJİ KURALI: sıralı eklenen kapılar sıralı sütunlara gider
// (farklı qubit'te olsalar bile zaman sırası korunur — GHZ'nin doğruluğu buna bağlı).
expect(circuitDepth(c1)).toBe(2);
addGate(c1, { type: 'x', qubits: [0] });
expect(circuitDepth(c1)).toBe(3);
// Aynı sütuna açıkça ekleme (çakışmayan qubit) derinliği artırmaz
const c2 = createCircuit(3);
addGate(c2, { type: 'h', qubits: [0], columnIndex: 0 });
addGate(c2, { type: 'x', qubits: [2], columnIndex: 0 });
expect(circuitDepth(c2)).toBe(1);
expect(gateCount(c2)).toBe(2);
expect(removeGate(c1, g1.id)).toBe(true);
expect(gateCount(c1)).toBe(2);
expect(removeGate(c1, 'olmayan_id')).toBe(false);
clearCircuit(c1);
expect(gateCount(c1)).toBe(0);
expect(circuitDepth(c1)).toBe(0);
const r = runCircuit(c1);
expect(abs2(r.state[0])).toBeCloseTo(1, 12); // boş devre → |000>
});
it('21c) Kronoloji korunur: H(q0) → CNOT(q0,q1) → CNOT(q1,q2) doğru sırada koşar', () => {
const c1 = createCircuit(3);
addGate(c1, { type: 'h', qubits: [0] });
addGate(c1, { type: 'cnot', qubits: [0, 1], control: 0 });
addGate(c1, { type: 'cnot', qubits: [1, 2], control: 1 });
// Sütun sırası, ekleme sırasıyla birebir aynı olmalı
const sirali = c1.columns.flatMap((c) => c.gates).map((g) => g.type);
expect(sirali).toEqual(['h', 'cnot', 'cnot']);
const kontrolSirasi = c1.columns.flatMap((c) => c.gates).filter((g) => g.type === 'cnot').map((g) => g.control);
expect(kontrolSirasi).toEqual([0, 1]);
// Ve gerçekten GHZ üretir
const r = runCircuit(c1);
expect(checkGhzState(r.state, 3).ok).toBe(true);
});
it('21b) Deney kütüphanesi 7 hazır deney sunar ve hepsi çalışır', () => {
expect(EXPERIMENTS.length).toBeGreaterThanOrEqual(7);
const ids = EXPERIMENTS.map((e) => e.id);
expect(ids).toContain('bell');
expect(ids).toContain('ghz3');
expect(ids).toContain('ghz4');
expect(ids).toContain('teleportation');
expect(ids).toContain('superposition');
expect(ids).toContain('hadamard-measurement');
for (const e of EXPERIMENTS) {
const r = runCircuit(e.kur());
expect(normOf(r.state), `${e.id}`).toBeCloseTo(1, 9);
}
});
it('22) Hadamard + ölçüm deneyi %100 |0> verir (H² = I)', () => {
const r = runCircuit(buildExperiment('hadamard-measurement'), { shots: 500, seed: 1 });
expect(r.histogram.counts[0]).toBe(500);
expect(checkProbabilitySum(r).ok).toBe(true);
expect(checkNorm(r).ok).toBe(true);
});
it('22b) validateRun tam rapor üretir ve temiz devrede GEÇER', () => {
const c1 = buildExperiment('bell');
const r = runCircuit(c1, { shots: 200, seed: 2 });
const rapor = validateRun(r, c1);
expect(rapor.checks.length).toBeGreaterThanOrEqual(6);
expect(rapor.ok).toBe(true);
for (const chk of rapor.checks) {
expect(chk.detay.length).toBeGreaterThan(0);
expect(typeof chk.ad).toBe('string');
}
});
it('22c) 8 qubit sınırında simülasyon çalışır (256 genlik)', () => {
const c1 = createCircuit(8);
addGate(c1, { type: 'h', qubits: [0] });
for (let q = 0; q < 7; q++) addGate(c1, { type: 'cnot', qubits: [q, q + 1], control: q });
const r = runCircuit(c1, { shots: 100, seed: 4 });
expect(r.state.length).toBe(256);
expect(normOf(r.state)).toBeCloseTo(1, 9);
expect(checkGhzState(r.state, 8).ok).toBe(true);
expect(r.histogram.counts[0] + r.histogram.counts[255]).toBe(100);
});
});
/* ================================================================== */
/* 23–24: Biçimlendirme ve yardımcılar */
/* ================================================================== */
describe('Yardımcı fonksiyonlar', () => {
it('23) basisLabel doğru üretir (5, 3 qubit → 101)', () => {
expect(basisLabel(5, 3)).toBe('101');
expect(basisLabel(0, 4)).toBe('0000');
expect(basisLabel(15, 4)).toBe('1111');
});
it('24) format küçük gürültüyü sıfıra çeker ve okunabilir yazar', () => {
expect(format(c(0.70710678, 0), 4)).toBe('0.7071+0.0000i');
expect(format(c(0.5, -0.866), 4)).toBe('0.5000-0.8660i');
expect(equals(c(1, 0), c(1, 0))).toBe(true);
expect(equals(c(1, 0), c(1, 1e-12))).toBe(true);
});
it('24b) sampleHistogram olasılıkları doğru raporlar', () => {
let s = initialState(1);
s = applySingleQubitGate(s, 1, 0, 'h');
const h = sampleHistogram(s, 1, 100, 5);
expect(h.probabilities[0]).toBeCloseTo(0.5, 12);
expect(h.probabilities[1]).toBeCloseTo(0.5, 12);
expect(h.labels).toEqual(['0', '1']);
});
});