File size: 4,867 Bytes
7c5acc4
 
c9c6353
 
 
 
e983e5c
 
 
7c5acc4
 
c9c6353
7c5acc4
8c55141
7c5acc4
 
 
 
 
 
 
 
c9c6353
e983e5c
7c5acc4
e983e5c
7c5acc4
c9c6353
7c5acc4
 
 
 
 
 
 
 
 
 
 
 
c9c6353
7c5acc4
 
 
 
 
 
 
c9c6353
7c5acc4
 
c9c6353
e983e5c
7c5acc4
e983e5c
7c5acc4
c9c6353
7c5acc4
 
 
 
 
 
 
 
 
 
c9c6353
e983e5c
 
8c55141
7c5acc4
e983e5c
 
 
8c55141
7c5acc4
e983e5c
7c5acc4
c9c6353
 
e983e5c
7c5acc4
e983e5c
7c5acc4
 
 
 
8c55141
7c5acc4
 
 
 
 
 
 
 
 
 
 
 
 
e983e5c
7c5acc4
 
 
 
 
 
 
 
 
 
 
 
 
 
c9c6353
 
 
7c5acc4
 
 
8c55141
e983e5c
7c5acc4
e983e5c
7c5acc4
 
 
 
 
 
 
 
 
 
 
 
e983e5c
8c55141
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# ===== Ultimate Quantum Chemistry Platform (Starter) =====
# Python 3.11 + Qiskit stable + Gradio + Plotly
import numpy as np
import plotly.graph_objects as go
import gradio as gr

from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.problems import ElectronicStructureProblem
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit.algorithms.minimum_eigensolvers import VQE
from qiskit.algorithms.optimizers import COBYLA
from qiskit.circuit.library import TwoLocal
from qiskit.primitives import Estimator  # stable Qiskit 1.12

# ----------------------------
# Molecules Library
# ----------------------------
molecules = {
    "H2": {"atoms": ["H", "H"], "coords": [(0,0,0), (0,0,0.74)]},
    "LiH": {"atoms": ["Li", "H"], "coords": [(0,0,0), (0,0,1.6)]},
    "BeH2": {"atoms": ["Be","H","H"], "coords": [(0,0,0), (0,0,1.3), (0,0,-1.3)]}
}

# ----------------------------
# Quantum ground state energy
# ----------------------------
def compute_ground_state_energy(mol_name, bond_length):
    bond_length = float(bond_length)
    
    if mol_name == "H2":
        atom_str = f"H 0 0 0; H 0 0 {bond_length}"
    elif mol_name == "LiH":
        atom_str = f"Li 0 0 0; H 0 0 {bond_length}"
    elif mol_name == "BeH2":
        # symmetrically along z-axis
        atom_str = f"Be 0 0 0; H 0 0 {bond_length}; H 0 0 {-bond_length}"
    else:
        raise ValueError("Molecule not supported")
    
    driver = PySCFDriver(atom=atom_str, basis="sto3g")
    problem = ElectronicStructureProblem(driver)
    hamiltonian = problem.second_q_ops()[0]
    
    qubit_op = JordanWignerMapper().map(hamiltonian)
    
    ansatz = TwoLocal(qubit_op.num_qubits, "ry", "cz", reps=2)
    vqe = VQE(estimator=Estimator(), ansatz=ansatz, optimizer=COBYLA(maxiter=80))
    
    result = vqe.compute_minimum_eigenvalue(qubit_op)
    energy = result.eigenvalue.real
    return energy

# ----------------------------
# 3D molecule plot
# ----------------------------
def molecule_3d_plot(mol_name, bond_length):
    bond_length = float(bond_length)
    if mol_name == "H2":
        coords = [(0,0,0),(0,0,bond_length)]
    elif mol_name == "LiH":
        coords = [(0,0,0),(0,0,bond_length)]
    elif mol_name == "BeH2":
        coords = [(0,0,0),(0,0,bond_length),(0,0,-bond_length)]
    else:
        coords = []
    
    x, y, z = zip(*coords)
    fig = go.Figure()
    fig.add_trace(go.Scatter3d(
        x=x, y=y, z=z,
        mode="markers",
        marker=dict(size=8, color="red")
    ))
    fig.add_trace(go.Scatter3d(
        x=x, y=y, z=z,
        mode="lines",
        line=dict(color="blue", width=5)
    ))
    fig.update_layout(scene=dict(aspectmode="data"))
    return fig

# ----------------------------
# Energy curve precompute (for 0.4 - 2.0 Å)
# ----------------------------
bond_grid = np.linspace(0.4, 2.0, 12)
energy_curves = {}
for mol in molecules:
    energy_curves[mol] = [compute_ground_state_energy(mol, bl) for bl in bond_grid]

# ----------------------------
# Update UI
# ----------------------------
def update_ui(mol_name, bond_length):
    bond_length = float(bond_length)
    energy = compute_ground_state_energy(mol_name, bond_length)
    mol_fig = molecule_3d_plot(mol_name, bond_length)
    
    curve_fig = go.Figure()
    curve_fig.add_trace(go.Scatter(
        x=bond_grid, y=energy_curves[mol_name],
        mode="lines+markers",
        name="Energy Curve"
    ))
    curve_fig.add_trace(go.Scatter(
        x=[bond_length], y=[energy],
        mode="markers",
        marker=dict(size=12, color="green"),
        name="Current Energy"
    ))
    min_idx = int(np.argmin(energy_curves[mol_name]))
    curve_fig.add_trace(go.Scatter(
        x=[bond_grid[min_idx]], y=[energy_curves[mol_name][min_idx]],
        mode="markers",
        marker=dict(size=14, color="orange"),
        name="Equilibrium"
    ))
    curve_fig.update_layout(
        xaxis_title="Bond Length (Å)",
        yaxis_title="Energy (Hartree)"
    )
    
    text = f"Ground state energy: {energy:.6f} Hartree\nEquilibrium bond length ≈ {bond_grid[min_idx]:.2f} Å"
    return text, mol_fig, curve_fig

# ----------------------------
# Gradio App
# ----------------------------
with gr.Blocks() as demo:
    gr.Markdown("# 🧬 Ultimate Quantum Chemistry Platform")
    
    mol_dropdown = gr.Dropdown(list(molecules.keys()), value="H2", label="Select Molecule")
    bond_slider = gr.Slider(0.4, 2.0, value=0.74, step=0.01, label="Bond Length (Å)")
    
    energy_box = gr.Textbox(label="Energy", lines=2)
    mol_plot = gr.Plot(label="3D Molecule")
    curve_plot = gr.Plot(label="Energy Curve")
    
    mol_dropdown.change(update_ui, [mol_dropdown, bond_slider], [energy_box, mol_plot, curve_plot])
    bond_slider.change(update_ui, [mol_dropdown, bond_slider], [energy_box, mol_plot, curve_plot])

demo.launch()