BoltzmannEntropy
commited on
Commit
·
41e6c53
1
Parent(s):
334036d
Co
Browse files- Dockerfile +1 -1
- app.py +48 -38
Dockerfile
CHANGED
@@ -85,7 +85,7 @@ COPY --chown=user:user app.py .
|
|
85 |
# COPY --chown=user:user test_images /home/user/app/test_images
|
86 |
|
87 |
ENV PYTHONUNBUFFERED=1 GRADIO_ALLOW_FLAGGING=never GRADIO_NUM_PORTS=1 GRADIO_SERVER_NAME=0.0.0.0 GRADIO_SERVER_PORT=7860 SYSTEM=spaces
|
88 |
-
RUN python3 -m pip install pennylane sympy pennylane-qiskit duckdb
|
89 |
WORKDIR $HOME/app
|
90 |
|
91 |
EXPOSE 8097 7842 8501 8000 6666 7860
|
|
|
85 |
# COPY --chown=user:user test_images /home/user/app/test_images
|
86 |
|
87 |
ENV PYTHONUNBUFFERED=1 GRADIO_ALLOW_FLAGGING=never GRADIO_NUM_PORTS=1 GRADIO_SERVER_NAME=0.0.0.0 GRADIO_SERVER_PORT=7860 SYSTEM=spaces
|
88 |
+
RUN python3 -m pip install pennylane sympy pennylane-qiskit duckdb qutip qutip-qip
|
89 |
WORKDIR $HOME/app
|
90 |
|
91 |
EXPOSE 8097 7842 8501 8000 6666 7860
|
app.py
CHANGED
@@ -10,33 +10,20 @@ import matplotlib.pyplot as plt
|
|
10 |
from PIL import Image
|
11 |
import pennylane as qml
|
12 |
import base64
|
13 |
-
|
14 |
-
from numpy import pi
|
15 |
-
import numpy as np
|
16 |
from qutip import *
|
17 |
from qutip.qip.operations import *
|
18 |
from qutip.qip.circuit import QubitCircuit, Gate
|
|
|
|
|
19 |
|
20 |
-
# Define a device
|
21 |
dev = qml.device('default.qubit', wires=10)
|
22 |
|
23 |
-
def plot_qutip_circuit():
|
24 |
-
q = QubitCircuit(2, reverse_states=False)
|
25 |
-
q.add_gate("CNOT", controls=[0], targets=[1])
|
26 |
-
|
27 |
-
# Display the circuit as an image
|
28 |
-
q.png # Generates and renders the circuit diagram
|
29 |
-
|
30 |
-
return q
|
31 |
-
|
32 |
-
|
33 |
# Hugging Face and DuckDB function placeholders
|
34 |
def store_in_hf_dataset(data):
|
35 |
-
# Implement storing data in the Hugging Face dataset
|
36 |
pass
|
37 |
|
38 |
def load_from_hf_dataset():
|
39 |
-
# Implement loading data from the Hugging Face dataset
|
40 |
return []
|
41 |
|
42 |
# Function to buffer the plot and return as PIL image
|
@@ -52,6 +39,13 @@ def pil_image_to_bytes(image):
|
|
52 |
image.save(img_byte_arr, format='PNG')
|
53 |
return img_byte_arr.getvalue()
|
54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
# Function to generate a random Hamiltonian
|
56 |
def generate_random_hamiltonian(num_qubits):
|
57 |
terms = []
|
@@ -88,20 +82,24 @@ def hamiltonian_to_qasm(hamiltonian, num_qubits):
|
|
88 |
|
89 |
return qasm_code
|
90 |
|
91 |
-
# Function
|
92 |
-
def
|
93 |
-
|
94 |
-
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
103 |
|
104 |
-
return
|
105 |
|
106 |
# Store data in DuckDB
|
107 |
def store_in_duckdb(data, db_file='quantum_hamiltonians.duckdb'):
|
@@ -120,13 +118,7 @@ def store_in_duckdb(data, db_file='quantum_hamiltonians.duckdb'):
|
|
120 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", data)
|
121 |
conn.close()
|
122 |
|
123 |
-
#
|
124 |
-
def encode_image_from_blob(blob):
|
125 |
-
img_buffer = io.BytesIO(blob)
|
126 |
-
image = Image.open(img_buffer)
|
127 |
-
img_str = base64.b64encode(img_buffer.getvalue()).decode("utf-8")
|
128 |
-
return f'<img src="data:image/png;base64,{img_str}" style="max-width:500px;"/>'
|
129 |
-
|
130 |
def load_from_duckdb(db_file='quantum_hamiltonians.duckdb'):
|
131 |
conn = duckdb.connect(database=db_file)
|
132 |
df = conn.execute("SELECT * FROM hamiltonians").df()
|
@@ -185,9 +177,11 @@ def generate_hamiltonians(num_hamiltonians, selected_qubits, selected_order, wri
|
|
185 |
qasm_code = hamiltonian_to_qasm(hamiltonian, num_qubits)
|
186 |
trotter_code = trotter_decomposition(hamiltonian, order)
|
187 |
|
188 |
-
#
|
189 |
-
|
190 |
-
|
|
|
|
|
191 |
circuit_plot_image = buffer_plot_and_get(fig)
|
192 |
circuit_plot_bytes = pil_image_to_bytes(circuit_plot_image)
|
193 |
|
@@ -209,6 +203,22 @@ def load_results(load_from_hf, load_from_duckdb1):
|
|
209 |
if load_from_duckdb1:
|
210 |
return load_from_duckdb()
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
# Gradio app
|
213 |
with gr.Blocks() as app:
|
214 |
gr.Markdown("# Quantum Hamiltonian Generator")
|
|
|
10 |
from PIL import Image
|
11 |
import pennylane as qml
|
12 |
import base64
|
|
|
|
|
|
|
13 |
from qutip import *
|
14 |
from qutip.qip.operations import *
|
15 |
from qutip.qip.circuit import QubitCircuit, Gate
|
16 |
+
import pennylane as qml
|
17 |
+
from math import pi
|
18 |
|
19 |
+
# Define a Pennylane device
|
20 |
dev = qml.device('default.qubit', wires=10)
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
# Hugging Face and DuckDB function placeholders
|
23 |
def store_in_hf_dataset(data):
|
|
|
24 |
pass
|
25 |
|
26 |
def load_from_hf_dataset():
|
|
|
27 |
return []
|
28 |
|
29 |
# Function to buffer the plot and return as PIL image
|
|
|
39 |
image.save(img_byte_arr, format='PNG')
|
40 |
return img_byte_arr.getvalue()
|
41 |
|
42 |
+
# Encode the image in base64 to display in HTML
|
43 |
+
def encode_image_from_blob(blob):
|
44 |
+
img_buffer = io.BytesIO(blob)
|
45 |
+
image = Image.open(img_buffer)
|
46 |
+
img_str = base64.b64encode(img_buffer.getvalue()).decode("utf-8")
|
47 |
+
return f'<img src="data:image/png;base64,{img_str}" style="max-width:500px;"/>'
|
48 |
+
|
49 |
# Function to generate a random Hamiltonian
|
50 |
def generate_random_hamiltonian(num_qubits):
|
51 |
terms = []
|
|
|
82 |
|
83 |
return qasm_code
|
84 |
|
85 |
+
# Function to parse QASM code and create Pennylane circuit
|
86 |
+
def qasm_to_pennylane(qasm_code):
|
87 |
+
qasm_lines = qasm_code.split("\n")
|
88 |
+
num_qubits = int(qasm_lines[2].split('[')[1].split(']')[0]) # Extract number of qubits from QASM
|
89 |
|
90 |
+
@qml.qnode(dev)
|
91 |
+
def circuit():
|
92 |
+
for line in qasm_lines:
|
93 |
+
if "x" in line:
|
94 |
+
qml.PauliX(int(line.split('q[')[1].split(']')[0]))
|
95 |
+
elif "rz" in line:
|
96 |
+
angle = float(line.split('(')[1].split(')')[0])
|
97 |
+
qml.RZ(angle, int(line.split('q[')[1].split(']')[0]))
|
98 |
+
elif "ry" in line:
|
99 |
+
qml.RY(pi / 2, int(line.split('q[')[1].split(']')[0]))
|
100 |
+
return qml.state()
|
101 |
|
102 |
+
return circuit
|
103 |
|
104 |
# Store data in DuckDB
|
105 |
def store_in_duckdb(data, db_file='quantum_hamiltonians.duckdb'):
|
|
|
118 |
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", data)
|
119 |
conn.close()
|
120 |
|
121 |
+
# Function to load results from DuckDB
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
def load_from_duckdb(db_file='quantum_hamiltonians.duckdb'):
|
123 |
conn = duckdb.connect(database=db_file)
|
124 |
df = conn.execute("SELECT * FROM hamiltonians").df()
|
|
|
177 |
qasm_code = hamiltonian_to_qasm(hamiltonian, num_qubits)
|
178 |
trotter_code = trotter_decomposition(hamiltonian, order)
|
179 |
|
180 |
+
# Generate Pennylane circuit from QASM code
|
181 |
+
circuit = qasm_to_pennylane(qasm_code)
|
182 |
+
|
183 |
+
# Draw the Pennylane circuit and save as an image
|
184 |
+
fig, ax = qml.draw_mpl(circuit)()
|
185 |
circuit_plot_image = buffer_plot_and_get(fig)
|
186 |
circuit_plot_bytes = pil_image_to_bytes(circuit_plot_image)
|
187 |
|
|
|
203 |
if load_from_duckdb1:
|
204 |
return load_from_duckdb()
|
205 |
|
206 |
+
# Function for Trotter decomposition
|
207 |
+
def trotter_decomposition(hamiltonian, order):
|
208 |
+
terms = hamiltonian.split(" + ")
|
209 |
+
trotter_steps = []
|
210 |
+
|
211 |
+
for term in terms:
|
212 |
+
coeff, *pauli_ops = term.split(" * ")
|
213 |
+
coeff = float(coeff)
|
214 |
+
for _ in range(order):
|
215 |
+
trotter_steps.append(f"exp({coeff / order}) * ({' * '.join(pauli_ops)})")
|
216 |
+
for _ in range(order):
|
217 |
+
trotter_steps.append(f"exp({-coeff / order}) * ({' * '.join(pauli_ops)})")
|
218 |
+
|
219 |
+
return " + ".join(trotter_steps)
|
220 |
+
|
221 |
+
|
222 |
# Gradio app
|
223 |
with gr.Blocks() as app:
|
224 |
gr.Markdown("# Quantum Hamiltonian Generator")
|