|
| 1 | + |
| 2 | +Uses a random 8×8 Hermitian matrix (for 3 qubits) |
| 3 | +Decomposes it into Pauli terms |
| 4 | +Runs VQE using a TwoLocal ansatz |
| 5 | +Uses the statevector simulator |
| 6 | +Visualizes:
|
| 7 | +The convergence of VQE (energy vs iteration) |
| 8 | +The circuit structure of the ansatz |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +import numpy as np |
| 15 | +import matplotlib.pyplot as plt |
| 16 | +from qiskit import Aer |
| 17 | +from qiskit.opflow import PauliSumOp, MatrixOp |
| 18 | +from qiskit.quantum_info import Operator |
| 19 | +from qiskit.circuit.library import TwoLocal |
| 20 | +from qiskit.algorithms import VQE |
| 21 | +from qiskit.algorithms.optimizers import COBYLA |
| 22 | +from qiskit.utils import QuantumInstance, algorithm_globals |
| 23 | + |
| 24 | +# --- Parameters --- |
| 25 | +n_qubits = 3 |
| 26 | +dim = 2**n_qubits |
| 27 | +np.random.seed(42) |
| 28 | +algorithm_globals.random_seed = 42 |
| 29 | + |
| 30 | +# --- Generate a random Hermitian matrix --- |
| 31 | +A = np.random.randn(dim, dim) + 1j * np.random.randn(dim, dim) |
| 32 | +H_np = (A + A.conj().T) / 2 |
| 33 | + |
| 34 | +# --- Convert to Pauli decomposition --- |
| 35 | +H_op = MatrixOp(H_np) |
| 36 | +H_pauli = PauliSumOp.from_operator(Operator(H_op)) |
| 37 | + |
| 38 | +# --- Exact eigenvalues for comparison --- |
| 39 | +eigvals = np.linalg.eigvalsh(H_np) |
| 40 | +exact_energy = np.min(eigvals) |
| 41 | + |
| 42 | +# --- Ansatz circuit --- |
| 43 | +ansatz = TwoLocal(n_qubits, rotation_blocks=['ry', 'rz'], |
| 44 | + entanglement_blocks='cz', entanglement='full', reps=2) |
| 45 | +print("\nAnsatz circuit:") |
| 46 | +print(ansatz.decompose().draw()) |
| 47 | + |
| 48 | +# --- Track convergence --- |
| 49 | +energy_log = [] |
| 50 | + |
| 51 | +def store_intermediate_result(eval_count, params, energy, stddev): |
| 52 | + energy_log.append(energy) |
| 53 | + |
| 54 | +# --- Optimizer and simulator --- |
| 55 | +optimizer = COBYLA(maxiter=200) |
| 56 | +backend = Aer.get_backend('aer_simulator_statevector') |
| 57 | +quantum_instance = QuantumInstance(backend) |
| 58 | + |
| 59 | +# --- Run VQE --- |
| 60 | +vqe = VQE(ansatz=ansatz, |
| 61 | + optimizer=optimizer, |
| 62 | + quantum_instance=quantum_instance, |
| 63 | + callback=store_intermediate_result) |
| 64 | + |
| 65 | +result = vqe.compute_minimum_eigenvalue(operator=H_pauli) |
| 66 | +vqe_energy = np.real(result.eigenvalue) |
| 67 | + |
| 68 | +# --- Output results --- |
| 69 | +print("\n=== Results ===") |
| 70 | +print(f"Exact ground energy: {exact_energy:.6f}") |
| 71 | +print(f"VQE estimated ground energy: {vqe_energy:.6f}") |
| 72 | +print("Full spectrum:", np.round(eigvals, 6)) |
| 73 | + |
| 74 | +# --- Plot convergence --- |
| 75 | +plt.figure(figsize=(6,4)) |
| 76 | +plt.plot(energy_log, marker='o') |
| 77 | +plt.xlabel("VQE iteration") |
| 78 | +plt.ylabel("Energy estimate") |
| 79 | +plt.title("VQE Convergence on Random 8×8 Hermitian Hamiltonian") |
| 80 | +plt.grid(True) |
| 81 | +plt.tight_layout() |
| 82 | +plt.show() |
| 83 | + |
| 84 | + |
| 85 | +Random Hermitian matrix: size 8 \times 8 → 3 qubits |
| 86 | +Pauli decomposition: PauliSumOp.from_operator() converts the dense matrix to a sum of Pauli strings |
| 87 | +TwoLocal ansatz: ry, rz, and cz with 2 layers |
| 88 | +Callback tracking: logs energy per iteration |
| 89 | +Plots:
|
| 90 | +Convergence of VQE |
| 91 | +Circuit diagram of the ansatz |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | + |
0 commit comments