Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instr #46

Merged
merged 13 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"args": [
"--debug"
],
"justMyCode": false
}
]
}
28 changes: 22 additions & 6 deletions app/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
from layouts.app_page_layout import sidebar_top, sidebar_bottom, content
from layouts.app_page_layout import (
sidebar_top,
sidebar_bottom,
content,
DEFAULT_ANSATZ,
DEFAULT_DATA_REUPLOAD,
DEFAULT_N_LAYERS,
DEFAULT_N_QUBITS,
DEFAULT_SEED,
)

import dash
import dash_bootstrap_components as dbc
from dash import Input, Output, html, callback, State
Expand Down Expand Up @@ -65,15 +75,21 @@ def on_preference_changed(
# Give a default data dict with 0 clicks if there's no data.
data = data or {}
data["number_qubits"] = (
max(min(number_qubits, 10), 0) if number_qubits is not None else None
max(min(number_qubits, 10), 0)
if number_qubits is not None
else DEFAULT_N_QUBITS
)
data["number_layers"] = (
max(min(number_layers, 10), 0) if number_layers is not None else None
max(min(number_layers, 10), 0)
if number_layers is not None
else DEFAULT_N_LAYERS
)
data["circuit_type"] = circuit_type if circuit_type is not None else DEFAULT_ANSATZ
data["data_reupload"] = (
data_reupload if data_reupload is not None else DEFAULT_DATA_REUPLOAD
)
data["circuit_type"] = circuit_type if circuit_type is not None else "No_Ansatz"
data["data_reupload"] = data_reupload
data["tffm"] = False # tffm
data["seed"] = max(min(seed, 999), 100)
data["seed"] = max(min(seed, 999), 1000) if seed is not None else DEFAULT_SEED

return data

Expand Down
2 changes: 1 addition & 1 deletion app/layouts/app_page_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
DEFAULT_N_LAYERS = 1
DEFAULT_SEED = 100
DEFAULT_DATA_REUPLOAD = True
DEFAULT_ANSATZ = "No Ansatz"
DEFAULT_ANSATZ = "No_Ansatz"

sidebar_top = [
dcc.Store(id="main-storage", storage_type="session"),
Expand Down
6 changes: 3 additions & 3 deletions app/layouts/training_page_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
)
import dash_bootstrap_components as dbc

DEFAULT_N_STEPS = 10
DEFAULT_N_FREQS = 3
DEFAULT_N_STEPS = 50
DEFAULT_N_FREQS = 4
DEFAULT_STEPSIZE = 0.01

layout = html.Div(
Expand Down Expand Up @@ -154,7 +154,7 @@
dbc.Input(
type="number",
min=1,
max=201,
max=801,
step=1,
value=DEFAULT_N_STEPS,
id="training-steps-numeric-input",
Expand Down
2 changes: 1 addition & 1 deletion app/pages/0-main-page.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

dash.register_page(__name__, name="Home", path="/")

from layouts.main_page_layout import layout # noqa
from layouts.main_page_layout import layout # noqa: E402
108 changes: 71 additions & 37 deletions app/pages/1-training.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from layouts.training_page_layout import layout # noqa
from utils.instructor import Instructor
from layouts.training_page_layout import layout # noqa: E402
from layouts.training_page_layout import (
DEFAULT_N_STEPS,
DEFAULT_N_FREQS,
Expand All @@ -9,8 +10,8 @@
DEFAULT_N_LAYERS,
DEFAULT_SEED,
DEFAULT_DATA_REUPLOAD,
DEFAULT_ANSATZ,
)
from utils.instructor import Instructor

import dash
import numpy as np
Expand All @@ -25,9 +26,24 @@

from typing import Dict, Any, List, Optional

import logging

log = logging.getLogger(__name__)

dash.register_page(__name__, name="Training")


instructor = Instructor(
DEFAULT_N_QUBITS,
DEFAULT_N_LAYERS,
n_freqs=DEFAULT_N_FREQS,
stepsize=DEFAULT_STEPSIZE,
seed=DEFAULT_SEED,
circuit_type=DEFAULT_ANSATZ,
data_reupload=DEFAULT_DATA_REUPLOAD,
)


def reset_log() -> Dict[str, list]:
"""
Resets the training log to contain empty lists for the following keys:
Expand Down Expand Up @@ -120,9 +136,11 @@ def on_preference_changed(
"PhaseDamping": pd,
"Depolarization": dp,
},
"steps": steps,
"n_freqs": n_freqs,
"stepsize": stepsize,
"steps": steps if steps is not None and steps > 0 else DEFAULT_N_STEPS,
"n_freqs": n_freqs if n_freqs is not None and n_freqs > 0 else DEFAULT_N_FREQS,
"stepsize": (
stepsize if stepsize is not None and stepsize > 0 else DEFAULT_STEPSIZE
),
"running": state != "Reset Training",
}
page_log_training = reset_log()
Expand Down Expand Up @@ -297,12 +315,15 @@ def update_expval(
x=page_log_training["x"], y=page_log_training["y"], name="Target"
)

miny = np.min(page_log_training["y"]) if len(page_log_training["y"]) > 0 else -1
maxy = np.max(page_log_training["y"]) if len(page_log_training["y"]) > 0 else 1

fig_expval.update_layout(
title="Output",
template="simple_white",
xaxis_title="X Domain",
yaxis_title="Expectation Value",
yaxis_range=[-0.5, 0.5],
yaxis_range=[miny, maxy],
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
)

Expand Down Expand Up @@ -386,48 +407,61 @@ def training(
Returns:
The updated data in the training log storage.
"""
global instructor

if page_log_training is None or page_data is None:
raise PreventUpdate()

if len(page_log_training["loss"]) > page_data["steps"]:
page_log_training = reset_log()

instructor = Instructor(
main_data["number_qubits"],
main_data["number_layers"],
n_freqs=page_data["n_freqs"],
stepsize=page_data["stepsize"],
seed=main_data["seed"],
circuit_type=main_data["circuit_type"],
data_reupload=main_data["data_reupload"],
)

page_log_training["params"], cost, pred = instructor.step(
page_log_training["params"], page_data["noise_params"]
)

page_log_training["loss"].append(cost.item())
page_log_training["y_hat"] = pred
if (
instructor.seed != main_data["seed"]
or instructor.model.n_qubits != main_data["number_qubits"]
or instructor.model.n_layers != main_data["number_layers"]
or instructor.stepsize != page_data["stepsize"]
or instructor.n_freqs != page_data["n_freqs"]
or instructor.circuit_type != main_data["circuit_type"]
or instructor.model.data_reupload != main_data["data_reupload"]
):
print("Re-init inst")
instructor = Instructor(
main_data["number_qubits"],
main_data["number_layers"],
n_freqs=page_data["n_freqs"],
stepsize=page_data["stepsize"],
seed=main_data["seed"],
circuit_type=main_data["circuit_type"],
data_reupload=main_data["data_reupload"],
)
page_log_training["x"] = instructor.x_d
page_log_training["y"] = instructor.y_d

data = instructor.calc_hist(
params=page_log_training["params"],
noise_params=page_data["noise_params"],
)

page_log_training["X"] = np.arange(
-len(data) // 2 + 1, len(data) // 2 + 1, 1
).tolist()
page_log_training["steps"] = [i for i in range(len(page_log_training["loss"]))]
page_log_training["Y"].append(data.tolist())

if main_data["number_qubits"] > 1:
instructor.model.params = page_log_training["params"]
ent_cap = instructor.meyer_wallach(
try:
data = instructor.calc_hist(
params=instructor.model.params,
noise_params=page_data["noise_params"],
)
page_log_training["X"] = np.arange(
-len(data) // 2 + 1, len(data) // 2 + 1, 1
).tolist()

page_log_training["Y"].append(data.tolist())

if main_data["number_qubits"] > 1:
instructor.model.params = instructor.model.params
ent_cap = instructor.meyer_wallach(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there might be an issue with qml-essentials here, when setting the n_qubits > 1. I get the following stack trace (when removing the try-catch), when resetting and starting the training (e.g. Ansatz=Circuit19, n_qubits=2, n_layers=2):

Traceback (most recent call last):
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/flask/app.py", line 865, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/dash/dash.py", line 1376, in dispatch
    ctx.run(
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/dash/_callback.py", line 507, in add_context
    raise err
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/dash/_callback.py", line 496, in add_context
    output_value = _invoke_callback(func, *func_args, **func_kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/dash/_callback.py", line 43, in _invoke_callback
    return func(*args, **kwargs)  # %% callback invoked %%
           ^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/app/pages/1-training.py", line 441, in training
    data = instructor.calc_hist(
           ^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/app/utils/instructor.py", line 166, in calc_hist
    .sample_coefficients(self.model, noise_params=noise_params, cache=False)
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/qml_essentials/coefficients.py", line 30, in sample_coefficients
    coeffs = coefficients(partial_circuit, 1, model.degree)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/pennylane/fourier/coefficients.py", line 178, in coefficients
    return _coefficients_no_filter(f, degree, use_broadcasting)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/pennylane/fourier/coefficients.py", line 262, in _coefficients_no_filter
    f_out = f(sampling_point)
            ^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/qml_essentials/model.py", line 483, in __call__
    return self._forward(
           ^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.11/site-packages/qml_essentials/model.py", line 616, in _forward
    if len(result.shape) == 3 and result.shape[0] == 1:
           ^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'shape'

My guess is that this is somehow caused by implicitly setting the execution_type to density when comuting the Meyer-Wallach measure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! already addressed with cirKITers/qml-essentials/pull/61

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah whoops

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating qml-essentials version to 0.1.17 with 1acfbf0 does not fully solve this problem.
Now getting a different stack trace (probably related to implicitly setting the execution_type):

ERROR:app:Exception on /_dash-update-component [POST]
TypeError: only length-1 arrays can be converted to Python scalars

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/flask/app.py", line 1473, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/flask/app.py", line 882, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/flask/app.py", line 880, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/flask/app.py", line 865, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/dash/dash.py", line 1376, in dispatch
    ctx.run(
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/dash/_callback.py", line 507, in add_context
    raise err
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/dash/_callback.py", line 496, in add_context
    output_value = _invoke_callback(func, *func_args, **func_kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/dash/_callback.py", line 43, in _invoke_callback
    return func(*args, **kwargs)  # %% callback invoked %%
           ^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/app/pages/1-training.py", line 440, in training
    data = instructor.calc_hist(
           ^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/app/utils/instructor.py", line 166, in calc_hist
    .sample_coefficients(self.model, noise_params=noise_params, cache=False)
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/qml_essentials/coefficients.py", line 30, in sample_coefficients
    coeffs = coefficients(partial_circuit, 1, model.degree)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/pennylane/fourier/coefficients.py", line 178, in coefficients
    return _coefficients_no_filter(f, degree, use_broadcasting)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<path>/mind-the-qapp/.venv/lib/python3.12/site-packages/pennylane/fourier/coefficients.py", line 263, in _coefficients_no_filter
    f_discrete[nvec] = f_out if use_broadcasting else np.squeeze(f_out)
    ~~~~~~~~~~^^^^^^
ValueError: setting an array element with a sequence.

noise_params=page_data["noise_params"],
)

page_log_training["ent_cap"].append(ent_cap)
except Exception as e:
log.error(e)

page_log_training["ent_cap"].append(ent_cap)
cost, pred = instructor.step(page_data["noise_params"])

page_log_training["loss"].append(cost.item())
page_log_training["steps"] = [i for i in range(len(page_log_training["loss"]))]
page_log_training["y_hat"] = pred

return page_log_training
2 changes: 1 addition & 1 deletion app/pages/2-expressibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

dash.register_page(__name__, name="Expressibility")

from layouts.expressibility_page_layout import layout # noqa
from layouts.expressibility_page_layout import layout # noqa: E402


@callback(
Expand Down
Loading