A19grey commited on
Commit
e0fff0e
·
1 Parent(s): af9d37a

Added display of full circuit Hamiltonian and reworked position of tiles

Browse files
Files changed (2) hide show
  1. app.py +95 -38
  2. quantum_utils.py +17 -2
app.py CHANGED
@@ -69,7 +69,7 @@ for handler in logger.handlers:
69
  handler.setLevel(logging.DEBUG)
70
 
71
  def install_dependencies():
72
- """Install required packages from requirements.txt."""
73
  try:
74
  subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])
75
  print("Dependencies installed successfully")
@@ -77,6 +77,16 @@ def install_dependencies():
77
  print(f"Error installing dependencies: {e}")
78
  sys.exit(1)
79
 
 
 
 
 
 
 
 
 
 
 
80
  # Load molecule definitions
81
  def load_molecules():
82
  """Load molecule definitions from JSON file."""
@@ -87,15 +97,6 @@ def load_molecules():
87
  print(f"Error loading molecules.json: {e}", file=sys.stderr)
88
  return {}
89
 
90
- # Test if cudaq is already installed
91
- try:
92
- import cudaq
93
- print("CUDA-Q already installed, skipping dependency installation")
94
- except ImportError:
95
- print("CUDA-Q not found, installing dependencies...")
96
- # Run installation before any other imports
97
- install_dependencies()
98
-
99
  # Now import the rest of the modules
100
  import gradio as gr
101
  import numpy as np
@@ -182,11 +183,14 @@ def create_interface():
182
  Select a molecule below, adjust its parameters, and watch as the simulation computes the lowest
183
  possible energy state using quantum-inspired algorithms accelerated by NVIDIA GPUs.
184
 
 
 
185
  Inspired by the CUDA-Q VQE Example: https://nvidia.github.io/cuda-quantum/latest/applications/python/vqe_advanced.html
186
  """)
187
 
188
  state = gr.State({}) # Store current molecule data
189
 
 
190
  with gr.Row():
191
  with gr.Column(scale=1):
192
  # Molecule selection controls
@@ -195,7 +199,7 @@ def create_interface():
195
  value=list(molecules.keys())[0],
196
  label="Select Molecule",
197
  interactive=True,
198
- allow_custom_value=False # Prevent text input
199
  )
200
 
201
  # Get scale range from selected molecule
@@ -208,41 +212,91 @@ def create_interface():
208
  label="Scale Factor (1.0 = original size)",
209
  interactive=True
210
  )
211
-
212
- # Split into two buttons
213
- generate_ham_button = gr.Button("Generate Hamiltonian")
214
- run_vqe_button = gr.Button("Run VQE Simulation", interactive=False)
215
-
216
  with gr.Column(scale=1):
217
  # Molecule parameters display
218
  params_display = gr.HTML(
219
  label="Molecule Parameters",
220
  value=format_molecule_params(default_molecule)
221
  )
 
 
 
 
 
 
 
 
 
222
 
223
- # Simulation results box below controls
224
- with gr.Row():
225
- simulation_results = gr.HTML(
226
- label="Simulation Results",
227
- value="<div style='padding: 10px; background-color: #f5f5f5; border-radius: 5px;'>" +
228
- "Click 'Generate Hamiltonian' to start.</div>"
229
- )
230
-
231
- # Plots and visualization
232
  with gr.Row():
233
  with gr.Column(scale=1):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  convergence_plot = gr.Plot(
235
  label="VQE Convergence",
236
  show_label=True
237
  )
238
- with gr.Column(scale=1, min_width=600):
239
- molecule_viz = MolGallery3D(
240
- columns=1,
241
- height=600,
242
- label="3D Molecule Viewer",
243
- automatic_rotation=True
244
- )
245
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  def generate_hamiltonian(molecule_choice: str, scale_factor: float) -> tuple:
247
  """Generate Hamiltonian for the selected molecule."""
248
  try:
@@ -258,25 +312,28 @@ def create_interface():
258
 
259
  # Format Hamiltonian results
260
  hamiltonian_html = f"""
261
- <div style='padding: 10px; background-color: #f5f5f5; border-radius: 5px;'>
262
  <h3>Hamiltonian Generated:</h3>
263
  <ul style='list-style-type: none; padding-left: 0;'>
264
  <li><b>Number of Qubits:</b> {results['qubit_count']}</li>
265
  <li><b>Number of Electrons:</b> {results['electron_count']}</li>
266
- <li><b>Parameter Count:</b> {results['parameter_count']}</li>
267
  <li><b>Hamiltonian Terms:</b> {results['hamiltonian_terms']}</li>
 
268
  <li><b>Scale Factor:</b> {scale_factor:.2f}</li>
269
  </ul>
270
  <p><i>Ready to run VQE optimization.</i></p>
271
  </div>
272
  """
273
 
 
 
 
274
  # Enable the VQE button now that Hamiltonian is generated
275
- return hamiltonian_html, gr.update(interactive=True), None
276
 
277
  except Exception as e:
278
  error_msg = f"<div style='color: red;'>Error generating Hamiltonian:<br>{str(e)}</div>"
279
- return error_msg, gr.update(interactive=False), None
280
 
281
  def run_vqe_optimization(molecule_choice: str, scale_factor: float) -> tuple:
282
  """Run VQE optimization after Hamiltonian is generated."""
@@ -376,7 +433,7 @@ def create_interface():
376
  generate_ham_button.click(
377
  fn=generate_hamiltonian,
378
  inputs=[molecule_choice, scale_factor],
379
- outputs=[simulation_results, run_vqe_button, convergence_plot]
380
  )
381
 
382
  # Run VQE optimization when button is clicked
 
69
  handler.setLevel(logging.DEBUG)
70
 
71
  def install_dependencies():
72
+ print("""Install required packages from requirements.txt.""")
73
  try:
74
  subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])
75
  print("Dependencies installed successfully")
 
77
  print(f"Error installing dependencies: {e}")
78
  sys.exit(1)
79
 
80
+ # Test if cudaq is already installed
81
+ try:
82
+ import cudaq
83
+ print("CUDA-Q already installed, skipping dependency installation")
84
+ except ImportError:
85
+ print("CUDA-Q not found, installing dependencies...")
86
+ # Run installation before any other imports
87
+ install_dependencies()
88
+
89
+
90
  # Load molecule definitions
91
  def load_molecules():
92
  """Load molecule definitions from JSON file."""
 
97
  print(f"Error loading molecules.json: {e}", file=sys.stderr)
98
  return {}
99
 
 
 
 
 
 
 
 
 
 
100
  # Now import the rest of the modules
101
  import gradio as gr
102
  import numpy as np
 
183
  Select a molecule below, adjust its parameters, and watch as the simulation computes the lowest
184
  possible energy state using quantum-inspired algorithms accelerated by NVIDIA GPUs.
185
 
186
+ Even for small molecules, the needed quantum circuit can be quite large so for learning purposes we display it in all it's sacred glory.
187
+
188
  Inspired by the CUDA-Q VQE Example: https://nvidia.github.io/cuda-quantum/latest/applications/python/vqe_advanced.html
189
  """)
190
 
191
  state = gr.State({}) # Store current molecule data
192
 
193
+ # Top section: 3 columns
194
  with gr.Row():
195
  with gr.Column(scale=1):
196
  # Molecule selection controls
 
199
  value=list(molecules.keys())[0],
200
  label="Select Molecule",
201
  interactive=True,
202
+ allow_custom_value=False
203
  )
204
 
205
  # Get scale range from selected molecule
 
212
  label="Scale Factor (1.0 = original size)",
213
  interactive=True
214
  )
215
+
 
 
 
 
216
  with gr.Column(scale=1):
217
  # Molecule parameters display
218
  params_display = gr.HTML(
219
  label="Molecule Parameters",
220
  value=format_molecule_params(default_molecule)
221
  )
222
+
223
+ with gr.Column(scale=1):
224
+ # 3D Molecule Viewer
225
+ molecule_viz = MolGallery3D(
226
+ columns=1,
227
+ height=400, # Reduced height to match other elements
228
+ label="3D Molecule Viewer",
229
+ automatic_rotation=True
230
+ )
231
 
232
+ # Middle section: Buttons and results in 2 columns
 
 
 
 
 
 
 
 
233
  with gr.Row():
234
  with gr.Column(scale=1):
235
+ # Buttons side by side
236
+ with gr.Row():
237
+ generate_ham_button = gr.Button("Generate Hamiltonian")
238
+ run_vqe_button = gr.Button("Run VQE Simulation", interactive=False)
239
+
240
+ # Hamiltonian Information
241
+ simulation_results = gr.HTML(
242
+ label="Hamiltonian Information",
243
+ value="<div style='padding: 10px; background-color: #f5f5f5; border-radius: 5px; font-size: 0.8em;'>" +
244
+ "Click 'Generate Hamiltonian' to start.</div>"
245
+ )
246
+
247
+ with gr.Column(scale=1):
248
+ # VQE Convergence Plot
249
  convergence_plot = gr.Plot(
250
  label="VQE Convergence",
251
  show_label=True
252
  )
253
+
254
+ # Bottom section: Full width circuit visualization
255
+ circuit_latex_display = gr.Markdown(
256
+ label="Quantum Circuit Visualization",
257
+ value="Circuit will be displayed after generation.",
258
+ elem_classes="circuit-output"
259
+ )
260
+
261
+ # Add CSS styling
262
+ gr.Markdown("""
263
+ <style>
264
+ .circuit-output {
265
+ font-family: monospace;
266
+ font-size: 0.6em;
267
+ white-space: pre;
268
+ overflow-x: auto;
269
+ padding: 10px;
270
+ background-color: #f8f8f8;
271
+ width: 100%;
272
+ max-width: 100%;
273
+ box-sizing: border-box;
274
+ display: block;
275
+ }
276
+ .circuit-output pre {
277
+ margin: 0 auto;
278
+ background: none !important;
279
+ border: none !important;
280
+ padding: 0 !important;
281
+ width: 100%;
282
+ overflow-x: auto;
283
+ }
284
+ .circuit-output code {
285
+ background: none !important;
286
+ border: none !important;
287
+ padding: 0 !important;
288
+ }
289
+ .gradio-container .prose {
290
+ max-width: 100% !important;
291
+ width: 100% !important;
292
+ }
293
+ .markdown-text {
294
+ width: 100% !important;
295
+ max-width: none !important;
296
+ }
297
+ </style>
298
+ """)
299
+
300
  def generate_hamiltonian(molecule_choice: str, scale_factor: float) -> tuple:
301
  """Generate Hamiltonian for the selected molecule."""
302
  try:
 
312
 
313
  # Format Hamiltonian results
314
  hamiltonian_html = f"""
315
+ <div style='padding: 10px; background-color: #f5f5f5; border-radius: 5px; font-size: 0.8em;'>
316
  <h3>Hamiltonian Generated:</h3>
317
  <ul style='list-style-type: none; padding-left: 0;'>
318
  <li><b>Number of Qubits:</b> {results['qubit_count']}</li>
319
  <li><b>Number of Electrons:</b> {results['electron_count']}</li>
 
320
  <li><b>Hamiltonian Terms:</b> {results['hamiltonian_terms']}</li>
321
+ <li style='margin-top: 8px; color: #2a6f97;'><b>Quantum Circuit Parameters:</b> {results['parameter_count']} <i>(parameters needed to represent the system in quantum circuit form)</i></li>
322
  <li><b>Scale Factor:</b> {scale_factor:.2f}</li>
323
  </ul>
324
  <p><i>Ready to run VQE optimization.</i></p>
325
  </div>
326
  """
327
 
328
+ # Format circuit output with monospace preservation and escape special characters
329
+ circuit_latex = f"""<div class='circuit-output'><pre>{results.get('circuit_latex', 'Circuit visualization not available').replace('`', '&#96;')}</pre></div>"""
330
+
331
  # Enable the VQE button now that Hamiltonian is generated
332
+ return hamiltonian_html, circuit_latex, gr.update(interactive=True), None
333
 
334
  except Exception as e:
335
  error_msg = f"<div style='color: red;'>Error generating Hamiltonian:<br>{str(e)}</div>"
336
+ return error_msg, "Error generating circuit visualization", gr.update(interactive=False), None
337
 
338
  def run_vqe_optimization(molecule_choice: str, scale_factor: float) -> tuple:
339
  """Run VQE optimization after Hamiltonian is generated."""
 
433
  generate_ham_button.click(
434
  fn=generate_hamiltonian,
435
  inputs=[molecule_choice, scale_factor],
436
+ outputs=[simulation_results, circuit_latex_display, run_vqe_button, convergence_plot]
437
  )
438
 
439
  # Run VQE optimization when button is clicked
quantum_utils.py CHANGED
@@ -236,6 +236,7 @@ def generate_hamiltonian(molecule_data: Dict[str, Any],
236
  - 'electron_count': Number of electrons in the system
237
  - 'parameter_count': Number of UCCSD parameters needed
238
  - 'hamiltonian_terms': Number of terms in the Hamiltonian
 
239
  """
240
  logging.info(f"Generating Hamiltonian for {molecule_data['name']} with scale factor {scale_factor}")
241
 
@@ -267,12 +268,25 @@ def generate_hamiltonian(molecule_data: Dict[str, Any],
267
  parameter_count = cudaq.kernels.uccsd_num_parameters(electron_count, qubit_count)
268
  logging.info(f"Number of UCCSD parameters needed = {parameter_count}")
269
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  return {
271
  'hamiltonian': spin_hamiltonian,
272
  'qubit_count': qubit_count,
273
  'electron_count': electron_count,
274
  'parameter_count': parameter_count,
275
- 'hamiltonian_terms': term_count
 
276
  }
277
 
278
  @spaces.GPU
@@ -306,7 +320,8 @@ def run_vqe_simulation(molecule_data: Dict[str, Any],
306
  'hamiltonian_terms': ham_info['hamiltonian_terms'],
307
  'qubit_count': ham_info['qubit_count'],
308
  'electron_count': ham_info['electron_count'],
309
- 'message': "Hamiltonian generated successfully"
 
310
  }
311
 
312
  # Otherwise continue with VQE optimization
 
236
  - 'electron_count': Number of electrons in the system
237
  - 'parameter_count': Number of UCCSD parameters needed
238
  - 'hamiltonian_terms': Number of terms in the Hamiltonian
239
+ - 'circuit_latex': LaTeX representation of the quantum circuit
240
  """
241
  logging.info(f"Generating Hamiltonian for {molecule_data['name']} with scale factor {scale_factor}")
242
 
 
268
  parameter_count = cudaq.kernels.uccsd_num_parameters(electron_count, qubit_count)
269
  logging.info(f"Number of UCCSD parameters needed = {parameter_count}")
270
 
271
+ # Generate LaTeX representation of the circuit
272
+ try:
273
+ logging.info("Starting circuit LaTeX generation")
274
+ thetas_draw = np.random.normal(0, 1, parameter_count)
275
+ # Draw the circuit in fancy nice stuff
276
+ circuit_latex = cudaq.draw(kernel, qubit_count, electron_count, thetas_draw)
277
+ logging.info("Successfully generated circuit LaTeX representation")
278
+ logging.info(circuit_latex)
279
+ except Exception as e:
280
+ logging.error(f"Failed to generate circuit LaTeX: {str(e)}")
281
+ circuit_latex = "Error generating circuit visualization"
282
+
283
  return {
284
  'hamiltonian': spin_hamiltonian,
285
  'qubit_count': qubit_count,
286
  'electron_count': electron_count,
287
  'parameter_count': parameter_count,
288
+ 'hamiltonian_terms': term_count,
289
+ 'circuit_latex': circuit_latex
290
  }
291
 
292
  @spaces.GPU
 
320
  'hamiltonian_terms': ham_info['hamiltonian_terms'],
321
  'qubit_count': ham_info['qubit_count'],
322
  'electron_count': ham_info['electron_count'],
323
+ 'message': "Hamiltonian generated successfully",
324
+ 'circuit_latex': ham_info['circuit_latex']
325
  }
326
 
327
  # Otherwise continue with VQE optimization