Skip to content

Commit 876a6c6

Browse files
committed
added codes
1 parent 0817250 commit 876a6c6

File tree

4 files changed

+370
-0
lines changed

4 files changed

+370
-0
lines changed

doc/Programs/VQEcodes/h2.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
4+
# Qiskit and Qiskit Nature imports
5+
from qiskit import Aer
6+
from qiskit.algorithms import VQE
7+
from qiskit.algorithms.optimizers import L_BFGS_B
8+
from qiskit.circuit.library import TwoLocal
9+
from qiskit_nature.drivers import UnitsType, PySCFDriver
10+
from qiskit_nature.problems.second_quantization.electronic import ElectronicStructureProblem
11+
from qiskit_nature.mappers.second_quantization import ParityMapper
12+
from qiskit_nature.converters.second_quantization import QubitConverter
13+
from qiskit_nature.circuit.library import HartreeFock
14+
15+
# Define the range of H-H distances (in Angstrom)
16+
bond_distances = np.arange(0.5, 2.6, 0.1) # 0.5 Å to 2.5 Å in 0.1 Å increments
17+
energies = [] # to store ground state energy for each distance
18+
19+
# Loop over distances and compute ground-state energy via VQE
20+
for dist in bond_distances:
21+
# 1. Define H2 molecule at the given bond distance
22+
molecule = f"H 0 0 0; H 0 0 {dist}" # two H atoms on z-axis separated by 'dist'
23+
driver = PySCFDriver(atom=molecule, unit=UnitsType.ANGSTROM, basis="sto3g", charge=0, spin=0)
24+
problem = ElectronicStructureProblem(driver)
25+
26+
# 2. Build second-quantized Hamiltonian
27+
second_q_ops = problem.second_q_ops()
28+
main_op = second_q_ops["ElectronicEnergy"] # electronic Hamiltonian (no nuclear repulsion added yet)
29+
30+
# 3. Prepare qubit mapping (Parity) with two-qubit reduction for spin symmetry
31+
particle_number = problem.grouped_property_transformed.get_property("ParticleNumber")
32+
num_particles = (particle_number.num_alpha, particle_number.num_beta)
33+
num_spin_orbitals = particle_number.num_spin_orbitals
34+
mapper = ParityMapper()
35+
converter = QubitConverter(mapper=mapper, two_qubit_reduction=True)
36+
qubit_op = converter.convert(main_op, num_particles=num_particles)
37+
38+
# 4. Setup the VQE algorithm (ansatz, initial state, optimizer, backend)
39+
# Hartree-Fock initial state
40+
init_state = HartreeFock(num_spin_orbitals, num_particles, converter)
41+
# TwoLocal ansatz with RY and RZ rotations and CZ entanglement, with HF initial state
42+
ansatz = TwoLocal(qubit_op.num_qubits, rotation_blocks=['ry', 'rz'], entanglement_blocks='cz')
43+
ansatz = ansatz.compose(init_state, front=True) # prepend HF state
44+
45+
46+
optimizer = L_BFGS_B() # optimizer for classical parameter updates
47+
backend = Aer.get_backend('aer_simulator_statevector') # statevector simulator backend
48+
vqe = VQE(ansatz, optimizer=optimizer, quantum_instance=backend)
49+
50+
# 5. Run VQE to obtain the minimum eigenvalue (ground state energy)
51+
result = vqe.compute_minimum_eigenvalue(qubit_op)
52+
# Add the nuclear repulsion energy to get total molecular energy
53+
electronic_result = problem.interpret(result)
54+
energy_hartree = electronic_result.total_energies[0] # ground state energy in Hartree
55+
energies.append(energy_hartree)
56+
print(f"Distance = {dist:.2f} Å, Ground state energy = {energy_hartree:.6f} Hartree")
57+
58+
# 6. Plot the ground state energy as a function of bond length
59+
plt.figure(figsize=(6,4))
60+
plt.plot(bond_distances, energies, marker='o', color='orange', label='Ground State Energy')
61+
plt.xlabel('H-H Bond Length (Å)')
62+
plt.ylabel('Energy (Hartree)')
63+
plt.title('H$_2$ Ground State Energy vs Bond Length (STO-3G)')
64+
plt.legend()
65+
plt.grid(True)
66+
plt.show()

doc/Programs/VQEcodes/isingvqe.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import numpy as np
2+
3+
# Define 1-qubit Pauli matrices
4+
I = np.array([[1,0],[0,1]], dtype=complex)
5+
X = np.array([[0,1],[1,0]], dtype=complex)
6+
Y = np.array([[0,-1j],[1j,0]], dtype=complex)
7+
Z = np.array([[1,0],[0,-1]], dtype=complex)
8+
9+
def get_neighbors(L):
10+
"""List of nearest-neighbor pairs (i,j) for an LxL square lattice (open boundaries)."""
11+
neighbors = []
12+
for i in range(L):
13+
for j in range(L):
14+
idx = i*L + j
15+
if j < L-1:
16+
neighbors.append((idx, idx+1))
17+
if i < L-1:
18+
neighbors.append((idx, idx+L))
19+
return neighbors
20+
21+
def build_ising_hamiltonian(L, J, h):
22+
"""Construct the 2^N x 2^N transverse-field Ising Hamiltonian for LxL spins."""
23+
N = L*L
24+
dim = 2**N
25+
H = np.zeros((dim, dim), dtype=complex)
26+
for (i,j) in get_neighbors(L):
27+
# Build tensor-product for -J * Z_i Z_j
28+
ops = [Z if k==i or k==j else I for k in range(N)]
29+
term = ops[0]
30+
for op in ops[1:]:
31+
term = np.kron(term, op)
32+
H += -J * term
33+
for i in range(N):
34+
# -h * X_i term
35+
ops = [X if k==i else I for k in range(N)]
36+
term = ops[0]
37+
for op in ops[1:]:
38+
term = np.kron(term, op)
39+
H += -h * term
40+
return H
41+
42+
def build_heisenberg_hamiltonian(L, J):
43+
"""Construct the 2^N x 2^N isotropic Heisenberg Hamiltonian for LxL spins."""
44+
N = L*L
45+
dim = 2**N
46+
H = np.zeros((dim, dim), dtype=complex)
47+
for (i,j) in get_neighbors(L):
48+
# Add J*(X_iX_j + Y_iY_j + Z_iZ_j)
49+
for P in (X, Y, Z):
50+
ops = [P if k==i or k==j else I for k in range(N)]
51+
term = ops[0]
52+
for op in ops[1:]:
53+
term = np.kron(term, op)
54+
H += J * term
55+
return H
56+
57+
def apply_RY(state, qubit, theta):
58+
"""Apply a single-qubit RY(theta) rotation on the specified qubit of the state."""
59+
N = int(np.log2(len(state)))
60+
new_state = np.zeros_like(state, dtype=complex)
61+
cos = np.cos(theta/2); sin = np.sin(theta/2)
62+
# Loop over basis states in binary; if qubit bit is 0, mix with its partner state
63+
for b in range(len(state)):
64+
if ((b >> qubit) & 1) == 0:
65+
partner = b | (1 << qubit) # flip that qubit bit
66+
new_state[b] += cos * state[b] - sin * state[partner]
67+
new_state[partner] += sin * state[b] + cos * state[partner]
68+
return new_state
69+
70+
def apply_CNOT(state, control, target):
71+
"""Apply a CNOT gate (control -> target) on the specified qubits of the state."""
72+
new_state = np.zeros_like(state, dtype=complex)
73+
for b in range(len(state)):
74+
# If control bit is 1, flip the target bit
75+
if ((b >> control) & 1) == 1:
76+
b_new = b ^ (1 << target)
77+
else:
78+
b_new = b
79+
new_state[b_new] += state[b]
80+
return new_state
81+
82+
def ansatz_state(params, L):
83+
"""Construct the variational ansatz state for parameters `params` on an LxL lattice."""
84+
N = L*L
85+
psi = np.zeros(2**N, dtype=complex)
86+
psi[0] = 1.0 # start in |00...0>
87+
# Apply RY on each qubit with corresponding parameter
88+
for i, theta in enumerate(params):
89+
psi = apply_RY(psi, i, theta)
90+
# Apply CNOT entanglers on each neighbor pair
91+
for (i,j) in get_neighbors(L):
92+
psi = apply_CNOT(psi, i, j)
93+
return psi
94+
95+
import scipy.optimize as opt
96+
97+
def energy_expectation(params, H, L):
98+
"""Compute expectation <psi(params)|H|psi(params)> for Hamiltonian H."""
99+
psi = ansatz_state(params, L)
100+
# <psi|H|psi> using complex conjugate transpose
101+
return np.vdot(psi, H.dot(psi)).real
102+
103+
# Example: find ground energy of 2x2 transverse Ising (J=1.0, h=0.5)
104+
L = 2
105+
J = 1.0
106+
h = 0.5
107+
H_ising = build_ising_hamiltonian(L, J, h)
108+
# Initial random parameters
109+
np.random.seed(0)
110+
init_params = 0.1 * np.random.randn(L*L)
111+
# Optimize parameters to minimize energy
112+
result = opt.minimize(lambda th: energy_expectation(th, H_ising, L),
113+
init_params, method='COBYLA')
114+
estimated_energy = result.fun
115+
116+
117+
118+
import matplotlib.pyplot as plt
119+
120+
# Example: Vary h for 2x2 Ising, J=1.0
121+
hs = np.linspace(0.0, 2.0, 5)
122+
energies_vqe = []
123+
for h_val in hs:
124+
H2 = build_ising_hamiltonian(2, 1.0, h_val)
125+
res = opt.minimize(lambda th: energy_expectation(th, H2, 2),
126+
init_params, method='COBYLA')
127+
energies_vqe.append(res.fun)
128+
129+
plt.plot(hs, energies_vqe, marker='o')
130+
plt.xlabel('Transverse field h')
131+
plt.ylabel('Ground-state energy (VQE)')
132+
plt.title('2x2 Transverse-Field Ising (J=1)')
133+
plt.show()
134+

doc/Programs/VQEcodes/slides.pdf

182 KB
Binary file not shown.

0 commit comments

Comments
 (0)