Loading...
Loading...
Comprehensive guide for Qiskit - IBM's quantum computing framework. Use for quantum circuit design, quantum algorithms (VQE, QAOA, Grover, Shor), quantum simulation, noise modeling, quantum machine learning, and quantum chemistry calculations. Essential for quantum computing research and applications.
npx skill4agent add tondevrel/scientific-agent-skills qiskitqiskit.circuit.QuantumCircuitqiskit.algorithms.VQEqiskit.quantum_infoqiskit_nature| Task | Module | Example |
|---|---|---|
| Circuit building | | |
| Quantum algorithms | | |
| Quantum simulation | | |
| Quantum chemistry | | |
| Noise modeling | | |
| Transpilation | | |
| Quantum ML | | |
| Visualization | | |
# Core Qiskit
pip install qiskit
# With visualization tools
pip install qiskit[visualization]
# Quantum chemistry extension
pip install qiskit-nature qiskit-nature-pyscf
# Machine learning extension
pip install qiskit-machine-learning
# Optimization extension
pip install qiskit-optimization
# Full installation
pip install 'qiskit[all]' qiskit-nature qiskit-machine-learning qiskit-optimization# Core imports
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit import transpile, assemble
from qiskit.providers.aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
# Quantum algorithms
from qiskit.algorithms import VQE, QAOA, Grover, Shor
from qiskit.algorithms.optimizers import SLSQP, COBYLA, SPSA
# Quantum info
from qiskit.quantum_info import Statevector, DensityMatrix, Operator
from qiskit.quantum_info import entropy, entanglement_of_formation
# Circuit library
from qiskit.circuit.library import QFT, RealAmplitudes, EfficientSU2from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
# Create circuit
qc = QuantumCircuit(2, 2)
# Add gates
qc.h(0) # Hadamard on qubit 0
qc.cx(0, 1) # CNOT from 0 to 1
# Measure
qc.measure([0, 1], [0, 1])
# Simulate
simulator = AerSimulator()
job = simulator.run(qc, shots=1000)
result = job.result()
counts = result.get_counts()
print(f"Results: {counts}")from qiskit import QuantumCircuit
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Estimator
from qiskit.quantum_info import SparsePauliOp
# Define Hamiltonian
hamiltonian = SparsePauliOp(['ZZ', 'IZ', 'ZI'], coeffs=[1.0, -0.5, -0.5])
# Create ansatz
ansatz = RealAmplitudes(num_qubits=2, reps=1)
# Setup VQE
optimizer = SLSQP(maxiter=100)
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer)
# Run
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(f"Ground state energy: {result.eigenvalue:.6f}")from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
from qiskit.primitives import Estimator
# ❌ BAD: No measurement
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
# Forgot qc.measure()!
# ✅ GOOD: Always measure when needed
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# ❌ BAD: Using deprecated execute()
from qiskit import execute
result = execute(qc, backend, shots=1024).result()
# ✅ GOOD: Use new run() method
simulator = AerSimulator()
job = simulator.run(qc, shots=1024)
result = job.result()
# ❌ BAD: Assuming perfect measurement
counts = result.get_counts()
# Assuming exactly 50/50 split!
assert counts['00'] == 512
# ✅ GOOD: Handle statistical variation
counts = result.get_counts()
ratio = counts.get('00', 0) / sum(counts.values())
print(f"Measured |00⟩ with probability {ratio:.3f}")
# ❌ BAD: Not checking circuit properties
qc = QuantumCircuit(20) # Many qubits!
# Adding many gates...
# Trying to simulate without checking depth/size!
# ✅ GOOD: Check circuit properties
qc = QuantumCircuit(20)
# ... add gates ...
print(f"Circuit depth: {qc.depth()}")
print(f"Gate count: {len(qc.data)}")
print(f"Qubits: {qc.num_qubits}")
# ❌ BAD: Ignoring transpilation
job = backend.run(qc) # May fail on real hardware!
# ✅ GOOD: Transpile for backend
from qiskit import transpile
transpiled_qc = transpile(qc, backend=backend, optimization_level=3)
job = backend.run(transpiled_qc)from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
import numpy as np
# Method 1: Simple initialization
qc = QuantumCircuit(3, 3) # 3 qubits, 3 classical bits
# Method 2: Using registers
qr = QuantumRegister(3, 'q')
cr = ClassicalRegister(3, 'c')
qc = QuantumCircuit(qr, cr)
# Method 3: Multiple registers
qr1 = QuantumRegister(2, 'data')
qr2 = QuantumRegister(1, 'ancilla')
cr = ClassicalRegister(2, 'meas')
qc = QuantumCircuit(qr1, qr2, cr)
print(f"Number of qubits: {qc.num_qubits}")
print(f"Number of classical bits: {qc.num_clbits}")
print(f"Circuit depth: {qc.depth()}")from qiskit import QuantumCircuit
import numpy as np
qc = QuantumCircuit(1)
# Pauli gates
qc.x(0) # Pauli X (NOT gate)
qc.y(0) # Pauli Y
qc.z(0) # Pauli Z
# Hadamard gate
qc.h(0) # Creates superposition
# Phase gates
qc.s(0) # S gate (π/2 phase)
qc.t(0) # T gate (π/4 phase)
qc.sdg(0) # S dagger
qc.tdg(0) # T dagger
# Rotation gates
qc.rx(np.pi/4, 0) # Rotation around X
qc.ry(np.pi/4, 0) # Rotation around Y
qc.rz(np.pi/4, 0) # Rotation around Z
# General rotation
qc.u(np.pi/4, np.pi/2, np.pi, 0) # U gate
# Identity (wait)
qc.id(0)
print(f"Gate count: {len(qc.data)}")from qiskit import QuantumCircuit
import numpy as np
qc = QuantumCircuit(2)
# CNOT (Controlled-NOT)
qc.cx(0, 1) # Control: 0, Target: 1
# Other controlled gates
qc.cy(0, 1) # Controlled-Y
qc.cz(0, 1) # Controlled-Z
qc.ch(0, 1) # Controlled-Hadamard
# SWAP gate
qc.swap(0, 1)
# Controlled phase
qc.cp(np.pi/4, 0, 1)
# Controlled-U
qc.cu(np.pi/4, np.pi/2, np.pi, 0, 0, 1)
# Toffoli (CCX) - needs 3 qubits
qc_3 = QuantumCircuit(3)
qc_3.ccx(0, 1, 2) # Controls: 0,1, Target: 2
print(qc.draw())from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
from qiskit.quantum_info import Statevector
# Bell state (maximally entangled)
def create_bell_state():
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
return qc
bell = create_bell_state()
state = Statevector.from_instruction(bell)
print(f"Bell state: {state}")
# GHZ state (3-qubit entanglement)
def create_ghz_state(n):
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n-1):
qc.cx(i, i+1)
return qc
ghz = create_ghz_state(3)
state_ghz = Statevector.from_instruction(ghz)
print(f"GHZ state: {state_ghz}")
# W state (another type of 3-qubit entanglement)
def create_w_state():
qc = QuantumCircuit(3)
qc.ry(1.9106, 0)
qc.ch(0, 1)
qc.x(0)
qc.cy(0, 1)
qc.ccx(0, 1, 2)
qc.x(0)
return qc
w = create_w_state()
print(f"W state circuit depth: {w.depth()}")from qiskit import QuantumCircuit
from qiskit.circuit import Parameter, ParameterVector
import numpy as np
# Single parameter
theta = Parameter('θ')
qc = QuantumCircuit(1)
qc.ry(theta, 0)
# Bind parameter
bound_qc = qc.bind_parameters({theta: np.pi/4})
print(f"Unbound: {qc}")
print(f"Bound: {bound_qc}")
# Multiple parameters
params = ParameterVector('θ', 4)
qc_param = QuantumCircuit(2)
qc_param.ry(params[0], 0)
qc_param.ry(params[1], 1)
qc_param.cx(0, 1)
qc_param.ry(params[2], 0)
qc_param.ry(params[3], 1)
# Bind all parameters
values = [np.pi/4, np.pi/3, np.pi/2, np.pi/6]
bound = qc_param.bind_parameters(dict(zip(params, values)))
print(f"Number of parameters: {qc_param.num_parameters}")from qiskit import QuantumCircuit
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP, COBYLA
from qiskit.circuit.library import RealAmplitudes, EfficientSU2
from qiskit.primitives import Estimator
from qiskit.quantum_info import SparsePauliOp
import numpy as np
# Define Hamiltonian (e.g., H2 molecule)
# H = -1.05 * ZZ + 0.39 * XX - 0.39 * YY - 0.01 * ZI
hamiltonian = SparsePauliOp(
['ZZ', 'XX', 'YY', 'ZI', 'IZ'],
coeffs=[-1.05, 0.39, -0.39, -0.01, -0.01]
)
# Create ansatz (variational form)
ansatz = RealAmplitudes(num_qubits=2, reps=2)
# Alternative: EfficientSU2
# ansatz = EfficientSU2(num_qubits=2, reps=2)
# Setup optimizer
optimizer = SLSQP(maxiter=100)
# Create estimator primitive
estimator = Estimator()
# Setup and run VQE
vqe = VQE(estimator, ansatz, optimizer)
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(f"Ground state energy: {result.eigenvalue:.6f}")
print(f"Optimal parameters: {result.optimal_parameters}")
print(f"Optimizer evaluations: {result.cost_function_evals}")
# Get optimal circuit
optimal_circuit = ansatz.bind_parameters(result.optimal_point)
print(f"\nOptimal circuit depth: {optimal_circuit.depth()}")from qiskit import QuantumCircuit
from qiskit.algorithms import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler
from qiskit.quantum_info import SparsePauliOp
import numpy as np
# Max-Cut problem on a triangle graph
# Cost Hamiltonian: H = (1-Z0*Z1)/2 + (1-Z1*Z2)/2 + (1-Z0*Z2)/2
cost_hamiltonian = SparsePauliOp(
['ZZ', 'ZI', 'IZ'],
coeffs=[0.5, -0.5, -0.5]
)
# Setup QAOA
optimizer = COBYLA(maxiter=100)
sampler = Sampler()
qaoa = QAOA(sampler, optimizer, reps=2)
# Run QAOA
result = qaoa.compute_minimum_eigenvalue(cost_hamiltonian)
print(f"Optimal objective: {result.eigenvalue:.6f}")
print(f"Optimal parameters: {result.optimal_parameters}")
# Most probable solution
from qiskit.result import QuasiDistribution
prob_dist = result.eigenstate
if isinstance(prob_dist, QuasiDistribution):
most_likely = max(prob_dist, key=prob_dist.get)
print(f"Most likely solution: {bin(most_likely)[2:].zfill(2)}")from qiskit import QuantumCircuit
from qiskit.algorithms import Grover, AmplificationProblem
from qiskit.circuit.library import GroverOperator
from qiskit.primitives import Sampler
import numpy as np
def grover_search(marked_states, n_qubits):
"""
Grover's algorithm to find marked states.
Args:
marked_states: List of marked states (e.g., ['101', '110'])
n_qubits: Number of qubits
"""
# Create oracle that marks the target states
oracle = QuantumCircuit(n_qubits)
# Mark state |101⟩ by flipping phase
if '101' in marked_states:
oracle.x([0, 2]) # Flip to make 101 -> 111
oracle.h(2)
oracle.ccx(0, 1, 2)
oracle.h(2)
oracle.x([0, 2]) # Flip back
# Grover diffusion operator
diffusion = QuantumCircuit(n_qubits)
diffusion.h(range(n_qubits))
diffusion.x(range(n_qubits))
diffusion.h(n_qubits - 1)
diffusion.mcx(list(range(n_qubits - 1)), n_qubits - 1)
diffusion.h(n_qubits - 1)
diffusion.x(range(n_qubits))
diffusion.h(range(n_qubits))
# Complete Grover iteration
grover_op = oracle.compose(diffusion)
# Setup and run
problem = AmplificationProblem(oracle, is_good_state=marked_states)
grover = Grover(sampler=Sampler())
result = grover.amplify(problem)
return result
# Example: Search for |101⟩ in 3-qubit space
result = grover_search(['101'], 3)
print(f"Top measurement: {result.top_measurement}")
print(f"Oracle evaluations: {result.oracle_evaluation}")
# Simpler example: 2-qubit search
qc = QuantumCircuit(2, 2)
qc.h([0, 1]) # Superposition
# Oracle marks |11⟩
qc.cz(0, 1)
# Diffusion
qc.h([0, 1])
qc.x([0, 1])
qc.cz(0, 1)
qc.x([0, 1])
qc.h([0, 1])
qc.measure([0, 1], [0, 1])
from qiskit.providers.aer import AerSimulator
simulator = AerSimulator()
job = simulator.run(qc, shots=1000)
counts = job.result().get_counts()
print(f"Grover results: {counts}")from qiskit import QuantumCircuit
from qiskit.circuit.library import QFT
from qiskit.providers.aer import AerSimulator
import numpy as np
def quantum_phase_estimation(unitary, n_counting_qubits):
"""
Estimate the phase of an eigenstate of a unitary operator.
Args:
unitary: Unitary operator as a QuantumCircuit
n_counting_qubits: Precision qubits
"""
n_system_qubits = unitary.num_qubits
qc = QuantumCircuit(n_counting_qubits + n_system_qubits, n_counting_qubits)
# Initialize eigenstate (simplified: use |1⟩)
qc.x(n_counting_qubits)
# Hadamard on counting qubits
for i in range(n_counting_qubits):
qc.h(i)
# Controlled-U^(2^i) operations
repetitions = 1
for counting_qubit in range(n_counting_qubits):
for _ in range(repetitions):
qc.append(unitary.control(), [counting_qubit] +
list(range(n_counting_qubits, n_counting_qubits + n_system_qubits)))
repetitions *= 2
# Inverse QFT
qc.append(QFT(n_counting_qubits, inverse=True), range(n_counting_qubits))
# Measure counting qubits
qc.measure(range(n_counting_qubits), range(n_counting_qubits))
return qc
# Example: Phase estimation for T gate (phase π/4)
t_gate = QuantumCircuit(1)
t_gate.t(0)
qpe_circuit = quantum_phase_estimation(t_gate, n_counting_qubits=3)
simulator = AerSimulator()
job = simulator.run(qpe_circuit, shots=1000)
counts = job.result().get_counts()
print(f"Phase estimation results: {counts}")
# Most common result gives phase
most_common = max(counts, key=counts.get)
phase_estimate = int(most_common, 2) / (2**3)
print(f"Estimated phase: {phase_estimate * 2 * np.pi:.4f} rad")
print(f"True phase: {np.pi/4:.4f} rad")# Requires: pip install qiskit-nature qiskit-nature-pyscf
from qiskit_nature.units import DistanceUnit
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.mappers import JordanWignerMapper, ParityMapper
from qiskit_nature.second_q.circuit.library import HartreeFock, UCCSD
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.primitives import Estimator
import numpy as np
# Define molecule (H2)
driver = PySCFDriver(
atom='H 0 0 0; H 0 0 0.735',
basis='sto3g',
charge=0,
spin=0,
unit=DistanceUnit.ANGSTROM
)
# Get problem
problem = driver.run()
hamiltonian = problem.hamiltonian.second_q_op()
# Map to qubits
mapper = JordanWignerMapper()
qubit_op = mapper.map(hamiltonian)
print(f"Number of qubits required: {qubit_op.num_qubits}")
# Initial state (Hartree-Fock)
num_particles = problem.num_particles
num_spatial_orbitals = problem.num_spatial_orbitals
init_state = HartreeFock(
num_spatial_orbitals=num_spatial_orbitals,
num_particles=num_particles,
qubit_mapper=mapper
)
# Ansatz (UCCSD)
ansatz = UCCSD(
num_spatial_orbitals=num_spatial_orbitals,
num_particles=num_particles,
qubit_mapper=mapper,
initial_state=init_state
)
# VQE calculation
optimizer = SLSQP(maxiter=100)
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer)
result = vqe.compute_minimum_eigenvalue(qubit_op)
print(f"\nVQE Ground State Energy: {result.eigenvalue:.6f} Ha")
print(f"Reference HF energy: {problem.reference_energy:.6f} Ha")from qiskit_nature.second_q.algorithms import GroundStateEigensolver, ExcitedStatesEigensolver
from qiskit_nature.second_q.algorithms import QEOM
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.primitives import Estimator
# Setup molecule
driver = PySCFDriver(atom='H 0 0 0; H 0 0 0.735', basis='sto3g')
problem = driver.run()
# Mapper
mapper = JordanWignerMapper()
# Ground state solver
optimizer = SLSQP(maxiter=100)
estimator = Estimator()
# Simple ansatz for demonstration
from qiskit.circuit.library import RealAmplitudes
ansatz = RealAmplitudes(num_qubits=4, reps=2)
vqe = VQE(estimator, ansatz, optimizer)
ground_solver = GroundStateEigensolver(mapper, vqe)
# Calculate ground state
ground_result = ground_solver.solve(problem)
print(f"Ground state energy: {ground_result.total_energies[0]:.6f} Ha")
# Excited states with QEOM
qeom = QEOM(ground_solver, 'sd') # singles and doubles
excited_solver = ExcitedStatesEigensolver(mapper, qeom)
# Calculate excited states
excited_result = excited_solver.solve(problem)
print(f"\nExcited state energies:")
for i, energy in enumerate(excited_result.total_energies):
print(f"State {i}: {energy:.6f} Ha")from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit_nature.second_q.algorithms import GroundStateEigensolver
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.primitives import Estimator
from qiskit.circuit.library import RealAmplitudes
import numpy as np
def calculate_pes(distances, molecule_template, basis='sto3g'):
"""
Calculate potential energy surface for a diatomic molecule.
Args:
distances: Array of interatomic distances
molecule_template: Molecule string with {} for distance
basis: Basis set
"""
energies = []
for distance in distances:
# Setup molecule at this distance
atom_string = molecule_template.format(distance)
driver = PySCFDriver(atom=atom_string, basis=basis)
problem = driver.run()
# Map to qubits
mapper = JordanWignerMapper()
# Simple VQE calculation
ansatz = RealAmplitudes(num_qubits=4, reps=1)
optimizer = SLSQP(maxiter=50)
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer)
solver = GroundStateEigensolver(mapper, vqe)
# Calculate energy
result = solver.solve(problem)
energies.append(result.total_energies[0])
print(f"Distance {distance:.2f} Å: Energy = {energies[-1]:.6f} Ha")
return np.array(energies)
# Calculate PES for H2
distances = np.linspace(0.5, 2.5, 5) # Angstroms
molecule_template = 'H 0 0 0; H 0 0 {}'
energies = calculate_pes(distances, molecule_template)
# Find equilibrium bond length
min_idx = np.argmin(energies)
print(f"\nEquilibrium bond length: {distances[min_idx]:.2f} Å")
print(f"Minimum energy: {energies[min_idx]:.6f} Ha")from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp, Statevector
from qiskit.synthesis import SuzukiTrotter
import numpy as np
def trotter_simulation(hamiltonian, time, n_steps):
"""
Simulate time evolution under Hamiltonian using Trotter decomposition.
Args:
hamiltonian: SparsePauliOp Hamiltonian
time: Total evolution time
n_steps: Number of Trotter steps
"""
dt = time / n_steps
# Create Trotter circuit
n_qubits = hamiltonian.num_qubits
qc = QuantumCircuit(n_qubits)
# Initial state (e.g., |0⟩)
# Apply Trotter steps
for _ in range(n_steps):
# For each Pauli term in Hamiltonian
for pauli, coeff in zip(hamiltonian.paulis, hamiltonian.coeffs):
# Apply exp(-i * coeff * dt * pauli)
angle = 2 * float(coeff.real) * dt
# Simple implementation for single Pauli terms
pauli_str = str(pauli)
# Apply appropriate rotation
if 'Z' in pauli_str and pauli_str.count('I') == n_qubits - 1:
idx = pauli_str.index('Z')
qc.rz(angle, n_qubits - 1 - idx)
elif 'X' in pauli_str and pauli_str.count('I') == n_qubits - 1:
idx = pauli_str.index('X')
qc.rx(angle, n_qubits - 1 - idx)
return qc
# Example: Ising model Hamiltonian
hamiltonian = SparsePauliOp(['ZZ', 'XI', 'IX'], coeffs=[1.0, -0.5, -0.5])
# Simulate for time t=1.0 with 10 Trotter steps
qc = trotter_simulation(hamiltonian, time=1.0, n_steps=10)
print(f"Trotter circuit depth: {qc.depth()}")
print(f"Gate count: {len(qc.data)}")
# Get final state
state = Statevector.from_instruction(qc)
print(f"Final state vector: {state[:4]}") # First 4 amplitudesfrom qiskit import QuantumCircuit
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Estimator
from qiskit.quantum_info import SparsePauliOp
import numpy as np
def simulate_dynamics(hamiltonian, initial_state_circuit, times, ansatz_reps=2):
"""
Simulate quantum dynamics using VQE at different times.
Args:
hamiltonian: Time-evolution Hamiltonian
initial_state_circuit: Circuit preparing initial state
times: Array of times to simulate
ansatz_reps: Repetitions in ansatz
"""
n_qubits = hamiltonian.num_qubits
results = []
for t in times:
# Time-evolved Hamiltonian: H(t) = exp(-iHt) ρ(0) exp(iHt)
# Approximate with VQE
ansatz = RealAmplitudes(num_qubits=n_qubits, reps=ansatz_reps)
# Combine initial state + ansatz
full_circuit = initial_state_circuit.copy()
full_circuit.compose(ansatz, inplace=True)
optimizer = SLSQP(maxiter=100)
estimator = Estimator()
vqe = VQE(estimator, full_circuit, optimizer)
result = vqe.compute_minimum_eigenvalue(hamiltonian)
results.append({
'time': t,
'energy': result.eigenvalue,
'parameters': result.optimal_parameters
})
print(f"Time {t:.2f}: Energy = {result.eigenvalue:.6f}")
return results
# Example: Simulate Heisenberg model
hamiltonian = SparsePauliOp(
['XX', 'YY', 'ZZ'],
coeffs=[0.5, 0.5, 0.5]
)
# Initial state: |01⟩
initial_state = QuantumCircuit(2)
initial_state.x(1)
# Simulate at different times
times = np.linspace(0, 2, 5)
results = simulate_dynamics(hamiltonian, initial_state, times)# Requires: pip install qiskit-machine-learning
from qiskit_machine_learning.kernels import FidelityQuantumKernel
from qiskit.circuit.library import ZZFeatureMap
from qiskit.primitives import Sampler
from sklearn.svm import SVC
import numpy as np
# Generate synthetic data
np.random.seed(42)
X_train = np.random.rand(20, 2) * 2 * np.pi
y_train = (X_train[:, 0] + X_train[:, 1] > np.pi).astype(int)
X_test = np.random.rand(10, 2) * 2 * np.pi
y_test = (X_test[:, 0] + X_test[:, 1] > np.pi).astype(int)
# Create feature map
feature_map = ZZFeatureMap(feature_dimension=2, reps=2)
# Create quantum kernel
sampler = Sampler()
quantum_kernel = FidelityQuantumKernel(feature_map=feature_map, fidelity=sampler)
# Compute kernel matrix
kernel_matrix_train = quantum_kernel.evaluate(x_vec=X_train)
kernel_matrix_test = quantum_kernel.evaluate(x_vec=X_test, y_vec=X_train)
print(f"Training kernel matrix shape: {kernel_matrix_train.shape}")
print(f"Test kernel matrix shape: {kernel_matrix_test.shape}")
# Use with SVM
svc = SVC(kernel='precomputed')
svc.fit(kernel_matrix_train, y_train)
# Predict
predictions = svc.predict(kernel_matrix_test)
accuracy = np.mean(predictions == y_test)
print(f"\nQuantum Kernel SVM Accuracy: {accuracy:.2%}")from qiskit_machine_learning.algorithms import VQC
from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap
from qiskit.algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler
import numpy as np
# Generate training data
np.random.seed(42)
X_train = np.random.rand(40, 2) * 2 - 1 # [-1, 1]
y_train = (X_train[:, 0]**2 + X_train[:, 1]**2 < 0.5).astype(int)
X_test = np.random.rand(20, 2) * 2 - 1
y_test = (X_test[:, 0]**2 + X_test[:, 1]**2 < 0.5).astype(int)
# Feature map
feature_map = ZZFeatureMap(2)
# Ansatz
ansatz = RealAmplitudes(2, reps=2)
# Create VQC
optimizer = COBYLA(maxiter=100)
sampler = Sampler()
vqc = VQC(
sampler=sampler,
feature_map=feature_map,
ansatz=ansatz,
optimizer=optimizer,
)
# Train
vqc.fit(X_train, y_train)
# Predict
train_score = vqc.score(X_train, y_train)
test_score = vqc.score(X_test, y_test)
print(f"Training accuracy: {train_score:.2%}")
print(f"Test accuracy: {test_score:.2%}")
# Predictions
predictions = vqc.predict(X_test)
print(f"Sample predictions: {predictions[:5]}")
print(f"True labels: {y_test[:5]}")from qiskit_machine_learning.neural_networks import SamplerQNN
from qiskit_machine_learning.algorithms import NeuralNetworkClassifier
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.circuit.library import RealAmplitudes
from qiskit.algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler
import numpy as np
# Create parameterized quantum circuit
def create_qnn_circuit(num_qubits, num_features):
qc = QuantumCircuit(num_qubits)
# Feature map parameters
feature_params = [Parameter(f'x{i}') for i in range(num_features)]
# Encode features
for i, param in enumerate(feature_params):
if i < num_qubits:
qc.ry(param, i)
# Variational part
ansatz = RealAmplitudes(num_qubits, reps=1)
qc.compose(ansatz, inplace=True)
return qc, feature_params, ansatz.parameters
num_qubits = 2
num_features = 2
qc, feature_params, weight_params = create_qnn_circuit(num_qubits, num_features)
# Create QNN
sampler = Sampler()
qnn = SamplerQNN(
circuit=qc,
input_params=feature_params,
weight_params=weight_params,
sampler=sampler,
)
# Create classifier
optimizer = COBYLA(maxiter=50)
classifier = NeuralNetworkClassifier(
neural_network=qnn,
optimizer=optimizer,
)
# Training data
X_train = np.random.rand(30, 2)
y_train = (X_train[:, 0] > X_train[:, 1]).astype(int)
# Train
classifier.fit(X_train, y_train)
# Test
X_test = np.random.rand(10, 2)
y_test = (X_test[:, 0] > X_test[:, 1]).astype(int)
score = classifier.score(X_test, y_test)
print(f"QNN Classifier accuracy: {score:.2%}")from qiskit.providers.aer import AerSimulator
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise import depolarizing_error, thermal_relaxation_error
from qiskit import QuantumCircuit
import numpy as np
# Create noise model
noise_model = NoiseModel()
# Depolarizing error on single-qubit gates
error_1q = depolarizing_error(0.001, 1) # 0.1% error
noise_model.add_all_qubit_quantum_error(error_1q, ['u1', 'u2', 'u3', 'rx', 'ry', 'rz'])
# Depolarizing error on two-qubit gates
error_2q = depolarizing_error(0.01, 2) # 1% error
noise_model.add_all_qubit_quantum_error(error_2q, ['cx', 'cz', 'swap'])
# Thermal relaxation error
# T1 = 50 microseconds, T2 = 70 microseconds, gate_time = 0.1 microseconds
t1 = 50e3 # ns
t2 = 70e3 # ns
gate_time = 100 # ns
error_thermal = thermal_relaxation_error(t1, t2, gate_time)
noise_model.add_all_qubit_quantum_error(error_thermal, ['id'])
# Measurement error
from qiskit.providers.aer.noise import ReadoutError
prob_meas0_prep1 = 0.05 # Prob of measuring 0 when prepared in 1
prob_meas1_prep0 = 0.10 # Prob of measuring 1 when prepared in 0
readout_error = ReadoutError([[1 - prob_meas1_prep0, prob_meas1_prep0],
[prob_meas0_prep1, 1 - prob_meas0_prep1]])
noise_model.add_all_qubit_readout_error(readout_error)
print(f"Noise model: {noise_model}")
# Run circuit with noise
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Noiseless simulation
simulator_ideal = AerSimulator()
job_ideal = simulator_ideal.run(qc, shots=1000)
counts_ideal = job_ideal.result().get_counts()
# Noisy simulation
simulator_noisy = AerSimulator(noise_model=noise_model)
job_noisy = simulator_noisy.run(qc, shots=1000)
counts_noisy = job_noisy.result().get_counts()
print(f"\nIdeal results: {counts_ideal}")
print(f"Noisy results: {counts_noisy}")from qiskit import QuantumCircuit, transpile
from qiskit.providers.aer import AerSimulator
from qiskit.providers.aer.noise import NoiseModel, depolarizing_error
import numpy as np
from scipy.optimize import curve_fit
def run_circuit_with_noise(circuit, noise_level, shots=1000):
"""Run circuit with scaled noise."""
# Create noise model
noise_model = NoiseModel()
error = depolarizing_error(noise_level, 1)
noise_model.add_all_qubit_quantum_error(error, ['u1', 'u2', 'u3'])
# Simulate
simulator = AerSimulator(noise_model=noise_model)
job = simulator.run(circuit, shots=shots)
result = job.result()
# Extract expectation value (simplified)
counts = result.get_counts()
expectation = sum(counts.get(bitstring, 0) * (-1)**bitstring.count('1')
for bitstring in counts) / shots
return expectation
def zero_noise_extrapolation(circuit, noise_levels, shots=1000):
"""
Perform zero-noise extrapolation.
Args:
circuit: Quantum circuit
noise_levels: List of noise scaling factors
shots: Number of shots per simulation
"""
expectations = []
for noise in noise_levels:
exp_val = run_circuit_with_noise(circuit, noise, shots)
expectations.append(exp_val)
print(f"Noise {noise:.4f}: Expectation = {exp_val:.4f}")
# Fit exponential model: E(λ) = A + B * exp(-C * λ)
def exp_model(x, a, b, c):
return a + b * np.exp(-c * x)
# Fit
popt, _ = curve_fit(exp_model, noise_levels, expectations)
# Extrapolate to zero noise
zero_noise_value = exp_model(0, *popt)
print(f"\nZero-noise extrapolated value: {zero_noise_value:.4f}")
return zero_noise_value, expectations
# Example circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run ZNE
noise_levels = np.array([0.001, 0.005, 0.01, 0.02])
zne_value, measured_values = zero_noise_extrapolation(qc, noise_levels)from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
from qiskit.providers.aer.noise import NoiseModel, ReadoutError
from qiskit.result import marginal_counts
from qiskit.ignis.mitigation.measurement import (
complete_meas_cal,
CompleteMeasFitter
)
# Create readout noise
prob_meas0_prep1 = 0.1
prob_meas1_prep0 = 0.05
readout_error = ReadoutError([[1 - prob_meas1_prep0, prob_meas1_prep0],
[prob_meas0_prep1, 1 - prob_meas0_prep1]])
noise_model = NoiseModel()
noise_model.add_all_qubit_readout_error(readout_error)
# Generate calibration circuits
n_qubits = 2
meas_calibs, state_labels = complete_meas_cal(qr=list(range(n_qubits)))
# Run calibration
simulator = AerSimulator(noise_model=noise_model)
cal_results = []
for circuit in meas_calibs:
job = simulator.run(circuit, shots=1000)
cal_results.append(job.result())
# Fit the calibration
meas_fitter = CompleteMeasFitter(cal_results, state_labels)
# Get mitigation matrix
print("Calibration matrix:")
print(meas_fitter.cal_matrix)
# Run actual circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
job = simulator.run(qc, shots=1000)
result = job.result()
noisy_counts = result.get_counts()
# Apply mitigation
mitigated_counts = meas_fitter.filter.apply(noisy_counts)
print(f"\nNoisy counts: {noisy_counts}")
print(f"Mitigated counts: {mitigated_counts}")from qiskit import QuantumCircuit, transpile
from qiskit.providers.fake_provider import FakeMontreal
from qiskit.visualization import plot_circuit_layout
import matplotlib.pyplot as plt
# Create circuit
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
qc.cx(0, 2)
# Get fake backend (simulates real hardware)
backend = FakeMontreal()
# Transpile with different optimization levels
for level in range(4):
transpiled = transpile(qc, backend=backend, optimization_level=level)
print(f"\nOptimization level {level}:")
print(f" Depth: {transpiled.depth()}")
print(f" Gate count: {len(transpiled.data)}")
print(f" CNOT count: {transpiled.count_ops().get('cx', 0)}")
# Best transpilation
best_transpiled = transpile(qc, backend=backend, optimization_level=3)
print(f"\nOriginal circuit:")
print(f" Depth: {qc.depth()}")
print(f" Gates: {len(qc.data)}")
print(f"\nTranspiled circuit:")
print(f" Depth: {best_transpiled.depth()}")
print(f" Gates: {len(best_transpiled.data)}")from qiskit import QuantumCircuit
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import Optimize1qGates, CommutativeCancellation
from qiskit.transpiler.passes import UnitarySynthesis, Unroll3qOrMore
# Create circuit with redundant gates
qc = QuantumCircuit(2)
qc.h(0)
qc.h(0) # Redundant - cancels previous H
qc.x(1)
qc.x(1) # Redundant - cancels previous X
qc.cx(0, 1)
print(f"Original circuit depth: {qc.depth()}")
print(f"Original gate count: {len(qc.data)}")
# Create custom pass manager
pm = PassManager()
# Add optimization passes
pm.append(Optimize1qGates()) # Optimize single-qubit gates
pm.append(CommutativeCancellation()) # Cancel commuting gates
pm.append(Unroll3qOrMore()) # Decompose 3+ qubit gates
pm.append(UnitarySynthesis()) # Synthesize unitaries
# Run pass manager
optimized_qc = pm.run(qc)
print(f"\nOptimized circuit depth: {optimized_qc.depth()}")
print(f"Optimized gate count: {len(optimized_qc.data)}")
print("\nOriginal circuit:")
print(qc.draw())
print("\nOptimized circuit:")
print(optimized_qc.draw())from qiskit import QuantumCircuit, transpile
from qiskit.providers.fake_provider import FakeMontreal
from qiskit.transpiler import CouplingMap
# Create circuit that requires routing
qc = QuantumCircuit(5)
qc.h(0)
qc.cx(0, 4) # Long-range connection
qc.cx(1, 3)
qc.cx(2, 4)
# Fake backend with specific topology
backend = FakeMontreal()
coupling_map = backend.configuration().coupling_map
print(f"Backend coupling map: {coupling_map[:10]}...") # First 10 edges
# Transpile with layout awareness
transpiled = transpile(
qc,
backend=backend,
optimization_level=3,
seed_transpiler=42 # For reproducibility
)
# Get final layout
final_layout = transpiled.layout.final_index_layout()
print(f"\nFinal qubit layout: {final_layout}")
print(f"\nOriginal circuit:")
print(f" Depth: {qc.depth()}")
print(f" CNOT count: {qc.count_ops().get('cx', 0)}")
print(f"\nTranspiled circuit (with routing):")
print(f" Depth: {transpiled.depth()}")
print(f" CNOT count: {transpiled.count_ops().get('cx', 0)}")
print(f" SWAP count: {transpiled.count_ops().get('swap', 0)}")from qiskit.quantum_info import Statevector, DensityMatrix, partial_trace
from qiskit.quantum_info import entropy, entanglement_of_formation
from qiskit import QuantumCircuit
import numpy as np
# Create entangled state (Bell state)
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
state = Statevector.from_instruction(qc)
density_matrix = DensityMatrix(state)
print(f"Bell state: {state}")
# Von Neumann entropy (should be 0 for pure states)
entropy_full = entropy(density_matrix)
print(f"\nFull system entropy: {entropy_full:.6f}")
# Reduced density matrix (trace out qubit 1)
rho_0 = partial_trace(density_matrix, [1])
entropy_reduced = entropy(rho_0)
print(f"Reduced density matrix entropy: {entropy_reduced:.6f}")
# Entanglement of formation
# For Bell state, should be 1
eof = entanglement_of_formation(density_matrix)
print(f"Entanglement of formation: {eof:.6f}")
# Compare with separable state
qc_sep = QuantumCircuit(2)
qc_sep.h(0)
qc_sep.h(1)
state_sep = Statevector.from_instruction(qc_sep)
dm_sep = DensityMatrix(state_sep)
rho_0_sep = partial_trace(dm_sep, [1])
entropy_sep = entropy(rho_0_sep)
print(f"\nSeparable state reduced entropy: {entropy_sep:.6f}")from qiskit.quantum_info import Choi, SuperOp, Kraus
from qiskit import QuantumCircuit
import numpy as np
# Define a quantum channel (amplitude damping)
def amplitude_damping_channel(gamma):
"""
Amplitude damping channel with damping parameter gamma.
Models energy dissipation.
"""
K0 = np.array([[1, 0], [0, np.sqrt(1 - gamma)]])
K1 = np.array([[0, np.sqrt(gamma)], [0, 0]])
return Kraus([K0, K1])
# Create channel
gamma = 0.3
channel = amplitude_damping_channel(gamma)
print(f"Amplitude damping channel (γ={gamma}):")
print(f"Number of Kraus operators: {len(channel)}")
# Convert to different representations
superop = SuperOp(channel)
choi = Choi(channel)
print(f"\nSuperoperator shape: {superop.dim}")
print(f"Choi matrix shape: {choi.dim}")
# Apply channel to a state
from qiskit.quantum_info import Statevector, DensityMatrix
# Initial state |1⟩
state = Statevector([0, 1])
dm = DensityMatrix(state)
# Apply channel
dm_evolved = dm.evolve(channel)
print(f"\nInitial state: {state}")
print(f"After channel: {dm_evolved}")
# Measure fidelity
from qiskit.quantum_info import state_fidelity
fidelity = state_fidelity(dm, dm_evolved)
print(f"Fidelity: {fidelity:.6f}")from qiskit.quantum_info import Statevector, DensityMatrix
from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
from qiskit.quantum_info.states import state_fidelity
import numpy as np
def perform_state_tomography(qc, shots=1000):
"""
Simplified quantum state tomography.
Measures in X, Y, Z bases to reconstruct density matrix.
"""
simulator = AerSimulator()
# Measurement circuits in different bases
measurements = {
'Z': QuantumCircuit(qc.num_qubits, qc.num_qubits),
'X': QuantumCircuit(qc.num_qubits, qc.num_qubits),
'Y': QuantumCircuit(qc.num_qubits, qc.num_qubits)
}
# X basis: apply H before measurement
measurements['X'].h(range(qc.num_qubits))
# Y basis: apply S†H before measurement
measurements['Y'].sdg(range(qc.num_qubits))
measurements['Y'].h(range(qc.num_qubits))
# Measure all
for basis_circ in measurements.values():
basis_circ.measure(range(qc.num_qubits), range(qc.num_qubits))
# Run measurements
results = {}
for basis, meas_circ in measurements.items():
full_circ = qc.copy()
full_circ.compose(meas_circ, inplace=True)
job = simulator.run(full_circ, shots=shots)
results[basis] = job.result().get_counts()
print(f"Z-basis measurements: {results['Z']}")
print(f"X-basis measurements: {results['X']}")
print(f"Y-basis measurements: {results['Y']}")
# Simplified reconstruction (for single qubit)
if qc.num_qubits == 1:
# Extract Pauli expectation values
z_exp = (results['Z'].get('0', 0) - results['Z'].get('1', 0)) / shots
x_exp = (results['X'].get('0', 0) - results['X'].get('1', 0)) / shots
y_exp = (results['Y'].get('0', 0) - results['Y'].get('1', 0)) / shots
# Reconstruct density matrix: ρ = (I + x⟨X⟩ + y⟨Y⟩ + z⟨Z⟩)/2
rho = np.array([
[0.5 + 0.5*z_exp, 0.5*x_exp - 0.5j*y_exp],
[0.5*x_exp + 0.5j*y_exp, 0.5 - 0.5*z_exp]
])
return DensityMatrix(rho)
return None
# Test on a known state
qc = QuantumCircuit(1)
qc.ry(np.pi/3, 0) # Rotate to create superposition
# True state
true_state = Statevector.from_instruction(qc)
true_dm = DensityMatrix(true_state)
# Tomography
reconstructed_dm = perform_state_tomography(qc, shots=10000)
if reconstructed_dm is not None:
fidelity = state_fidelity(true_dm, reconstructed_dm)
print(f"\nReconstruction fidelity: {fidelity:.6f}")
print(f"\nTrue density matrix:\n{np.array(true_dm)}")
print(f"\nReconstructed density matrix:\n{np.array(reconstructed_dm)}")from qiskit import QuantumCircuit
from qiskit.visualization import circuit_drawer
import matplotlib.pyplot as plt
# Create complex circuit
qc = QuantumCircuit(3, 3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
qc.barrier()
qc.measure([0, 1, 2], [0, 1, 2])
# Different drawing styles
print("Text representation:")
print(qc.draw(output='text'))
# Matplotlib style (most common)
print("\nMatplotlib style:")
qc.draw(output='mpl')
plt.show()
# LaTeX style (for publications)
# qc.draw(output='latex')
# With gate labels
qc_labeled = QuantumCircuit(2, 2)
qc_labeled.h(0)
qc_labeled.cx(0, 1)
qc_labeled.measure_all()
qc_labeled.draw(output='mpl', style={'name': 'bw'})
plt.show()from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
from qiskit.visualization import plot_histogram, plot_bloch_multivector
from qiskit.quantum_info import Statevector
import matplotlib.pyplot as plt
# Run circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
simulator = AerSimulator()
job = simulator.run(qc, shots=1000)
counts = job.result().get_counts()
# Histogram
plot_histogram(counts, title='Bell State Measurement')
plt.show()
# Multiple result comparison
qc2 = QuantumCircuit(2, 2)
qc2.h(0)
qc2.h(1)
qc2.measure([0, 1], [0, 1])
job2 = simulator.run(qc2, shots=1000)
counts2 = job2.result().get_counts()
plot_histogram([counts, counts2],
legend=['Bell State', 'Product State'],
title='State Comparison')
plt.show()
# Bloch sphere visualization
qc_bloch = QuantumCircuit(1)
qc_bloch.ry(np.pi/4, 0)
state = Statevector.from_instruction(qc_bloch)
plot_bloch_multivector(state)
plt.show()from qiskit.quantum_info import Statevector, DensityMatrix
from qiskit.visualization import plot_state_qsphere, plot_state_city
from qiskit.visualization import plot_state_hinton, plot_state_paulivec
import matplotlib.pyplot as plt
# Create an interesting state
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.h(0)
qc.ry(np.pi/4, 1)
qc.cx(0, 1)
state = Statevector.from_instruction(qc)
# Q-sphere
plot_state_qsphere(state, title='Q-sphere')
plt.show()
# City plot
plot_state_city(state, title='State City')
plt.show()
# Hinton plot
dm = DensityMatrix(state)
plot_state_hinton(dm, title='Density Matrix')
plt.show()
# Pauli vector representation
plot_state_paulivec(state, title='Pauli Vector')
plt.show()from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit_nature.second_q.circuit.library import UCCSD, HartreeFock
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.primitives import Estimator
import numpy as np
def calculate_molecule_energy(atom_string, basis='sto3g', charge=0, spin=0):
"""
Complete workflow for molecular energy calculation.
Args:
atom_string: Atomic coordinates (e.g., 'H 0 0 0; H 0 0 0.735')
basis: Basis set
charge: Molecular charge
spin: Spin multiplicity
"""
print(f"Calculating energy for: {atom_string}")
print(f"Basis: {basis}, Charge: {charge}, Spin: {spin}\n")
# 1. Setup driver
driver = PySCFDriver(
atom=atom_string,
basis=basis,
charge=charge,
spin=spin
)
# 2. Get electronic structure problem
problem = driver.run()
# 3. Setup mapper
mapper = JordanWignerMapper()
# 4. Get Hamiltonian
hamiltonian = problem.hamiltonian.second_q_op()
qubit_op = mapper.map(hamiltonian)
print(f"Number of qubits: {qubit_op.num_qubits}")
print(f"Number of Hamiltonian terms: {len(qubit_op)}")
# 5. Setup initial state and ansatz
num_particles = problem.num_particles
num_spatial_orbitals = problem.num_spatial_orbitals
init_state = HartreeFock(
num_spatial_orbitals=num_spatial_orbitals,
num_particles=num_particles,
qubit_mapper=mapper
)
ansatz = UCCSD(
num_spatial_orbitals=num_spatial_orbitals,
num_particles=num_particles,
qubit_mapper=mapper,
initial_state=init_state
)
print(f"Ansatz circuit depth: {ansatz.depth()}")
print(f"Number of parameters: {ansatz.num_parameters}\n")
# 6. Run VQE
optimizer = SLSQP(maxiter=100)
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer)
result = vqe.compute_minimum_eigenvalue(qubit_op)
# 7. Extract results
vqe_energy = result.eigenvalue
hf_energy = problem.reference_energy
print(f"Hartree-Fock energy: {hf_energy:.6f} Ha")
print(f"VQE energy: {vqe_energy:.6f} Ha")
print(f"Correlation energy: {vqe_energy - hf_energy:.6f} Ha")
print(f"Optimizer evaluations: {result.cost_function_evals}")
return {
'vqe_energy': vqe_energy,
'hf_energy': hf_energy,
'correlation': vqe_energy - hf_energy,
'optimal_parameters': result.optimal_parameters,
'num_qubits': qubit_op.num_qubits
}
# Example: H2 molecule
results = calculate_molecule_energy('H 0 0 0; H 0 0 0.735')from qiskit import QuantumCircuit, transpile
from qiskit.providers.fake_provider import FakeMontreal
from qiskit.transpiler import PassManager, CouplingMap
from qiskit.transpiler.passes import *
import matplotlib.pyplot as plt
def optimize_circuit_for_hardware(qc, backend=None, optimization_level=3):
"""
Complete circuit optimization pipeline.
Args:
qc: Input quantum circuit
backend: Target backend (or None for generic optimization)
optimization_level: 0-3
"""
print(f"Original circuit:")
print(f" Qubits: {qc.num_qubits}")
print(f" Depth: {qc.depth()}")
print(f" Gate count: {len(qc.data)}")
print(f" Operations: {qc.count_ops()}\n")
if backend is None:
backend = FakeMontreal()
# Standard transpilation
transpiled = transpile(
qc,
backend=backend,
optimization_level=optimization_level,
seed_transpiler=42
)
print(f"After transpilation (level {optimization_level}):")
print(f" Depth: {transpiled.depth()}")
print(f" Gate count: {len(transpiled.data)}")
print(f" Operations: {transpiled.count_ops()}")
print(f" SWAP gates: {transpiled.count_ops().get('swap', 0)}\n")
# Custom optimization passes
pm = PassManager()
# Add passes
pm.append(Optimize1qGates())
pm.append(CommutativeCancellation())
pm.append(CXCancellation())
further_optimized = pm.run(transpiled)
print(f"After custom optimization:")
print(f" Depth: {further_optimized.depth()}")
print(f" Gate count: {len(further_optimized.data)}")
print(f" Operations: {further_optimized.count_ops()}\n")
# Calculate reduction
depth_reduction = (1 - further_optimized.depth() / qc.depth()) * 100
gate_reduction = (1 - len(further_optimized.data) / len(qc.data)) * 100
print(f"Optimization results:")
print(f" Depth reduction: {depth_reduction:.1f}%")
print(f" Gate count reduction: {gate_reduction:.1f}%")
return further_optimized
# Example: Complex circuit
qc = QuantumCircuit(4)
qc.h(range(4))
for i in range(3):
qc.cx(i, i+1)
qc.barrier()
for i in range(4):
qc.ry(np.pi/4, i)
qc.barrier()
for i in range(2):
qc.cx(i, i+2)
optimized = optimize_circuit_for_hardware(qc)from qiskit import QuantumCircuit
from qiskit.algorithms import VQE, QAOA
from qiskit.algorithms.optimizers import SLSQP, COBYLA, SPSA
from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Estimator
from qiskit.quantum_info import SparsePauliOp
import time
import numpy as np
def benchmark_vqe_optimizers(hamiltonian, ansatz, optimizers_dict, trials=3):
"""
Benchmark different optimizers for VQE.
Args:
hamiltonian: Problem Hamiltonian
ansatz: Variational ansatz
optimizers_dict: Dict of optimizer name -> optimizer instance
trials: Number of trials per optimizer
"""
results = {}
for opt_name, optimizer in optimizers_dict.items():
print(f"\nBenchmarking {opt_name}...")
trial_results = []
for trial in range(trials):
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer)
start_time = time.time()
result = vqe.compute_minimum_eigenvalue(hamiltonian)
elapsed_time = time.time() - start_time
trial_results.append({
'energy': result.eigenvalue,
'time': elapsed_time,
'evals': result.cost_function_evals
})
print(f" Trial {trial + 1}: E = {result.eigenvalue:.6f}, "
f"Time = {elapsed_time:.2f}s, Evals = {result.cost_function_evals}")
# Aggregate results
energies = [r['energy'] for r in trial_results]
times = [r['time'] for r in trial_results]
evals = [r['evals'] for r in trial_results]
results[opt_name] = {
'mean_energy': np.mean(energies),
'std_energy': np.std(energies),
'mean_time': np.mean(times),
'mean_evals': np.mean(evals),
'best_energy': min(energies)
}
# Print summary
print("\n" + "="*60)
print("BENCHMARK SUMMARY")
print("="*60)
print(f"{'Optimizer':<15} {'Best Energy':>12} {'Mean Time':>12} {'Mean Evals':>12}")
print("-"*60)
for opt_name, res in results.items():
print(f"{opt_name:<15} {res['best_energy']:>12.6f} "
f"{res['mean_time']:>12.2f}s {res['mean_evals']:>12.0f}")
return results
# Example: Benchmark for simple Hamiltonian
hamiltonian = SparsePauliOp(['ZZ', 'XI', 'IX'], coeffs=[1.0, -0.5, -0.5])
ansatz = RealAmplitudes(num_qubits=2, reps=2)
optimizers = {
'SLSQP': SLSQP(maxiter=100),
'COBYLA': COBYLA(maxiter=100),
'SPSA': SPSA(maxiter=100)
}
benchmark_results = benchmark_vqe_optimizers(hamiltonian, ansatz, optimizers, trials=3)from qiskit import QuantumCircuit
from qiskit.providers.aer import AerSimulator
import numpy as np
# Problem: Simulating too many qubits
def bad_simulation():
# DON'T DO THIS - will use ~2^25 * 16 bytes = 512 MB per state vector
qc = QuantumCircuit(25)
for i in range(25):
qc.h(i)
# This will be very slow or crash
# simulator = AerSimulator(method='statevector')
# result = simulator.run(qc).result()
# Solution 1: Use sampling instead of statevector
def good_simulation_sampling():
qc = QuantumCircuit(25, 25)
for i in range(25):
qc.h(i)
qc.measure_all()
# Much more efficient - doesn't store full state vector
simulator = AerSimulator(method='automatic') # Chooses best method
result = simulator.run(qc, shots=1000).result()
counts = result.get_counts()
return counts
# Solution 2: Use Matrix Product State for certain circuits
def good_simulation_mps():
qc = QuantumCircuit(50) # Can handle more qubits!
# MPS works well for circuits with limited entanglement
for i in range(49):
qc.h(i)
qc.cx(i, i+1) # Nearest-neighbor only
simulator = AerSimulator(method='matrix_product_state')
qc.measure_all()
result = simulator.run(qc, shots=1000).result()
return result.get_counts()
# Solution 3: Reduce circuit size
def good_simulation_reduced():
# Use fewer qubits or simpler circuits
qc = QuantumCircuit(10) # More manageable
for i in range(10):
qc.h(i)
simulator = AerSimulator()
qc.measure_all()
result = simulator.run(qc, shots=1000).result()
return result.get_counts()
# Test solutions
counts = good_simulation_sampling()
print(f"Sampling method: {len(counts)} unique outcomes")from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP, COBYLA
from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Estimator
from qiskit.quantum_info import SparsePauliOp
import numpy as np
def robust_vqe(hamiltonian, n_qubits, max_attempts=5):
"""
VQE with multiple restart attempts and parameter initialization.
Args:
hamiltonian: Problem Hamiltonian
n_qubits: Number of qubits
max_attempts: Maximum restart attempts
"""
best_result = None
best_energy = float('inf')
for attempt in range(max_attempts):
print(f"\nAttempt {attempt + 1}/{max_attempts}")
# Create fresh ansatz
ansatz = RealAmplitudes(num_qubits=n_qubits, reps=2)
# Initialize parameters randomly (but bounded)
initial_point = np.random.uniform(-np.pi, np.pi, ansatz.num_parameters)
# Try different optimizers
if attempt < max_attempts // 2:
optimizer = COBYLA(maxiter=200)
else:
optimizer = SLSQP(maxiter=200)
estimator = Estimator()
vqe = VQE(estimator, ansatz, optimizer, initial_point=initial_point)
try:
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(f" Energy: {result.eigenvalue:.6f}")
print(f" Evaluations: {result.cost_function_evals}")
if result.eigenvalue < best_energy:
best_energy = result.eigenvalue
best_result = result
print(f" ✓ New best energy!")
except Exception as e:
print(f" ✗ Failed: {e}")
continue
if best_result is None:
raise RuntimeError("All VQE attempts failed")
print(f"\nBest energy found: {best_energy:.6f}")
return best_result
# Example usage
hamiltonian = SparsePauliOp(['ZZ', 'XI', 'IX'], coeffs=[1.0, -0.5, -0.5])
result = robust_vqe(hamiltonian, n_qubits=2, max_attempts=3)