Skip to content

Commit 1d2d838

Browse files
committed
update
1 parent 7bc9c9b commit 1d2d838

File tree

3 files changed

+711
-474
lines changed

3 files changed

+711
-474
lines changed

doc/Programs/OOcodes/codes.do.txt

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,3 +1812,255 @@ if __name__ == "__main__":
18121812

18131813
!ec
18141814

1815+
1816+
!split
1817+
===== More codes =====
1818+
1819+
!bc pycod
1820+
import numpy as np
1821+
1822+
# One-qubit gates
1823+
def I(): return np.eye(2)
1824+
def X(): return np.array([[0,1],[1,0]])
1825+
def Y(): return np.array([[0,-1j],[1j,0]])
1826+
def Z(): return np.array([[1,0],[0,-1]])
1827+
def H(): return (1/np.sqrt(2))*np.array([[1,1],[1,-1]])
1828+
def S(): return np.array([[1,0],[0,1j]])
1829+
def T(): return np.array([[1,0],[0,np.exp(1j*np.pi/4)]])
1830+
1831+
def Rx(theta):
1832+
return np.array([
1833+
[np.cos(theta/2), -1j*np.sin(theta/2)],
1834+
[-1j*np.sin(theta/2), np.cos(theta/2)]
1835+
])
1836+
1837+
def Ry(theta):
1838+
return np.array([
1839+
[np.cos(theta/2), -np.sin(theta/2)],
1840+
[np.sin(theta/2), np.cos(theta/2)]
1841+
])
1842+
1843+
def Rz(theta):
1844+
return np.array([
1845+
[np.exp(-1j*theta/2), 0],
1846+
[0, np.exp(1j*theta/2)]
1847+
])
1848+
1849+
# Two-qubit gates
1850+
def CNOT():
1851+
return np.array([
1852+
[1,0,0,0],
1853+
[0,1,0,0],
1854+
[0,0,0,1],
1855+
[0,0,1,0]
1856+
])
1857+
1858+
def CZ():
1859+
return np.array([
1860+
[1,0,0,0],
1861+
[0,1,0,0],
1862+
[0,0,1,0],
1863+
[0,0,0,-1]
1864+
])
1865+
1866+
def SWAP():
1867+
return np.array([
1868+
[1,0,0,0],
1869+
[0,0,1,0],
1870+
[0,1,0,0],
1871+
[0,0,0,1]
1872+
])
1873+
1874+
1875+
!ec
1876+
1877+
1878+
!split
1879+
===== Circuit =====
1880+
!bc pycod
1881+
import random
1882+
from collections import Counter
1883+
1884+
class Gate:
1885+
def __init__(self, matrix, targets):
1886+
self.matrix = matrix
1887+
self.targets = targets
1888+
1889+
class Circuit:
1890+
def __init__(self, num_qubits):
1891+
self.n = num_qubits
1892+
self.reset()
1893+
1894+
def reset(self):
1895+
self.state = np.zeros(2**self.n, dtype=np.complex128)
1896+
self.state[0] = 1.0
1897+
self.gates = []
1898+
1899+
def add_gate(self, gate):
1900+
self.gates.append(gate)
1901+
1902+
def run(self):
1903+
for gate in self.gates:
1904+
self.apply_gate(gate)
1905+
1906+
def apply_gate(self, gate):
1907+
full_U = self.expand_gate(gate)
1908+
self.state = full_U @ self.state
1909+
1910+
def expand_gate(self, gate):
1911+
if len(gate.targets) == 1:
1912+
return self.tensor_product_gate(gate)
1913+
elif len(gate.targets) == 2:
1914+
return self.tensor_product_two_qubit_gate(gate)
1915+
else:
1916+
raise ValueError("Only 1 or 2 qubit gates supported.")
1917+
1918+
def tensor_product_gate(self, gate):
1919+
ops = [np.eye(2) for _ in range(self.n)]
1920+
ops[gate.targets[0]] = gate.matrix
1921+
U = ops[0]
1922+
for op in ops[1:]:
1923+
U = np.kron(U, op)
1924+
return U
1925+
1926+
def tensor_product_two_qubit_gate(self, gate):
1927+
ops = [np.eye(2) for _ in range(self.n)]
1928+
idx = sorted(gate.targets)
1929+
# naive expansion for generality:
1930+
full_U = np.eye(1)
1931+
for i in range(self.n):
1932+
if i in gate.targets:
1933+
continue
1934+
full_U = np.kron(full_U, np.eye(2))
1935+
full_U = np.kron(gate.matrix, full_U)
1936+
return full_U # for small N this works; we can optimize later
1937+
1938+
def get_statevector(self):
1939+
return self.state
1940+
1941+
def get_probabilities(self):
1942+
return np.abs(self.state)**2
1943+
1944+
def measure(self, shots=1024):
1945+
probs = self.get_probabilities()
1946+
basis_states = [format(i, f'0{self.n}b') for i in range(2**self.n)]
1947+
samples = random.choices(basis_states, weights=probs, k=shots)
1948+
return dict(Counter(samples))
1949+
1950+
1951+
!ec
1952+
1953+
!split
1954+
===== Noise model =====
1955+
!bc pycod
1956+
1957+
import numpy as np
1958+
import random
1959+
1960+
def bit_flip(state, p):
1961+
noisy_state = state.copy()
1962+
for i in range(len(state)):
1963+
if random.random() < p:
1964+
flipped = i ^ 1 # flips qubit 0
1965+
noisy_state[flipped] += state[i]
1966+
noisy_state[i] = 0
1967+
return noisy_state / np.linalg.norm(noisy_state)
1968+
1969+
def depolarizing(state, p):
1970+
d = len(state)
1971+
noisy_state = (1-p) * state + p/d * np.ones(d)
1972+
return noisy_state / np.linalg.norm(noisy_state)
1973+
1974+
def bit_flip(state, p):
1975+
noisy_state = state.copy()
1976+
for i in range(len(state)):
1977+
if random.random() < p:
1978+
flipped = i ^ 1 # flips qubit 0
1979+
noisy_state[flipped] += state[i]
1980+
noisy_state[i] = 0
1981+
return noisy_state / np.linalg.norm(noisy_state)
1982+
1983+
def depolarizing(state, p):
1984+
d = len(state)
1985+
noisy_state = (1-p) * state + p/d * np.ones(d)
1986+
return noisy_state / np.linalg.norm(noisy_state)
1987+
1988+
1989+
!ec
1990+
1991+
!split
1992+
===== Bell states =====
1993+
!bc pycod
1994+
from core.circuit import Circuit, Gate
1995+
from core import gates
1996+
1997+
def bell_state(label="Phi+"):
1998+
c = Circuit(2)
1999+
c.add_gate(Gate(gates.H(), [0]))
2000+
c.add_gate(Gate(gates.CNOT(), [0,1]))
2001+
2002+
if label == "Phi+":
2003+
pass
2004+
elif label == "Phi-":
2005+
c.add_gate(Gate(gates.Z(), [0]))
2006+
elif label == "Psi+":
2007+
c.add_gate(Gate(gates.X(), [1]))
2008+
elif label == "Psi-":
2009+
c.add_gate(Gate(gates.X(), [1]))
2010+
c.add_gate(Gate(gates.Z(), [0]))
2011+
else:
2012+
raise ValueError("Unknown Bell state label")
2013+
2014+
c.run()
2015+
# Assuming the Circuit class has a measure method for simulation
2016+
# If not, this line will need to be adjusted based on how measurement is handled
2017+
return c
2018+
2019+
!ec
2020+
2021+
!split
2022+
===== Example =====
2023+
!bc pycod
2024+
import matplotlib.pyplot as plt
2025+
import numpy as np # Add numpy import
2026+
2027+
# Assuming Circuit and Gate are available in the environment from previous cell execution
2028+
# If not, you might need to re-import them here or ensure the 'core' module is structured correctly.
2029+
# For now, let's assume they are available after running the previous cell.
2030+
2031+
labels = ["Phi+", "Phi-", "Psi+", "Psi-"]
2032+
shots = 1000
2033+
2034+
for label in labels:
2035+
print(f"\nBell state {label}")
2036+
c = bell_state(label)
2037+
probs = c.get_probabilities()
2038+
print("Statevector probabilities:", probs)
2039+
# The Circuit class defined earlier does NOT have a 'measure' method.
2040+
# You need to implement a simulation of measurement based on probabilities.
2041+
# Here's a possible implementation:
2042+
counts = {}
2043+
statevector = c.get_statevector()
2044+
num_qubits = int(np.log2(len(statevector))) # infer number of qubits
2045+
basis_states = [bin(i)[2:].zfill(num_qubits) for i in range(len(statevector))]
2046+
2047+
# Simulate shots based on probabilities
2048+
measured_indices = np.random.choice(len(statevector), size=shots, p=probs)
2049+
for idx in measured_indices:
2050+
basis_state_str = basis_states[idx]
2051+
counts[basis_state_str] = counts.get(basis_state_str, 0) + 1
2052+
2053+
print("Measurement counts:", counts)
2054+
plt.bar(counts.keys(), counts.values())
2055+
plt.title(f"Bell state {label}")
2056+
plt.show()
2057+
2058+
!ec
2059+
2060+
2061+
2062+
2063+
2064+
2065+
2066+

0 commit comments

Comments
 (0)