Update app.py
Browse files
app.py
CHANGED
|
@@ -8,7 +8,6 @@ import matplotlib.pyplot as plt
|
|
| 8 |
import numpy as np
|
| 9 |
import pandas as pd
|
| 10 |
from datasets import load_dataset
|
| 11 |
-
|
| 12 |
from sklearn.cluster import KMeans
|
| 13 |
from sklearn.decomposition import PCA
|
| 14 |
from sklearn.impute import SimpleImputer
|
|
@@ -19,7 +18,6 @@ from sklearn.preprocessing import StandardScaler
|
|
| 19 |
logging.basicConfig(level=logging.INFO)
|
| 20 |
logger = logging.getLogger(__name__)
|
| 21 |
|
| 22 |
-
# ========================= CONFIG =========================
|
| 23 |
APP_TITLE = "Circuit Complexity Clustering"
|
| 24 |
APP_SUBTITLE = (
|
| 25 |
"Unsupervised grouping of quantum circuits by structural complexity "
|
|
@@ -34,16 +32,31 @@ REPO_CONFIG = {
|
|
| 34 |
}
|
| 35 |
|
| 36 |
NON_FEATURE_COLS = {
|
| 37 |
-
"sample_id",
|
| 38 |
-
"
|
| 39 |
-
"
|
| 40 |
-
"
|
| 41 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
|
| 44 |
SOFT_EXCLUDE_PATTERNS = ["ideal_", "noisy_", "error_", "sign_ideal_", "sign_noisy_"]
|
| 45 |
|
| 46 |
_ASSET_CACHE: Dict[str, pd.DataFrame] = {}
|
|
|
|
| 47 |
|
| 48 |
|
| 49 |
def safe_parse(value):
|
|
@@ -140,6 +153,18 @@ def load_dataset_df(dataset_key: str) -> pd.DataFrame:
|
|
| 140 |
return _ASSET_CACHE[dataset_key]
|
| 141 |
|
| 142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
def load_guide_content() -> str:
|
| 144 |
"""Load the markdown guide if it exists."""
|
| 145 |
try:
|
|
@@ -165,52 +190,130 @@ def get_available_feature_columns(df: pd.DataFrame) -> List[str]:
|
|
| 165 |
def default_feature_selection(features: List[str]) -> List[str]:
|
| 166 |
"""Select a stable default feature subset."""
|
| 167 |
preferred = [
|
| 168 |
-
"gate_entropy",
|
| 169 |
-
"
|
| 170 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
]
|
| 172 |
selected = [feature for feature in preferred if feature in features]
|
| 173 |
return selected[:10] if selected else features[:10]
|
| 174 |
|
| 175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
def run_clustering(
|
| 177 |
-
|
| 178 |
feature_columns: List[str],
|
| 179 |
n_clusters: int,
|
| 180 |
random_state: float,
|
| 181 |
) -> Tuple[Optional[plt.Figure], str, pd.DataFrame]:
|
| 182 |
-
"""Run K-Means clustering and return PCA plot
|
|
|
|
|
|
|
|
|
|
| 183 |
if not feature_columns:
|
| 184 |
-
return None, "### β Please select at least one feature.",
|
| 185 |
|
| 186 |
-
df =
|
| 187 |
train_df = df.dropna(subset=feature_columns).copy()
|
| 188 |
|
| 189 |
if len(train_df) < 30:
|
| 190 |
-
return None, "### β Not enough rows after filtering missing values.",
|
| 191 |
|
| 192 |
X = train_df[feature_columns]
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
| 200 |
|
| 201 |
pipeline.fit(X)
|
| 202 |
labels = pipeline.named_steps["kmeans"].labels_
|
| 203 |
-
pca_coords = pipeline.named_steps["pca"].transform(
|
| 204 |
-
pipeline.named_steps["scaler"].transform(
|
| 205 |
-
pipeline.named_steps["imputer"].transform(X)
|
| 206 |
-
)
|
| 207 |
-
)
|
| 208 |
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
-
# Plot
|
| 212 |
fig, ax = plt.subplots(figsize=(10, 8))
|
| 213 |
-
scatter = ax.scatter(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
ax.set_title(f"Circuit Complexity Clusters (K={n_clusters})")
|
| 215 |
ax.set_xlabel("PCA Component 1")
|
| 216 |
ax.set_ylabel("PCA Component 2")
|
|
@@ -218,21 +321,29 @@ def run_clustering(
|
|
| 218 |
plt.colorbar(scatter, ax=ax, label="Cluster")
|
| 219 |
plt.tight_layout()
|
| 220 |
|
| 221 |
-
# Cluster summary
|
| 222 |
summary = train_df.copy()
|
| 223 |
summary["cluster"] = labels
|
| 224 |
-
cluster_summary = summary.groupby("cluster").size().reset_index()
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
metrics_text = (
|
| 228 |
f"### Clustering Results\n\n"
|
| 229 |
-
f"**
|
| 230 |
-
f"**Number of
|
|
|
|
| 231 |
f"**Silhouette Score:** {sil_score:.4f} (closer to 1 = better separation)\n\n"
|
| 232 |
f"**Cluster sizes:**\n"
|
| 233 |
f"{cluster_summary.to_markdown(index=False)}"
|
| 234 |
)
|
| 235 |
|
|
|
|
|
|
|
|
|
|
| 236 |
return fig, metrics_text, cluster_summary
|
| 237 |
|
| 238 |
|
|
@@ -270,14 +381,18 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 270 |
transpiled_qasm = gr.Code(label="Transpiled QASM", language=None)
|
| 271 |
|
| 272 |
with gr.TabItem("π§ Clustering"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
feature_picker = gr.CheckboxGroup(label="Input features", choices=[])
|
| 274 |
n_clusters = gr.Slider(2, 10, value=4, step=1, label="Number of Clusters")
|
| 275 |
seed = gr.Number(value=42, precision=0, label="Random Seed")
|
| 276 |
run_btn = gr.Button("π Run K-Means Clustering", variant="primary")
|
| 277 |
-
|
| 278 |
plot = gr.Plot()
|
| 279 |
metrics = gr.Markdown()
|
| 280 |
-
cluster_table = gr.Dataframe(label="Cluster Sizes")
|
| 281 |
|
| 282 |
with gr.TabItem("π Guide"):
|
| 283 |
gr.Markdown(load_guide_content())
|
|
@@ -290,35 +405,6 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 290 |
"[GitHub](https://github.com/QSBench)"
|
| 291 |
)
|
| 292 |
|
| 293 |
-
# Callbacks
|
| 294 |
-
def refresh_explorer(dataset_key: str, split_name: str):
|
| 295 |
-
df = load_dataset_df(dataset_key)
|
| 296 |
-
splits = df["split"].dropna().unique().tolist() if "split" in df.columns else ["train"]
|
| 297 |
-
if not splits:
|
| 298 |
-
splits = ["train"]
|
| 299 |
-
if split_name not in splits:
|
| 300 |
-
split_name = splits[0]
|
| 301 |
-
filtered = df[df["split"] == split_name] if "split" in df.columns else df
|
| 302 |
-
display_df = filtered.head(12).copy()
|
| 303 |
-
raw = display_df["qasm_raw"].iloc[0] if not display_df.empty else "// N/A"
|
| 304 |
-
transpiled = display_df["qasm_transpiled"].iloc[0] if not display_df.empty else "// N/A"
|
| 305 |
-
profile = f"### Dataset profile\n\n**Rows:** {len(df):,}\n**Columns:** {len(df.columns):,}"
|
| 306 |
-
summary = f"### Split summary\n\n**Dataset:** `{dataset_key}`\n**Available splits:** {', '.join(splits)}\n**Preview rows:** {len(display_df)}"
|
| 307 |
-
return (
|
| 308 |
-
gr.update(choices=splits, value=split_name),
|
| 309 |
-
display_df,
|
| 310 |
-
raw,
|
| 311 |
-
transpiled,
|
| 312 |
-
profile,
|
| 313 |
-
summary,
|
| 314 |
-
)
|
| 315 |
-
|
| 316 |
-
def sync_feature_picker(dataset_key: str):
|
| 317 |
-
df = load_dataset_df(dataset_key)
|
| 318 |
-
features = get_available_feature_columns(df)
|
| 319 |
-
defaults = default_feature_selection(features)
|
| 320 |
-
return gr.update(choices=features, value=defaults)
|
| 321 |
-
|
| 322 |
dataset_dropdown.change(
|
| 323 |
refresh_explorer,
|
| 324 |
[dataset_dropdown, split_dropdown],
|
|
@@ -329,11 +415,12 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 329 |
[dataset_dropdown, split_dropdown],
|
| 330 |
[split_dropdown, explorer_df, raw_qasm, transpiled_qasm, profile_box, summary_box],
|
| 331 |
)
|
| 332 |
-
|
|
|
|
| 333 |
|
| 334 |
run_btn.click(
|
| 335 |
run_clustering,
|
| 336 |
-
[
|
| 337 |
[plot, metrics, cluster_table],
|
| 338 |
)
|
| 339 |
|
|
@@ -342,8 +429,8 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 342 |
[dataset_dropdown, split_dropdown],
|
| 343 |
[split_dropdown, explorer_df, raw_qasm, transpiled_qasm, profile_box, summary_box],
|
| 344 |
)
|
| 345 |
-
demo.load(sync_feature_picker, [
|
| 346 |
|
| 347 |
|
| 348 |
if __name__ == "__main__":
|
| 349 |
-
demo.launch(theme=gr.themes.Soft(), css=CUSTOM_CSS)
|
|
|
|
| 8 |
import numpy as np
|
| 9 |
import pandas as pd
|
| 10 |
from datasets import load_dataset
|
|
|
|
| 11 |
from sklearn.cluster import KMeans
|
| 12 |
from sklearn.decomposition import PCA
|
| 13 |
from sklearn.impute import SimpleImputer
|
|
|
|
| 18 |
logging.basicConfig(level=logging.INFO)
|
| 19 |
logger = logging.getLogger(__name__)
|
| 20 |
|
|
|
|
| 21 |
APP_TITLE = "Circuit Complexity Clustering"
|
| 22 |
APP_SUBTITLE = (
|
| 23 |
"Unsupervised grouping of quantum circuits by structural complexity "
|
|
|
|
| 32 |
}
|
| 33 |
|
| 34 |
NON_FEATURE_COLS = {
|
| 35 |
+
"sample_id",
|
| 36 |
+
"sample_seed",
|
| 37 |
+
"circuit_hash",
|
| 38 |
+
"split",
|
| 39 |
+
"circuit_qasm",
|
| 40 |
+
"qasm_raw",
|
| 41 |
+
"qasm_transpiled",
|
| 42 |
+
"circuit_type_resolved",
|
| 43 |
+
"circuit_type_requested",
|
| 44 |
+
"noise_type",
|
| 45 |
+
"noise_prob",
|
| 46 |
+
"observable_bases",
|
| 47 |
+
"observable_mode",
|
| 48 |
+
"backend_device",
|
| 49 |
+
"precision_mode",
|
| 50 |
+
"circuit_signature",
|
| 51 |
+
"entanglement",
|
| 52 |
+
"meyer_wallach",
|
| 53 |
+
"noise_label",
|
| 54 |
}
|
| 55 |
|
| 56 |
SOFT_EXCLUDE_PATTERNS = ["ideal_", "noisy_", "error_", "sign_ideal_", "sign_noisy_"]
|
| 57 |
|
| 58 |
_ASSET_CACHE: Dict[str, pd.DataFrame] = {}
|
| 59 |
+
_COMBINED_CACHE: Optional[pd.DataFrame] = None
|
| 60 |
|
| 61 |
|
| 62 |
def safe_parse(value):
|
|
|
|
| 153 |
return _ASSET_CACHE[dataset_key]
|
| 154 |
|
| 155 |
|
| 156 |
+
def load_combined_dataset(dataset_keys: List[str]) -> pd.DataFrame:
|
| 157 |
+
"""Load and merge selected datasets."""
|
| 158 |
+
global _COMBINED_CACHE
|
| 159 |
+
cache_key = "|".join(sorted(dataset_keys))
|
| 160 |
+
if _COMBINED_CACHE is None or getattr(load_combined_dataset, "_cache_key", None) != cache_key:
|
| 161 |
+
frames = [load_dataset_df(key).assign(source_dataset=key) for key in dataset_keys]
|
| 162 |
+
combined = pd.concat(frames, ignore_index=True)
|
| 163 |
+
_COMBINED_CACHE = combined
|
| 164 |
+
load_combined_dataset._cache_key = cache_key # type: ignore[attr-defined]
|
| 165 |
+
return _COMBINED_CACHE
|
| 166 |
+
|
| 167 |
+
|
| 168 |
def load_guide_content() -> str:
|
| 169 |
"""Load the markdown guide if it exists."""
|
| 170 |
try:
|
|
|
|
| 190 |
def default_feature_selection(features: List[str]) -> List[str]:
|
| 191 |
"""Select a stable default feature subset."""
|
| 192 |
preferred = [
|
| 193 |
+
"gate_entropy",
|
| 194 |
+
"adj_density",
|
| 195 |
+
"adj_degree_mean",
|
| 196 |
+
"adj_degree_std",
|
| 197 |
+
"depth",
|
| 198 |
+
"total_gates",
|
| 199 |
+
"single_qubit_gates",
|
| 200 |
+
"two_qubit_gates",
|
| 201 |
+
"cx_count",
|
| 202 |
+
"qasm_length",
|
| 203 |
+
"qasm_line_count",
|
| 204 |
+
"qasm_gate_keyword_count",
|
| 205 |
]
|
| 206 |
selected = [feature for feature in preferred if feature in features]
|
| 207 |
return selected[:10] if selected else features[:10]
|
| 208 |
|
| 209 |
|
| 210 |
+
def build_dataset_profile(df: pd.DataFrame) -> str:
|
| 211 |
+
"""Build a short dataset summary for the explorer tab."""
|
| 212 |
+
return (
|
| 213 |
+
f"### Dataset profile\n\n"
|
| 214 |
+
f"**Rows:** {len(df):,} \n"
|
| 215 |
+
f"**Columns:** {len(df.columns):,} \n"
|
| 216 |
+
f"**Available datasets:** {len(REPO_CONFIG)}"
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def refresh_explorer(dataset_key: str, split_name: str) -> Tuple[gr.update, pd.DataFrame, str, str, str, str]:
|
| 221 |
+
"""Refresh the explorer view for the selected source dataset."""
|
| 222 |
+
df = load_dataset_df(dataset_key)
|
| 223 |
+
splits = df["split"].dropna().unique().tolist() if "split" in df.columns else ["train"]
|
| 224 |
+
if not splits:
|
| 225 |
+
splits = ["train"]
|
| 226 |
+
|
| 227 |
+
if split_name not in splits:
|
| 228 |
+
split_name = splits[0]
|
| 229 |
+
|
| 230 |
+
filtered = df[df["split"] == split_name] if "split" in df.columns else df
|
| 231 |
+
display_df = filtered.head(12).copy()
|
| 232 |
+
|
| 233 |
+
raw_qasm = display_df["qasm_raw"].iloc[0] if "qasm_raw" in display_df.columns and not display_df.empty else "// N/A"
|
| 234 |
+
transpiled_qasm = display_df["qasm_transpiled"].iloc[0] if "qasm_transpiled" in display_df.columns and not display_df.empty else "// N/A"
|
| 235 |
+
|
| 236 |
+
profile_box = build_dataset_profile(df)
|
| 237 |
+
summary_box = (
|
| 238 |
+
f"### Split summary\n\n"
|
| 239 |
+
f"**Dataset:** `{dataset_key}` \n"
|
| 240 |
+
f"**Available splits:** {', '.join(splits)} \n"
|
| 241 |
+
f"**Preview rows:** {len(display_df)}"
|
| 242 |
+
)
|
| 243 |
+
|
| 244 |
+
return (
|
| 245 |
+
gr.update(choices=splits, value=split_name),
|
| 246 |
+
display_df,
|
| 247 |
+
raw_qasm,
|
| 248 |
+
transpiled_qasm,
|
| 249 |
+
profile_box,
|
| 250 |
+
summary_box,
|
| 251 |
+
)
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
def sync_feature_picker(dataset_keys: List[str]) -> gr.update:
|
| 255 |
+
"""Refresh the feature list from the selected datasets."""
|
| 256 |
+
if not dataset_keys:
|
| 257 |
+
return gr.update(choices=[], value=[])
|
| 258 |
+
|
| 259 |
+
df = load_combined_dataset(dataset_keys)
|
| 260 |
+
features = get_available_feature_columns(df)
|
| 261 |
+
defaults = default_feature_selection(features)
|
| 262 |
+
return gr.update(choices=features, value=defaults)
|
| 263 |
+
|
| 264 |
+
|
| 265 |
def run_clustering(
|
| 266 |
+
dataset_keys: List[str],
|
| 267 |
feature_columns: List[str],
|
| 268 |
n_clusters: int,
|
| 269 |
random_state: float,
|
| 270 |
) -> Tuple[Optional[plt.Figure], str, pd.DataFrame]:
|
| 271 |
+
"""Run K-Means clustering and return a PCA plot plus metrics."""
|
| 272 |
+
if not dataset_keys:
|
| 273 |
+
return None, "### β Please select at least one dataset.", pd.DataFrame()
|
| 274 |
+
|
| 275 |
if not feature_columns:
|
| 276 |
+
return None, "### β Please select at least one feature.", pd.DataFrame()
|
| 277 |
|
| 278 |
+
df = load_combined_dataset(dataset_keys)
|
| 279 |
train_df = df.dropna(subset=feature_columns).copy()
|
| 280 |
|
| 281 |
if len(train_df) < 30:
|
| 282 |
+
return None, "### β Not enough rows after filtering missing values.", pd.DataFrame()
|
| 283 |
|
| 284 |
X = train_df[feature_columns]
|
| 285 |
+
seed = int(random_state)
|
| 286 |
+
|
| 287 |
+
pipeline = Pipeline(
|
| 288 |
+
steps=[
|
| 289 |
+
("imputer", SimpleImputer(strategy="median")),
|
| 290 |
+
("scaler", StandardScaler()),
|
| 291 |
+
("pca", PCA(n_components=2, random_state=seed)),
|
| 292 |
+
("kmeans", KMeans(n_clusters=n_clusters, random_state=seed, n_init=10)),
|
| 293 |
+
]
|
| 294 |
+
)
|
| 295 |
|
| 296 |
pipeline.fit(X)
|
| 297 |
labels = pipeline.named_steps["kmeans"].labels_
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
|
| 299 |
+
transformed = pipeline.named_steps["imputer"].transform(X)
|
| 300 |
+
transformed = pipeline.named_steps["scaler"].transform(transformed)
|
| 301 |
+
pca_coords = pipeline.named_steps["pca"].transform(transformed)
|
| 302 |
+
|
| 303 |
+
try:
|
| 304 |
+
sil_score = silhouette_score(X, labels)
|
| 305 |
+
except Exception:
|
| 306 |
+
sil_score = float("nan")
|
| 307 |
|
|
|
|
| 308 |
fig, ax = plt.subplots(figsize=(10, 8))
|
| 309 |
+
scatter = ax.scatter(
|
| 310 |
+
pca_coords[:, 0],
|
| 311 |
+
pca_coords[:, 1],
|
| 312 |
+
c=labels,
|
| 313 |
+
cmap="tab10",
|
| 314 |
+
s=30,
|
| 315 |
+
alpha=0.8,
|
| 316 |
+
)
|
| 317 |
ax.set_title(f"Circuit Complexity Clusters (K={n_clusters})")
|
| 318 |
ax.set_xlabel("PCA Component 1")
|
| 319 |
ax.set_ylabel("PCA Component 2")
|
|
|
|
| 321 |
plt.colorbar(scatter, ax=ax, label="Cluster")
|
| 322 |
plt.tight_layout()
|
| 323 |
|
|
|
|
| 324 |
summary = train_df.copy()
|
| 325 |
summary["cluster"] = labels
|
| 326 |
+
cluster_summary = summary.groupby("cluster").size().reset_index(name="Number of Circuits")
|
| 327 |
+
|
| 328 |
+
dataset_counts = (
|
| 329 |
+
summary.groupby(["cluster", "source_dataset"]).size().reset_index(name="Count")
|
| 330 |
+
if "source_dataset" in summary.columns
|
| 331 |
+
else pd.DataFrame()
|
| 332 |
+
)
|
| 333 |
|
| 334 |
metrics_text = (
|
| 335 |
f"### Clustering Results\n\n"
|
| 336 |
+
f"**Datasets used:** {', '.join(dataset_keys)} \n"
|
| 337 |
+
f"**Number of circuits clustered:** {len(train_df):,} \n"
|
| 338 |
+
f"**Number of clusters:** {n_clusters} \n"
|
| 339 |
f"**Silhouette Score:** {sil_score:.4f} (closer to 1 = better separation)\n\n"
|
| 340 |
f"**Cluster sizes:**\n"
|
| 341 |
f"{cluster_summary.to_markdown(index=False)}"
|
| 342 |
)
|
| 343 |
|
| 344 |
+
if not dataset_counts.empty:
|
| 345 |
+
metrics_text += f"\n\n**Dataset composition per cluster:**\n{dataset_counts.to_markdown(index=False)}"
|
| 346 |
+
|
| 347 |
return fig, metrics_text, cluster_summary
|
| 348 |
|
| 349 |
|
|
|
|
| 381 |
transpiled_qasm = gr.Code(label="Transpiled QASM", language=None)
|
| 382 |
|
| 383 |
with gr.TabItem("π§ Clustering"):
|
| 384 |
+
dataset_picker = gr.CheckboxGroup(
|
| 385 |
+
label="Datasets",
|
| 386 |
+
choices=list(REPO_CONFIG.keys()),
|
| 387 |
+
value=list(REPO_CONFIG.keys()),
|
| 388 |
+
)
|
| 389 |
feature_picker = gr.CheckboxGroup(label="Input features", choices=[])
|
| 390 |
n_clusters = gr.Slider(2, 10, value=4, step=1, label="Number of Clusters")
|
| 391 |
seed = gr.Number(value=42, precision=0, label="Random Seed")
|
| 392 |
run_btn = gr.Button("π Run K-Means Clustering", variant="primary")
|
|
|
|
| 393 |
plot = gr.Plot()
|
| 394 |
metrics = gr.Markdown()
|
| 395 |
+
cluster_table = gr.Dataframe(label="Cluster Sizes", interactive=False)
|
| 396 |
|
| 397 |
with gr.TabItem("π Guide"):
|
| 398 |
gr.Markdown(load_guide_content())
|
|
|
|
| 405 |
"[GitHub](https://github.com/QSBench)"
|
| 406 |
)
|
| 407 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 408 |
dataset_dropdown.change(
|
| 409 |
refresh_explorer,
|
| 410 |
[dataset_dropdown, split_dropdown],
|
|
|
|
| 415 |
[dataset_dropdown, split_dropdown],
|
| 416 |
[split_dropdown, explorer_df, raw_qasm, transpiled_qasm, profile_box, summary_box],
|
| 417 |
)
|
| 418 |
+
|
| 419 |
+
dataset_picker.change(sync_feature_picker, [dataset_picker], [feature_picker])
|
| 420 |
|
| 421 |
run_btn.click(
|
| 422 |
run_clustering,
|
| 423 |
+
[dataset_picker, feature_picker, n_clusters, seed],
|
| 424 |
[plot, metrics, cluster_table],
|
| 425 |
)
|
| 426 |
|
|
|
|
| 429 |
[dataset_dropdown, split_dropdown],
|
| 430 |
[split_dropdown, explorer_df, raw_qasm, transpiled_qasm, profile_box, summary_box],
|
| 431 |
)
|
| 432 |
+
demo.load(sync_feature_picker, [dataset_picker], [feature_picker])
|
| 433 |
|
| 434 |
|
| 435 |
if __name__ == "__main__":
|
| 436 |
+
demo.launch(theme=gr.themes.Soft(), css=CUSTOM_CSS)
|