summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYurenHao0426 <Blackhao0426@gmail.com>2026-08-29 17:42:16 -0500
committerYurenHao0426 <Blackhao0426@gmail.com>2026-08-29 17:42:16 -0500
commit5d5afff674c898f345fc57119cbc2f99fa7fb0bd (patch)
tree526213e7aa1982790e52d673b0263614527dba79
parentcaa30af8f8191f48bae08f3f1074021cc8e4d81e (diff)
feat: add stable-target and physical-exposure metrics
-rw-r--r--experiments/coupled_ladder_scaling.py34
-rw-r--r--sdil/coupled_ladder.py45
2 files changed, 59 insertions, 20 deletions
diff --git a/experiments/coupled_ladder_scaling.py b/experiments/coupled_ladder_scaling.py
index ce3509a..7c50e2d 100644
--- a/experiments/coupled_ladder_scaling.py
+++ b/experiments/coupled_ladder_scaling.py
@@ -160,10 +160,16 @@ def run_job(job: dict) -> dict:
"failure_message": str(error),
"classification_error": 1.0,
"hinge_loss_v2": None,
- "reached_zero_error": False,
- "restricted_epochs_to_zero_error": job["epochs"],
- "restricted_updates_to_zero_error": (
+ "reached_stable_zero_error": False,
+ "restricted_epochs_to_stable_zero_error": job["epochs"],
+ "restricted_updates_to_stable_zero_error": (
job["epochs"] * len(dataset.labels_v)),
+ "restricted_edge_updates_to_stable_zero_error": (
+ job["epochs"] * len(dataset.labels_v)
+ * circuit.edge_count),
+ "restricted_learning_time_to_stable_zero_seconds": (
+ job["epochs"] * len(dataset.labels_v)
+ * job["learning_time_seconds"]),
"classification_error_auc": 1.0,
"local_updates": None,
"neutral_observations": None,
@@ -201,10 +207,27 @@ def summarize(records: list[dict], methods: tuple[str, ...]) -> dict:
"mean_classification_error_auc": float(np.mean([
value["classification_error_auc"] for value in values
])),
- "mean_restricted_epochs_to_zero_error": float(np.mean([
- value["restricted_epochs_to_zero_error"]
+ "stable_zero_error_fraction": float(np.mean([
+ value["reached_stable_zero_error"] for value in values
+ ])),
+ "mean_restricted_epochs_to_stable_zero_error": float(np.mean([
+ value["restricted_epochs_to_stable_zero_error"]
for value in values
])),
+ "mean_restricted_edge_updates_to_stable_zero_error": (
+ float(np.mean([
+ value[
+ "restricted_edge_updates_to_stable_zero_error"
+ ] for value in values
+ ]))
+ ),
+ "mean_restricted_learning_time_to_stable_zero_seconds": (
+ float(np.mean([
+ value[
+ "restricted_learning_time_to_stable_zero_seconds"
+ ] for value in values
+ ]))
+ ),
"median_wall_seconds": float(np.median([
value["wall_seconds"] for value in values
])),
@@ -338,4 +361,3 @@ def main() -> None:
if __name__ == "__main__":
main()
-
diff --git a/sdil/coupled_ladder.py b/sdil/coupled_ladder.py
index a9b8014..b7c67fb 100644
--- a/sdil/coupled_ladder.py
+++ b/sdil/coupled_ladder.py
@@ -224,6 +224,7 @@ def train_digital_grid(
trace = [{
"epoch": 0,
"local_updates": 0,
+ "cumulative_learning_time_seconds": 0.0,
**evaluate_digital_grid(circuit, gates, dataset),
}]
@@ -296,21 +297,31 @@ def train_digital_grid(
trace.append({
"epoch": epoch,
"local_updates": local_updates,
+ "cumulative_learning_time_seconds": float(
+ cumulative_learning_time),
**evaluate_digital_grid(circuit, gates, dataset),
})
- zero_records = [
- record for record in trace
+ stable_zero_index = next((
+ index for index, record in enumerate(trace)
if record["classification_error"] == 0.0
- ]
- if zero_records:
- epochs_to_zero = int(zero_records[0]["epoch"])
- updates_to_zero = int(zero_records[0]["local_updates"])
- reached_zero = True
+ and all(
+ later["classification_error"] == 0.0
+ for later in trace[index:]
+ )
+ ), None)
+ if stable_zero_index is not None:
+ stable_record = trace[stable_zero_index]
+ epochs_to_stable_zero = int(stable_record["epoch"])
+ updates_to_stable_zero = int(stable_record["local_updates"])
+ exposure_to_stable_zero = float(
+ stable_record["cumulative_learning_time_seconds"])
+ reached_stable_zero = True
else:
- epochs_to_zero = config.epochs
- updates_to_zero = local_updates
- reached_zero = False
+ epochs_to_stable_zero = config.epochs
+ updates_to_stable_zero = local_updates
+ exposure_to_stable_zero = float(cumulative_learning_time)
+ reached_stable_zero = False
epoch_axis = np.asarray([record["epoch"] for record in trace])
error_axis = np.asarray([
record["classification_error"] for record in trace])
@@ -322,15 +333,21 @@ def train_digital_grid(
"hinge_loss_v2": final["hinge_loss_v2"],
"margin_success_fraction": final["margin_success_fraction"],
"outputs_v": final["outputs_v"],
- "reached_zero_error": reached_zero,
- "restricted_epochs_to_zero_error": epochs_to_zero,
- "restricted_updates_to_zero_error": updates_to_zero,
+ "reached_stable_zero_error": reached_stable_zero,
+ "restricted_epochs_to_stable_zero_error": epochs_to_stable_zero,
+ "restricted_updates_to_stable_zero_error": updates_to_stable_zero,
+ "restricted_edge_updates_to_stable_zero_error": int(
+ updates_to_stable_zero * circuit.edge_count),
+ "restricted_learning_time_to_stable_zero_seconds": (
+ exposure_to_stable_zero),
"classification_error_auc": error_auc,
"local_updates": local_updates,
+ "local_edge_updates": int(local_updates * circuit.edge_count),
"neutral_observations": neutral_observations,
+ "neutral_scalar_observations": int(
+ neutral_observations * circuit.edge_count),
"cumulative_learning_time_seconds": float(cumulative_learning_time),
"clipped_updates": clipped_updates,
"final_gates_v": gates.tolist(),
"trace": trace,
}
-