gpt-oss-20b / __init,__.py
Ananthusajeev190's picture
Upload 312 files
d2e0b37 verified
raw
history blame
4.34 kB
# artificial_quotom_chip_toy.py
# A tiny educational quantum "chip" simulator (statevector) — for learning.
import numpy as np
from typing import List, Tuple
SQRT2_INV = 1 / np.sqrt(2)
class ArtificialQuotomChip:
def __init__(self, n_qubits: int):
self.n = n_qubits
self.state = np.zeros(2**n, dtype=complex)
self.state[0] = 1.0 # |00...0>
def _apply_unitary(self, U: np.ndarray, targets: List[int]):
"""Apply an n-qubit unitary on specified target qubits (by building full matrix)."""
# Build full operator by tensoring identities and U at target positions.
# Note: simple but exponential; fine for small n (<= 16 practically).
ops = []
tset = set(targets)
k = 0
for i in range(self.n):
if i in tset:
ops.append(U if len(targets) == 1 else None) # We'll handle multi-target separately
k += 1
else:
ops.append(np.eye(2, dtype=complex))
# If single-target, tensor directly
if len(targets) == 1:
full = ops[0]
for op in ops[1:]:
if op is None:
# should not happen here
op = np.eye(2, dtype=complex)
full = np.kron(full, op)
else:
# For CNOT (2-qubit) quick path: generate full operator by acting on basis
full = np.eye(2**self.n, dtype=complex)
# We'll implement CNOT by permuting basis amplitudes (more efficient than building big matrices)
return self._apply_custom_on_basis(targets, self._cnot_action)
self.state = full @ self.state
def _apply_custom_on_basis(self, targets: List[int], action_fn):
"""Apply a basis-level action function that maps basis index -> new basis index/value."""
new = np.zeros_like(self.state)
for idx, amp in enumerate(self.state):
if amp == 0:
continue
new_idx, scale = action_fn(idx, targets)
new[new_idx] += amp * scale
self.state = new
def _cnot_action(self, idx: int, targets: List[int]) -> Tuple[int, complex]:
# targets: [control, target] (qubit indices with 0 = MSB if we constructed that way)
control, target = targets
# Convert index to bitstring array (LSB = last qubit). We'll treat qubit-0 as leftmost (MSB)
bits = [(idx >> (self.n - 1 - i)) & 1 for i in range(self.n)]
if bits[control] == 1:
bits[target] ^= 1
# convert bits back to index
new_idx = 0
for b in bits:
new_idx = (new_idx << 1) | b
return new_idx, 1.0
# gates
def H(self, q: int):
H = np.array([[SQRT2_INV, SQRT2_INV], [SQRT2_INV, -SQRT2_INV]], dtype=complex)
self._apply_unitary(H, [q])
def X(self, q: int):
X = np.array([[0,1],[1,0]], dtype=complex)
self._apply_unitary(X, [q])
def CNOT(self, control: int, target: int):
# implement via basis mapping
self._apply_custom_on_basis([control, target], self._cnot_action)
def measure(self, q: int) -> int:
"""Measure qubit q (collapses state). Returns 0/1."""
zero_mask = []
one_mask = []
for basis in range(2**self.n):
# extract bit at position q
b = (basis >> (self.n - 1 - q)) & 1
if b == 0:
zero_mask.append(basis)
else:
one_mask.append(basis)
p0 = np.sum(np.abs(self.state[zero_mask])**2)
if np.random.rand() < p0:
# collapse to 0
self.state[one_mask] = 0
self.state /= np.sqrt(p0) if p0>0 else 1
return 0
else:
p1 = 1 - p0
self.state[zero_mask] = 0
self.state /= np.sqrt(p1) if p1>0 else 1
return 1
def probs(self):
return np.abs(self.state)**2
def statevector(self):
return self.state.copy()
# Example: create Bell pair on 2 qubits
if __name__ == "__main__":
chip = ArtificialQuotomChip(2)
chip.H(0)
chip.CNOT(0,1)
print("Statevector:", chip.statevector())
print("Probs:", chip.probs())
# Measure both
m0 = chip.measure(0)
m1 = chip.measure(1)
print("Measurements:", m0, m1)