๐Ÿ Python SDK v1.5.2

๊ฐ€์žฅ ์ธ๊ธฐ์žˆ๋Š” ์–‘์ž ์ปดํ“จํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - NumPy, Pandas, Matplotlib์™€ ์™„๋ฒฝ ํ˜ธํ™˜

๐Ÿงช ๊ณผํ•™ ๊ณ„์‚ฐ

NumPy, SciPy์™€ ๋„ค์ดํ‹ฐ๋ธŒ ํ†ตํ•ฉ

๐Ÿ“Š ๋ฐ์ดํ„ฐ ๋ถ„์„

Pandas, Matplotlib ์™„๋ฒฝ ์ง€์›

๐Ÿค– ๋จธ์‹ ๋Ÿฌ๋‹

PyTorch, TensorFlow ์—ฐ๋™

๐Ÿ““ Jupyter

๋…ธํŠธ๋ถ์—์„œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์‹คํ–‰

์„ค์น˜

pip ์„ค์น˜

Bashpip install cqm-quantum

๊ฐœ๋ฐœ ๋ฒ„์ „ ์„ค์น˜

Bashpip install git+https://github.com/cqmdesk/quantum-sdk-python.git

์˜์กด์„ฑ ํฌํ•จ ์„ค์น˜

Bashpip install cqm-quantum[visualization,ml]

๋น ๋ฅธ ์‹œ์ž‘

๊ธฐ๋ณธ ์˜ˆ์ œ

Pythonfrom cqm import QuantumCircuit, Simulator
import numpy as np

# 2ํ๋น„ํŠธ Bell ์ƒํƒœ ์ƒ์„ฑ
qc = QuantumCircuit(2)
qc.h(0)              # Hadamard gate on qubit 0
qc.cx(0, 1)          # CNOT gate (control: 0, target: 1)
qc.measure_all()

# ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์‹คํ–‰
sim = Simulator()
result = sim.run(qc, shots=1000)

print(result.get_counts())
# Output: {'00': 502, '11': 498}

Jupyter Notebook์—์„œ ์‚ฌ์šฉ

Pythonfrom cqm import QuantumCircuit, Simulator
from cqm.visualization import plot_histogram, plot_bloch_multivector

qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.h(2)
qc.measure_all()

sim = Simulator()
result = sim.run(qc, shots=1024)

# ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”
plot_histogram(result.get_counts())
plot_bloch_multivector(result.get_statevector())

์ฃผ์š” ๊ธฐ๋Šฅ

1. ์–‘์ž ํšŒ๋กœ ์ƒ์„ฑ

Pythonimport numpy as np
from cqm import QuantumCircuit

qc = QuantumCircuit(4)  # 4ํ๋น„ํŠธ ํšŒ๋กœ

# ๊ธฐ๋ณธ ๊ฒŒ์ดํŠธ
qc.h(0)                    # Hadamard
qc.x(1)                    # Pauli-X (NOT)
qc.y(2)                    # Pauli-Y
qc.z(3)                    # Pauli-Z

# ํšŒ์ „ ๊ฒŒ์ดํŠธ
qc.rx(np.pi/4, 0)          # X์ถ• ํšŒ์ „
qc.ry(np.pi/2, 1)          # Y์ถ• ํšŒ์ „
qc.rz(np.pi, 2)            # Z์ถ• ํšŒ์ „

# ์ œ์–ด ๊ฒŒ์ดํŠธ
qc.cx(0, 1)                # CNOT
qc.cz(1, 2)                # Controlled-Z
qc.ccx(0, 1, 2)            # Toffoli (CCX)

# ๊ธฐํƒ€
qc.swap(0, 1)              # SWAP
qc.measure(0, 0)           # ์ธก์ •

2. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์˜ต์…˜

Pythonfrom cqm import Simulator, SimulatorOptions

# ๊ธฐ๋ณธ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
sim = Simulator()
result = sim.run(qc, shots=1000)

# ๊ณ ๊ธ‰ ์˜ต์…˜
sim = Simulator(
    backend='statevector',
    optimization_level=2,
    seed_simulator=42
)

result = sim.run(qc, shots=10000, memory=True)

# ๊ฒฐ๊ณผ ํ™•์ธ
counts = result.get_counts()
statevector = result.get_statevector()
probabilities = result.get_probabilities()
memory = result.get_memory()  # ๊ฐ ์ƒท์˜ ๊ฐœ๋ณ„ ์ธก์ •๊ฐ’

3. NumPy ํ†ตํ•ฉ

Pythonimport numpy as np
from cqm import QuantumCircuit

# NumPy ๋ฐฐ์—ด๋กœ ํšŒ๋กœ ์ œ์–ด
angles = np.linspace(0, 2*np.pi, 10)
results = []

for angle in angles:
    qc = QuantumCircuit(1)
    qc.ry(angle, 0)
    qc.measure_all()
    
    result = sim.run(qc, shots=1000)
    results.append(result.get_counts())

# NumPy ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
prob_0 = np.array([r.get('0', 0)/1000 for r in results])

4. Pandas ๋ฐ์ดํ„ฐ ๋ถ„์„

Pythonimport pandas as pd
from cqm import QuantumCircuit, Simulator

sim = Simulator()
data = []

# ์—ฌ๋Ÿฌ ํšŒ๋กœ ์‹คํ–‰
for n_qubits in range(2, 6):
    qc = QuantumCircuit(n_qubits)
    for i in range(n_qubits):
        qc.h(i)
    qc.measure_all()
    
    result = sim.run(qc, shots=1000)
    
    data.append({
        'qubits': n_qubits,
        'states': len(result.get_counts()),
        'entropy': result.get_entropy()
    })

df = pd.DataFrame(data)
print(df)

API ๋ ˆํผ๋Ÿฐ์Šค

QuantumCircuit

๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช…
h(qubit) qubit: int Hadamard ๊ฒŒ์ดํŠธ ์ ์šฉ
x(qubit) qubit: int Pauli-X ๊ฒŒ์ดํŠธ ์ ์šฉ
cx(control, target) control, target: int CNOT ๊ฒŒ์ดํŠธ ์ ์šฉ
rx(angle, qubit) angle: float, qubit: int X์ถ• ํšŒ์ „ ๊ฒŒ์ดํŠธ
measure(qubit, cbit) qubit, cbit: int ๋‹จ์ผ ํ๋น„ํŠธ ์ธก์ •
measure_all() ์—†์Œ ์ „์ฒด ํ๋น„ํŠธ ์ธก์ •

Simulator

๋ฉ”์„œ๋“œ ๋ฐ˜ํ™˜ ํƒ€์ž… ์„ค๋ช…
run(circuit, shots) Result ํšŒ๋กœ ์‹คํ–‰
run_batch(circuits, shots) List[Result] ์—ฌ๋Ÿฌ ํšŒ๋กœ ์ผ๊ด„ ์‹คํ–‰

Result

๋ฉ”์„œ๋“œ ๋ฐ˜ํ™˜ ํƒ€์ž… ์„ค๋ช…
get_counts() Dict[str, int] ์ธก์ • ๊ฒฐ๊ณผ ์นด์šดํŠธ
get_statevector() np.ndarray ์ƒํƒœ ๋ฒกํ„ฐ
get_probabilities() np.ndarray ํ™•๋ฅ  ๋ถ„ํฌ

๊ณ ๊ธ‰ ์˜ˆ์ œ

์–‘์ž ํ‘ธ๋ฆฌ์— ๋ณ€ํ™˜ (QFT)

Pythonimport numpy as np
from cqm import QuantumCircuit

def qft(circuit, qubits):
    """Quantum Fourier Transform"""
    n = len(qubits)
    
    for i in range(n):
        circuit.h(qubits[i])
        
        for j in range(i + 1, n):
            angle = np.pi / (2 ** (j - i))
            circuit.cp(angle, qubits[j], qubits[i])
    
    # Swap qubits
    for i in range(n // 2):
        circuit.swap(qubits[i], qubits[n - i - 1])

# ์‚ฌ์šฉ ์˜ˆ์ œ
qc = QuantumCircuit(4)
qft(qc, [0, 1, 2, 3])
qc.measure_all()

Grover ์•Œ๊ณ ๋ฆฌ์ฆ˜

Pythonimport numpy as np
from cqm import QuantumCircuit, Simulator

def grover_oracle(circuit, target):
    """Oracle for Grover's algorithm"""
    # target ๋ฌธ์ž์—ด์— ํ•ด๋‹นํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋งˆํ‚น
    for i, bit in enumerate(target):
        if bit == '0':
            circuit.x(i)
    
    circuit.h(len(target) - 1)
    circuit.mcx(list(range(len(target) - 1)), len(target) - 1)
    circuit.h(len(target) - 1)
    
    for i, bit in enumerate(target):
        if bit == '0':
            circuit.x(i)

def grover_diffusion(circuit, n):
    """Diffusion operator"""
    for i in range(n):
        circuit.h(i)
        circuit.x(i)
    
    circuit.h(n - 1)
    circuit.mcx(list(range(n - 1)), n - 1)
    circuit.h(n - 1)
    
    for i in range(n):
        circuit.x(i)
        circuit.h(i)

# 2ํ๋น„ํŠธ Grover ๊ฒ€์ƒ‰
n = 2
target = '11'  # ์ฐพ๊ณ ์ž ํ•˜๋Š” ์ƒํƒœ

qc = QuantumCircuit(n)

# ์ดˆ๊ธฐํ™”
for i in range(n):
    qc.h(i)

# Grover ๋ฐ˜๋ณต (์ตœ์  ํšŸ์ˆ˜)
iterations = int(np.pi / 4 * np.sqrt(2**n))
for _ in range(iterations):
    grover_oracle(qc, target)
    grover_diffusion(qc, n)

qc.measure_all()

sim = Simulator()
result = sim.run(qc, shots=1000)
print(result.get_counts())  # '11'์ด ๋†’์€ ํ™•๋ฅ ๋กœ ๋‚˜ํƒ€๋‚จ

๋ณ€๋ถ„ ์–‘์ž ๊ณ ์œ ๊ฐ’ ํ’€์ด๊ธฐ (VQE)

Pythonimport numpy as np
from cqm import QuantumCircuit, Simulator
from scipy.optimize import minimize

def vqe_circuit(params):
    """Parametrized quantum circuit"""
    qc = QuantumCircuit(2)
    
    qc.ry(params[0], 0)
    qc.ry(params[1], 1)
    qc.cx(0, 1)
    qc.ry(params[2], 0)
    qc.ry(params[3], 1)
    
    return qc

def compute_expectation(params, hamiltonian):
    """Compute expectation value"""
    qc = vqe_circuit(params)
    
    sim = Simulator(backend='statevector')
    result = sim.run(qc, shots=1)
    
    statevector = result.get_statevector()
    expectation = np.real(
        np.conj(statevector) @ hamiltonian @ statevector
    )
    
    return expectation

# ํ•ด๋ฐ€ํ† ๋‹ˆ์•ˆ ์ •์˜ (์˜ˆ: H2 ๋ถ„์ž)
hamiltonian = np.array([
    [-1.0523, 0, 0, 0.3979],
    [0, -0.4804, 0.3979, 0],
    [0, 0.3979, -0.4804, 0],
    [0.3979, 0, 0, -1.0523]
])

# ์ตœ์ ํ™”
initial_params = np.random.rand(4) * 2 * np.pi
result = minimize(
    compute_expectation, 
    initial_params,
    args=(hamiltonian,),
    method='COBYLA'
)

print(f"Ground state energy: {result.fun}")
print(f"Optimal parameters: {result.x}")

์–‘์ž ๊ธฐ๊ณ„ํ•™์Šต

Pythonimport numpy as np
from cqm import QuantumCircuit, Simulator
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

class QuantumClassifier:
    def __init__(self, n_qubits=4):
        self.n_qubits = n_qubits
        self.params = np.random.rand(n_qubits * 2) * 2 * np.pi
        self.sim = Simulator()
    
    def feature_map(self, x):
        """Encode classical data into quantum state"""
        qc = QuantumCircuit(self.n_qubits)
        for i in range(self.n_qubits):
            qc.ry(x[i % len(x)] * np.pi, i)
        return qc
    
    def variational_circuit(self, qc):
        """Variational layer"""
        for i in range(self.n_qubits):
            qc.ry(self.params[i], i)
        
        for i in range(self.n_qubits - 1):
            qc.cx(i, i + 1)
        
        for i in range(self.n_qubits):
            qc.ry(self.params[self.n_qubits + i], i)
    
    def predict(self, X):
        predictions = []
        
        for x in X:
            qc = self.feature_map(x)
            self.variational_circuit(qc)
            qc.measure_all()
            
            result = self.sim.run(qc, shots=100)
            counts = result.get_counts()
            
            # ์ธก์ • ๊ฒฐ๊ณผ์˜ ํŒจ๋ฆฌํ‹ฐ๋กœ ๋ถ„๋ฅ˜
            prob_0 = sum(v for k, v in counts.items() if k.count('0') > self.n_qubits/2)
            predictions.append(1 if prob_0 > 50 else 0)
        
        return np.array(predictions)

# ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ๋ฐ ํ•™์Šต
X, y = make_classification(n_samples=100, n_features=4, n_classes=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

qclf = QuantumClassifier(n_qubits=4)
y_pred = qclf.predict(X_test)

accuracy = np.mean(y_pred == y_test)
print(f"Accuracy: {accuracy:.2%}")
๐Ÿ’ก Pro Tip: %matplotlib inline์„ Jupyter์—์„œ ์‹คํ–‰ํ•˜๋ฉด ํ”Œ๋กฏ์ด ์ž๋™์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
โš ๏ธ ์ฃผ์˜: ๋Œ€๊ทœ๋ชจ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. 25ํ๋น„ํŠธ ์ด์ƒ์€ HPC ํ™˜๊ฒฝ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐํ™”

Pythonfrom cqm.visualization import (
    plot_histogram,
    plot_bloch_multivector,
    plot_state_city,
    circuit_drawer
)

# ํžˆ์Šคํ† ๊ทธ๋žจ
plot_histogram(result.get_counts())

# ๋ธ”๋กœํ ๊ตฌ
plot_bloch_multivector(result.get_statevector())

# State city
plot_state_city(result.get_statevector())

# ํšŒ๋กœ ๋‹ค์ด์–ด๊ทธ๋žจ
circuit_drawer(qc, output='mpl')

๋ฌธ์˜ ๋ฐ ์ง€์›