Advanced Examples
Advanced examples demonstrating QPyth's capabilities.
Custom VQE Implementation
Custom Ansatz
from qiskit import QuantumCircuit, ParameterVector
from qiskit_algorithms.optimizers import SPSA
from qiskit_aer import AerSimulator
import numpy as np
def custom_ansatz(num_qubits, depth):
"""Create custom parameterized ansatz."""
qc = QuantumCircuit(num_qubits)
params = ParameterVector('θ', num_qubits * depth)
for d in range(depth):
# Rotation layer
for i in range(num_qubits):
qc.ry(params[d * num_qubits + i], i)
# Entanglement layer
for i in range(num_qubits - 1):
qc.cx(i, i + 1)
return qc
# Create ansatz
ansatz = custom_ansatz(num_qubits=2, depth=3)
print(ansatz)
Custom Optimizer
from qiskit_algorithms.optimizers import SPSA, COBYLA, SLSQP
from qiskit_algorithms import VQE
from qiskit.primitives import Estimator
# Define cost function
def cost_function(params):
# Your cost function here
return np.sum(params ** 2)
# Use SPSA optimizer (robust for noisy environments)
optimizer = SPSA(maxiter=100)
# Use COBYLA optimizer
optimizer = COBYLA(maxiter=100)
# Use SLSQP optimizer
optimizer = SLSQP(maxiter=100)
# Optimize
initial_params = np.random.rand(10)
result = optimizer.minimize(cost_function, x0=initial_params)
print(f"Optimized parameters: {result.x}")
print(f"Minimum value: {result.fun}")
Multi-Molecule VQE
from quantumpytho.modules.vqe_molecules import list_molecules, get_molecule
from quantumpytho.modules.vqe_core import run_vqe_molecule
# Get available molecules
molecules = list_molecules()
print(f"Available molecules: {molecules}")
# Run VQE for each molecule
results = {}
for mol_name in molecules:
print(f"\nRunning VQE for {mol_name}...")
result = run_vqe_molecule(mol_name, max_iters=50)
results[mol_name] = result
print(f"Final energy: {result['final_energy']:.6f} Hartree")
Advanced Noise Modeling
Custom Noise Model
from qiskit_aer.noise import NoiseModel, errors
from qiskit_aer import AerSimulator
# Create noise model
noise_model = NoiseModel()
# Add depolarizing error to single-qubit gates
error_1q = errors.depolarizing_error(0.001, 1)
for gate in ['h', 'x', 'y', 'z', 'rx', 'ry', 'rz']:
noise_model.add_all_qubit_quantum_error(error_1q, gate)
# Add depolarizing error to two-qubit gates
error_2q = errors.depolarizing_error(0.01, 2)
for gate in ['cx', 'cz']:
noise_model.add_all_qubit_quantum_error(error_2q, gate)
# Add readout error
readout_error = errors.readout_error([[0.99, 0.01], [0.02, 0.98]])
noise_model.add_all_qubit_readout_error(readout_error)
# Use with simulator
simulator = AerSimulator(noise_model=noise_model)
Thermal Relaxation Error
from qiskit_aer.noise import NoiseModel, errors
import numpy as np
# Create noise model with thermal relaxation
noise_model = NoiseModel()
# T1 and T2 times (in microseconds)
t1 = 100.0
t2 = 80.0
gate_time = 0.1 # Gate time in microseconds
# Calculate thermal relaxation error
# Error probability = 1 - exp(-gate_time/T1)
p_reset = 1 - np.exp(-gate_time / t1)
# Add thermal relaxation error
thermal_error = errors.thermal_relaxation_error(t1, t2, gate_time)
noise_model.add_all_qubit_quantum_error(thermal_error, ['h', 'x', 'y', 'z'])
# Use with simulator
from qiskit_aer import AerSimulator
simulator = AerSimulator(noise_model=noise_model)
Correlated Noise
from qiskit_aer.noise import NoiseModel, errors
# Create noise model with correlated errors
noise_model = NoiseModel()
# Create correlated readout error
# Probability of measuring 0 when actual is 0: 0.99
# Probability of measuring 1 when actual is 0: 0.01
# Probability of measuring 0 when actual is 1: 0.02
# Probability of measuring 1 when actual is 1: 0.98
correlated_readout = errors.readout_error(
[[0.99, 0.01], [0.02, 0.98]]
)
noise_model.add_all_qubit_readout_error(correlated_readout)
# Use with simulator
from qiskit_aer import AerSimulator
simulator = AerSimulator(noise_model=noise_model)
Error Mitigation
Measurement Error Mitigation
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt
# Create circuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
# Run without mitigation
simulator = AerSimulator()
result_no_mitigation = simulator.run(qc, shots=1024).result()
counts_no_mitigation = result_no_mitigation.get_counts()
# Run with measurement error mitigation
simulator_mitigated = AerSimulator(
mitigation_config={"measure_mitigation": True}
)
result_mitigated = simulator_mitigated.run(qc, shots=1024).result()
counts_mitigated = result_mitigated.get_counts()
# Compare results
print("Without mitigation:", counts_no_mitigation)
print("With mitigation:", counts_mitigated)
# Plot comparison
plot_histogram([counts_no_mitigation, counts_mitigated],
legend=['No Mitigation', 'With Mitigation'])
plt.show()
Zero Noise Extrapolation
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
import numpy as np
# Create circuit
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
# Run at different noise levels
noise_factors = [1.0, 2.0, 3.0]
results = []
for factor in noise_factors:
# Scale noise
simulator = AerSimulator(
noise_model=noise_model,
noise_scale_factor=factor
)
result = simulator.run(qc, shots=1024).result()
counts = result.get_counts()
results.append(counts)
# Extrapolate to zero noise
# (simplified example)
# In practice, use more sophisticated extrapolation methods
print("Results at different noise levels:")
for i, counts in enumerate(results):
print(f"Noise factor {noise_factors[i]}: {counts}")
Advanced QEC
Concatenated Codes
from qiskit import QuantumCircuit
def concatenate_shor_code(logical_qubit):
"""Concatenate Shor's code with itself."""
# Outer encoding: 1 logical -> 9 physical
outer_qubits = list(range(9))
# Inner encoding: each of 9 -> 9 more
# Total: 81 physical qubits
inner_qubits = []
for i in range(9):
start = i * 9
inner_qubits.append(list(range(start, start + 9)))
# Create circuit
qc = QuantumCircuit(81)
# Outer encoding
# ... (encoding circuit)
# Inner encoding for each block
for block in inner_qubits:
# ... (encoding circuit for each block)
return qc
# Create concatenated code
qc = concatenate_shor_code(0)
print(f"Concatenated code uses {qc.num_qubits} qubits")
Fault-Tolerant Gates
from qiskit import QuantumCircuit
def transversal_cnot(control, target):
"""Apply transversal CNOT for Steane's code."""
qc = QuantumCircuit(14) # 7 qubits each
# Apply CNOT transversally
for i in range(7):
qc.cx(control[i], target[i])
return qc
# Create transversal CNOT
control = list(range(7))
target = list(range(7, 14))
qc = transversal_cnot(control, target)
print(qc)
Bond Distance Scanning
H2 Bond Distance Scan
from quantumpytho.modules.vqe_utils import scan_h2_bond_distances
# Scan bond distances
result = scan_h2_bond_distances(
distances=[0.5, 0.6, 0.735, 0.8, 0.9, 1.0],
max_iters=50
)
print(f"Equilibrium distance: {result['equilibrium_distance']:.3f} Å")
print(f"Minimum energy: {result['min_energy']:.6f} Hartree")
# Plot energy curve
import matplotlib.pyplot as plt
plt.plot(result['distances'], result['energies'], 'o-')
plt.xlabel('Bond Distance (Å)')
plt.ylabel('Energy (Hartree)')
plt.title('H2 Energy vs Bond Distance')
plt.grid(True)
plt.show()
Custom Molecule Scan
from quantumpytho.modules.vqe_molecules import scan_bond_distance
# Scan LiH bond distance
result = scan_bond_distance(
name="LiH",
distances=[1.4, 1.5, 1.595, 1.7, 1.8],
max_iters=50
)
print(f"Equilibrium distance: {result['equilibrium_distance']:.3f} Å")
print(f"Minimum energy: {result['min_energy']:.6f} Hartree")
Hardware Integration
Backend Selection
from quantumpytho.modules.hardware_ibm import IBMHardwareEngine
# Connect to IBM Quantum
engine = IBMHardwareEngine()
engine.connect()
# List all backends
backends = engine.list_backends()
print("Available backends:")
for backend in backends:
print(f" {backend['name']}: {backend['num_qubits']} qubits")
# Select least busy backend with at least 5 qubits
selected = engine.select_backend(min_qubits=5, least_busy=True)
print(f"\nSelected backend: {selected}")
# Get backend info
info = engine.get_backend_info(selected)
print(f"Queue: {info['pending_jobs']} jobs")
print(f"Operations: {info['operations']}")
Job Monitoring
from qiskit_ibm_runtime import QiskitRuntimeService
import time
# Connect to service
service = QiskitRuntimeService()
# Get job
job = service.job("your-job-id")
# Monitor job status
while job.status() not in ['DONE', 'CANCELLED', 'ERROR']:
print(f"Status: {job.status()}")
time.sleep(10)
# Get results
result = job.result()
print(f"Job completed: {job.status()}")
Performance Optimization
Circuit Optimization
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
# Create circuit
qc = QuantumCircuit(5)
qc.h(0)
for i in range(4):
qc.cx(i, i+1)
qc.measure_all()
# Optimize for specific backend
backend = AerSimulator()
optimized_qc = transpile(qc, backend=backend, optimization_level=3)
print(f"Original depth: {qc.depth()}")
print(f"Optimized depth: {optimized_qc.depth()}")
Parallel Execution
from concurrent.futures import ThreadPoolExecutor
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
def run_circuit(params):
"""Run circuit with given parameters."""
qc = QuantumCircuit(2)
qc.ry(params[0], 0)
qc.ry(params[1], 1)
qc.cx(0, 1)
qc.measure_all()
simulator = AerSimulator()
result = simulator.run(qc, shots=1024).result()
return result.get_counts()
# Run multiple circuits in parallel
param_sets = [
[0.0, 0.0],
[1.57, 1.57],
[3.14, 3.14]
]
with ThreadPoolExecutor(max_workers=3) as executor:
results = list(executor.map(run_circuit, param_sets))
for i, counts in enumerate(results):
print(f"Params {param_sets[i]}: {counts}")
Next Steps
- API Reference - Complete API documentation
- Noisy Simulation - Deep dive into noise modeling
- VQE - Advanced VQE techniques