From 907b5e25af32dc938bb04f4cb06a99cd55a20f46 Mon Sep 17 00:00:00 2001 From: YurenHao0426 Date: Thu, 6 Aug 2026 16:17:50 -0500 Subject: results: identify state-dependent physical drift --- TWO_STATE_BIAS_PROGRAM.md | 7 + .../analyze_physical_drift_state_dependence.py | 493 +++++++++++ results/figs/physical_bias_state_dependence.png | Bin 0 -> 231580 bytes .../figs/physical_bias_state_dependence_caption.md | 15 + results/physical_bias/p0_state_dependence.json | 901 +++++++++++++++++++++ 5 files changed, 1416 insertions(+) create mode 100644 experiments/analyze_physical_drift_state_dependence.py create mode 100644 results/figs/physical_bias_state_dependence.png create mode 100644 results/figs/physical_bias_state_dependence_caption.md create mode 100644 results/physical_bias/p0_state_dependence.json diff --git a/TWO_STATE_BIAS_PROGRAM.md b/TWO_STATE_BIAS_PROGRAM.md index b0df1b2..1020b11 100644 --- a/TWO_STATE_BIAS_PROGRAM.md +++ b/TWO_STATE_BIAS_PROGRAM.md @@ -290,6 +290,13 @@ Stop this paper direction if: `1.8374/1.7360/1.9468`; see `results/physical_bias/p0_summary.json`. This reproduces a nonzero rapid-switching error floor and an approximately constant low-period drift speed from real hardware. It is not an SDIL result. +- Physical state-dependence diagnostic: complete. On held-out later portions of + the four released `DriftTests` traces, a per-edge affine field reduces + tangential-velocity RMSE to `0.21/0.54` of a constant-bias model for the two + task pairs. The direction is unchanged when excluding the final + `30/50/80/100 mV` before the observed gate plateaus; see + `results/physical_bias/p0_state_dependence.json`. This establishes a measured + locally predictable component suitable for P1, not an SDIL learning result. - Dual Prop same-path confirmation: active/supporting, not a passed result. - EP/CpL adapters: not implemented under this bias model. - Current score for this new paper framing: 5/10 until P1 passes. diff --git a/experiments/analyze_physical_drift_state_dependence.py b/experiments/analyze_physical_drift_state_dependence.py new file mode 100644 index 0000000..42ca420 --- /dev/null +++ b/experiments/analyze_physical_drift_state_dependence.py @@ -0,0 +1,493 @@ +#!/usr/bin/env python3 +"""Test whether released physical drift is state dependent. + +Dillavou et al. approximate the two-edge physical network with a constant +bias vector. Their appendix also notes that the experimental drift rate is +not constant. This script tests that statement directly from the four +released DriftTests traces. + +Once a trace is close to a one-task solution line, the clean learning force is +normal to that line. Its measured tangential velocity therefore estimates +the tangential projection of the physical bias. We compare: + + constant: B(G) = b + local affine: B_i(G_i) = b_i + k_i (G_i - G_ref_i) + +The second model uses exactly the per-edge local information available to an +affine SDIL predictor. It is a measured-data identifiability diagnostic, not +yet evidence that SDIL improves task learning. +""" + +from __future__ import annotations + +import argparse +from dataclasses import dataclass +import hashlib +import json +from pathlib import Path +from typing import Dict, List, Sequence + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import numpy as np +from scipy.io import loadmat + + +ZENODO_RECORD = "15692914" +ZENODO_DOI = "10.5281/zenodo.15692914" +RELEASE = "v1.0.1" +SOURCE_TREE = "maguzj-imperfect-learning-physical-systems-71b8d72" + + +@dataclass(frozen=True) +class TraceSpec: + filename: str + task: str + solution_slope: float + solution_intercept: float + + +@dataclass(frozen=True) +class PairSpec: + name: str + reference_gate: tuple[float, float] + published_bias_at_reference: tuple[float, float] + traces: tuple[TraceSpec, TraceSpec] + + +PAIR_SPECS = ( + PairSpec( + name="experiment_1", + reference_gate=(3.0, 3.5), + published_bias_at_reference=(2.9, 4.7), + traces=( + TraceSpec("exp1DriftTest_1.mat", "beta", 0.43914, 1.6061), + TraceSpec("exp1DriftTest_2.mat", "alpha", 2.7257, -3.3003), + ), + ), + PairSpec( + name="experiment_2", + reference_gate=(3.1, 4.3), + published_bias_at_reference=(-0.3, 2.0), + traces=( + TraceSpec("exp2DriftTest_1.mat", "beta", 0.74821, 1.9224), + TraceSpec("exp2DriftTest_2.mat", "alpha", 2.5678, -2.901), + ), + ), +) + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as handle: + for block in iter(lambda: handle.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def rmse(observed: np.ndarray, predicted: np.ndarray) -> float: + return float(np.sqrt(np.mean((observed - predicted) ** 2))) + + +def r_squared(observed: np.ndarray, predicted: np.ndarray) -> float: + denominator = float(np.sum((observed - np.mean(observed)) ** 2)) + if denominator == 0.0: + return float("nan") + return float(1.0 - np.sum((observed - predicted) ** 2) / denominator) + + +def load_trace( + drift_dir: Path, + spec: TraceSpec, + reference_gate: Sequence[float], + *, + minimum_time: float, + terminal_headroom: float, + maximum_line_distance: float, + trim_selected_ends: int, +) -> dict: + path = drift_dir / spec.filename + raw = loadmat(path, squeeze_me=True) + time = np.asarray(raw["time"], dtype=float) + gate_minus = np.asarray(raw["GMINUS"], dtype=float) + gate_plus = np.asarray(raw["GPLUS"], dtype=float) + if time.ndim != 1 or len(time) != 300: + raise ValueError(f"unexpected time array in {path}: {time.shape}") + if not (time.shape == gate_minus.shape == gate_plus.shape): + raise ValueError(f"array shape disagreement in {path}") + if not np.all(np.isfinite(np.column_stack((time, gate_minus, gate_plus)))): + raise ValueError(f"nonfinite source value in {path}") + + # The first two entries straddle the experiment initialization and a + # roughly 0.9 s gap. The remaining samples have a stable ~30 ms cadence. + time = time[2:] + gate_minus = gate_minus[2:] + gate_plus = gate_plus[2:] + sample_period = float(np.median(np.diff(time))) + velocity_minus = np.gradient(gate_minus, time) + velocity_plus = np.gradient(gate_plus, time) + + slope = spec.solution_slope + intercept = spec.solution_intercept + tangent = np.asarray((1.0, slope), dtype=float) + tangent /= np.linalg.norm(tangent) + signed_distance = ( + gate_plus - slope * gate_minus - intercept + ) / np.sqrt(1.0 + slope * slope) + # Every released trace terminates on a clear gate-voltage plateau. Exclude + # the final headroom before either observed plateau so a hardware rail is + # not mislabeled as a state-dependent bias. Trimming the selected ends + # then ensures that centered differences use only pre-plateau samples. + selected = ( + (time >= minimum_time) + & (gate_minus < np.max(gate_minus) - terminal_headroom) + & (gate_plus < np.max(gate_plus) - terminal_headroom) + & (np.abs(signed_distance) < maximum_line_distance) + ) + indices = np.flatnonzero(selected) + if len(indices) <= 2 * trim_selected_ends: + raise ValueError(f"too few usable solution-line samples in {path}") + if np.any(np.diff(indices) != 1): + raise ValueError(f"selected solution-line window is not contiguous in {path}") + indices = indices[trim_selected_ends:-trim_selected_ends] + + gates = np.column_stack((gate_minus[indices], gate_plus[indices])) + velocities = np.column_stack( + (velocity_minus[indices], velocity_plus[indices])) + reference = np.asarray(reference_gate, dtype=float) + design = np.column_stack(( + np.full(len(indices), tangent[0]), + np.full(len(indices), tangent[1]), + tangent[0] * (gates[:, 0] - reference[0]), + tangent[1] * (gates[:, 1] - reference[1]), + )) + projected_velocity = velocities @ tangent + path_coordinate = gates @ tangent + if len(indices) < 6: + raise ValueError(f"need at least six retained samples in {path}") + + return { + "spec": spec, + "source_file": {"path": str(path), "sha256": sha256(path)}, + "sample_period_seconds": sample_period, + "raw_gate_minus": gate_minus, + "raw_gate_plus": gate_plus, + "time": time, + "selected_indices": indices, + "selected_time": time[indices], + "selected_gates": gates, + "selected_line_distance": signed_distance[indices], + "tangent": tangent, + "path_coordinate": path_coordinate, + "projected_velocity": projected_velocity, + "design": design, + } + + +def fit_columns(design: np.ndarray, target: np.ndarray, columns: List[int]) -> dict: + selected = design[:, columns] + parameters, _, _, _ = np.linalg.lstsq(selected, target, rcond=None) + predicted = selected @ parameters + return { + "columns": columns, + "parameters": parameters, + "predicted": predicted, + "rank": int(np.linalg.matrix_rank(selected)), + "condition_number": float(np.linalg.cond(selected)), + "rmse": rmse(target, predicted), + "r_squared": r_squared(target, predicted), + } + + +def forward_block_test(traces: Sequence[dict], columns: List[int]) -> dict: + train_design = [] + train_target = [] + test_design = [] + test_target = [] + split_records = [] + for trace in traces: + count = len(trace["projected_velocity"]) + train_count = max(2, int(np.floor(0.6 * count))) + if count - train_count < 2: + raise ValueError("forward block test needs at least two held-out samples") + train_design.append(trace["design"][:train_count, columns]) + train_target.append(trace["projected_velocity"][:train_count]) + test_design.append(trace["design"][train_count:, columns]) + test_target.append(trace["projected_velocity"][train_count:]) + split_records.append({ + "source": trace["spec"].filename, + "train_samples": train_count, + "test_samples": count - train_count, + }) + train_design_array = np.vstack(train_design) + train_target_array = np.concatenate(train_target) + test_design_array = np.vstack(test_design) + test_target_array = np.concatenate(test_target) + parameters, _, _, _ = np.linalg.lstsq( + train_design_array, train_target_array, rcond=None) + train_prediction = train_design_array @ parameters + test_prediction = test_design_array @ parameters + return { + "split": "first 60% of each retained trace trains; final 40% tests", + "trace_splits": split_records, + "parameters": parameters.tolist(), + "train_rank": int(np.linalg.matrix_rank(train_design_array)), + "train_condition_number": float(np.linalg.cond(train_design_array)), + "train_rmse": rmse(train_target_array, train_prediction), + "test_rmse": rmse(test_target_array, test_prediction), + "test_r_squared": r_squared(test_target_array, test_prediction), + } + + +def serializable_trace(trace: dict) -> dict: + spec = trace["spec"] + return { + "source_file": trace["source_file"], + "task": spec.task, + "solution_line": { + "gate_plus_slope": spec.solution_slope, + "gate_plus_intercept": spec.solution_intercept, + }, + "sample_period_seconds": trace["sample_period_seconds"], + "retained_samples": int(len(trace["projected_velocity"])), + "retained_time_seconds": trace["selected_time"].tolist(), + "retained_gate_minus": trace["selected_gates"][:, 0].tolist(), + "retained_gate_plus": trace["selected_gates"][:, 1].tolist(), + "retained_line_distance": trace["selected_line_distance"].tolist(), + "path_coordinate": trace["path_coordinate"].tolist(), + "projected_drift_velocity_v_per_s": trace["projected_velocity"].tolist(), + } + + +def analyze_pair(drift_dir: Path, spec: PairSpec, settings: dict) -> dict: + traces = [ + load_trace( + drift_dir, + trace_spec, + spec.reference_gate, + **settings, + ) + for trace_spec in spec.traces + ] + design = np.vstack([trace["design"] for trace in traces]) + target = np.concatenate([trace["projected_velocity"] for trace in traces]) + constant = fit_columns(design, target, [0, 1]) + local_affine = fit_columns(design, target, [0, 1, 2, 3]) + constant_forward = forward_block_test(traces, [0, 1]) + affine_forward = forward_block_test(traces, [0, 1, 2, 3]) + affine_parameters = local_affine["parameters"] + published = np.asarray(spec.published_bias_at_reference) + intercept = affine_parameters[:2] + return { + "reference_gate": list(spec.reference_gate), + "published_constant_bias_at_reference_v_per_s": published.tolist(), + "traces": [serializable_trace(trace) for trace in traces], + "constant_model": { + "definition": "B(G) = b", + "bias_v_per_s": constant["parameters"].tolist(), + "rank": constant["rank"], + "condition_number": constant["condition_number"], + "in_sample_rmse_v_per_s": constant["rmse"], + "in_sample_r_squared": constant["r_squared"], + "forward_block": constant_forward, + }, + "local_affine_model": { + "definition": "B_i(G_i) = b_i + k_i (G_i - G_ref_i)", + "bias_at_reference_v_per_s": intercept.tolist(), + "local_slopes_per_s": affine_parameters[2:].tolist(), + "rank": local_affine["rank"], + "condition_number": local_affine["condition_number"], + "in_sample_rmse_v_per_s": local_affine["rmse"], + "in_sample_r_squared": local_affine["r_squared"], + "forward_block": affine_forward, + "reference_bias_error_v_per_s": (intercept - published).tolist(), + }, + "diagnostic": { + "in_sample_rmse_ratio_affine_over_constant": ( + local_affine["rmse"] / constant["rmse"]), + "forward_test_rmse_ratio_affine_over_constant": ( + affine_forward["test_rmse"] / constant_forward["test_rmse"]), + "affine_improves_forward_test": bool( + affine_forward["test_rmse"] < constant_forward["test_rmse"]), + }, + "_plot": { + "traces": traces, + "constant_parameters": constant["parameters"], + "affine_parameters": affine_parameters, + }, + } + + +def headroom_sensitivity(drift_dir: Path, base_settings: dict) -> List[dict]: + records = [] + for headroom in (0.03, 0.05, 0.08, 0.10): + settings = dict(base_settings) + settings["terminal_headroom"] = headroom + pair_ratios = {} + for spec in PAIR_SPECS: + pair = analyze_pair(drift_dir, spec, settings) + pair_ratios[spec.name] = pair["diagnostic"][ + "forward_test_rmse_ratio_affine_over_constant"] + records.append({ + "terminal_headroom_v": headroom, + "forward_test_rmse_ratios_affine_over_constant": pair_ratios, + "affine_improves_both": bool(all( + ratio < 1.0 for ratio in pair_ratios.values())), + }) + return records + + +def plot_report(report: dict, output: Path) -> None: + colors = {"alpha": "#4477AA", "beta": "#EE6677"} + fig, axes = plt.subplots(2, 2, figsize=(9.2, 7.0)) + for column, pair_name in enumerate(("experiment_1", "experiment_2")): + pair = report["pairs"][pair_name] + plot_data = pair["_plot"] + path_axis = axes[0, column] + velocity_axis = axes[1, column] + for trace in plot_data["traces"]: + spec = trace["spec"] + color = colors[spec.task] + path_axis.plot( + trace["raw_gate_minus"], trace["raw_gate_plus"], + color=color, alpha=0.24, linewidth=1.0) + gates = trace["selected_gates"] + path_axis.plot( + gates[:, 0], gates[:, 1], "o-", color=color, + markersize=3.0, linewidth=1.2, label=f"task {spec.task}") + x_line = np.linspace(gates[:, 0].min(), gates[:, 0].max(), 100) + path_axis.plot( + x_line, spec.solution_slope * x_line + spec.solution_intercept, + "--", color=color, linewidth=1.0) + + order = np.argsort(trace["path_coordinate"]) + coordinate = trace["path_coordinate"][order] + observed = trace["projected_velocity"][order] + design = trace["design"][order] + constant_prediction = design[:, :2] @ plot_data["constant_parameters"] + affine_prediction = design @ plot_data["affine_parameters"] + velocity_axis.plot( + coordinate, observed, "o", color=color, markersize=3.5, + label=f"task {spec.task} measured") + velocity_axis.plot( + coordinate, constant_prediction, ":", color=color, + linewidth=1.3) + velocity_axis.plot( + coordinate, affine_prediction, "-", color=color, + linewidth=1.5) + + path_axis.set_title( + f"{chr(ord('A') + column)} Published drift: {pair_name.replace('_', ' ')}") + path_axis.set_xlabel("gate voltage minus (V)") + path_axis.set_ylabel("gate voltage plus (V)") + path_axis.legend(frameon=False, fontsize=8) + path_axis.grid(alpha=0.18) + + ratio = pair["diagnostic"]["forward_test_rmse_ratio_affine_over_constant"] + velocity_axis.set_title( + f"{chr(ord('C') + column)} Held-out RMSE ratio affine/constant = {ratio:.2f}") + velocity_axis.set_xlabel("position along solution line (V)") + velocity_axis.set_ylabel("tangential drift (V/s)") + velocity_axis.legend(frameon=False, fontsize=7) + velocity_axis.grid(alpha=0.18) + + fig.suptitle( + "Released physical drift varies with local gate state\n" + "dots: measured projection; dotted: constant bias; solid: per-edge affine bias", + fontsize=11) + fig.tight_layout() + output.parent.mkdir(parents=True, exist_ok=True) + fig.savefig(output, dpi=180) + plt.close(fig) + + +def strip_plot_data(report: dict) -> dict: + clean = dict(report) + clean["pairs"] = {} + for name, pair in report["pairs"].items(): + clean["pairs"][name] = {key: value for key, value in pair.items() if key != "_plot"} + return clean + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument( + "--artifact-root", type=Path, required=True, + help="Root of the extracted Zenodo source tree") + parser.add_argument( + "--json", type=Path, + default=Path("results/physical_bias/p0_state_dependence.json")) + parser.add_argument( + "--figure", type=Path, + default=Path("results/figs/physical_bias_state_dependence.png")) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + root = args.artifact_root.resolve() + if root.name != SOURCE_TREE: + raise ValueError(f"expected source root {SOURCE_TREE}, received {root.name}") + drift_dir = root / "small network" / "DriftTests" + settings = { + "minimum_time": 1.05, + "terminal_headroom": 0.05, + "maximum_line_distance": 0.03, + "trim_selected_ends": 1, + } + report = { + "analysis": "published_physical_drift_state_dependence_diagnostic", + "confirmatory": False, + "supports_task_learning_improvement": False, + "provenance": { + "zenodo_record": ZENODO_RECORD, + "doi": ZENODO_DOI, + "release": RELEASE, + "source_tree": SOURCE_TREE, + }, + "identification": { + "observable": "tangential gate velocity after reaching a one-task solution line", + "assumption": ( + "the clean force has zero tangential projection on the published solution line" + ), + "model_restriction": "each edge bias is affine in its own local gate voltage", + "limitation": ( + "the traces identify a local affine surrogate over their visited states, not the " + "complete physical vector field" + ), + }, + "preprocessing": settings, + "pairs": {}, + } + for spec in PAIR_SPECS: + report["pairs"][spec.name] = analyze_pair(drift_dir, spec, settings) + report["headroom_sensitivity"] = headroom_sensitivity(drift_dir, settings) + report["summary"] = { + "forward_test_rmse_ratios_affine_over_constant": [ + report["pairs"][spec.name]["diagnostic"][ + "forward_test_rmse_ratio_affine_over_constant"] + for spec in PAIR_SPECS + ], + "affine_improves_both_forward_tests": bool(all( + report["pairs"][spec.name]["diagnostic"][ + "affine_improves_forward_test"] + for spec in PAIR_SPECS + )), + "affine_improves_both_for_all_headroom_thresholds": bool(all( + record["affine_improves_both"] + for record in report["headroom_sensitivity"] + )), + } + plot_report(report, args.figure) + serializable = strip_plot_data(report) + args.json.parent.mkdir(parents=True, exist_ok=True) + args.json.write_text(json.dumps(serializable, indent=2) + "\n") + print(json.dumps(serializable["summary"], indent=2)) + print(f"wrote {args.json}") + print(f"wrote {args.figure}") + + +if __name__ == "__main__": + main() diff --git a/results/figs/physical_bias_state_dependence.png b/results/figs/physical_bias_state_dependence.png new file mode 100644 index 0000000..6e15af6 Binary files /dev/null and b/results/figs/physical_bias_state_dependence.png differ diff --git a/results/figs/physical_bias_state_dependence_caption.md b/results/figs/physical_bias_state_dependence_caption.md new file mode 100644 index 0000000..51d63dc --- /dev/null +++ b/results/figs/physical_bias_state_dependence_caption.md @@ -0,0 +1,15 @@ +**Released physical drift contains a locally predictable state-dependent +component.** A--B, gate-voltage trajectories from the four small-network +`DriftTests` files released with Dillavou et al. (Zenodo 15692914). Colored +points are the retained pre-saturation samples within 30 mV of the published +single-task solution lines; faint curves show the complete post-initialization +traces. C--D, tangential drift velocity along each solution line. A constant +bias model (dotted) is compared with a per-edge local affine model +`B_i(G_i)=b_i+k_i(G_i-G_ref_i)` (solid). With the pre-saturation threshold +fixed at 50 mV before each trace's observed terminal gate plateau, the affine +model reduces forward time-block test RMSE to 0.21 and 0.54 of the constant +model in the two task pairs. The direction holds for terminal headrooms of 30, +50, 80 and 100 mV using unsmoothed centered-difference velocities. This +descriptive reanalysis establishes a measured state-dependent component +representable by the proposed local predictor. It does not demonstrate that +SDIL improves physical task learning; that is the prospective P1 test. diff --git a/results/physical_bias/p0_state_dependence.json b/results/physical_bias/p0_state_dependence.json new file mode 100644 index 0000000..ef641c2 --- /dev/null +++ b/results/physical_bias/p0_state_dependence.json @@ -0,0 +1,901 @@ +{ + "analysis": "published_physical_drift_state_dependence_diagnostic", + "confirmatory": false, + "supports_task_learning_improvement": false, + "provenance": { + "zenodo_record": "15692914", + "doi": "10.5281/zenodo.15692914", + "release": "v1.0.1", + "source_tree": "maguzj-imperfect-learning-physical-systems-71b8d72" + }, + "identification": { + "observable": "tangential gate velocity after reaching a one-task solution line", + "assumption": "the clean force has zero tangential projection on the published solution line", + "model_restriction": "each edge bias is affine in its own local gate voltage", + "limitation": "the traces identify a local affine surrogate over their visited states, not the complete physical vector field" + }, + "preprocessing": { + "minimum_time": 1.05, + "terminal_headroom": 0.05, + "maximum_line_distance": 0.03, + "trim_selected_ends": 1 + }, + "pairs": { + "experiment_1": { + "reference_gate": [ + 3.0, + 3.5 + ], + "published_constant_bias_at_reference_v_per_s": [ + 2.9, + 4.7 + ], + "traces": [ + { + "source_file": { + "path": "/scratch/yurenh2/imperfect-learning-physical-systems-v1.0.1/maguzj-imperfect-learning-physical-systems-71b8d72/small network/DriftTests/exp1DriftTest_1.mat", + "sha256": "06dc0a494d255304e40b372bcf85a30df928248b46b8c9884008e52beabcb79f" + }, + "task": "beta", + "solution_line": { + "gate_plus_slope": 0.43914, + "gate_plus_intercept": 1.6061 + }, + "sample_period_seconds": 0.030553000000000274, + "retained_samples": 13, + "retained_time_seconds": [ + 1.095956, + 1.126507, + 1.157059, + 1.187613, + 1.218165, + 1.248715, + 1.279265, + 1.309815, + 1.340367, + 1.370923, + 1.401476, + 1.432031, + 1.462575 + ], + "retained_gate_minus": [ + 3.086655100456178, + 3.2045506972079334, + 3.325833171568152, + 3.4500186838784823, + 3.577671713740335, + 3.707743941893947, + 3.841203047656023, + 3.9774845514251513, + 4.1206204503542665, + 4.266014267689023, + 4.417133520980944, + 4.5722041314827395, + 4.731709938852762 + ], + "retained_gate_plus": [ + 2.9615825487722023, + 3.0177079491410272, + 3.073107590022324, + 3.1284265909605615, + 3.184874551101621, + 3.241806350901032, + 3.299221990358795, + 3.3585729884499664, + 3.419052945743958, + 3.4806618622407712, + 3.543964217541817, + 3.610008330906856, + 3.67516540489825 + ], + "retained_line_distance": [ + 8.08292293261819e-06, + 0.003993462730446216, + 0.005952541765860968, + 0.00667053642362007, + 0.00702799652153725, + 0.006855754296051377, + 0.005764726401341312, + 0.005310896245919922, + 0.0031347398202806855, + 0.0010844030170761051, + -0.0017174891048780722, + -0.003597770655753531, + -0.00807352861708409 + ], + "path_coordinate": [ + 4.016946619401107, + 4.147459258818917, + 4.28078112801541, + 4.4167286098466505, + 4.556304898876256, + 4.698290759784522, + 4.843572204653746, + 4.992216018121322, + 5.147589681075312, + 5.305484636124792, + 5.4693027251830655, + 5.6378410997238895, + 5.810083703241586 + ], + "projected_drift_velocity_v_per_s": [ + 4.236218003994951, + 4.31786355506276, + 4.40659149235734, + 4.508951804944697, + 4.608070247817559, + 4.701592565916367, + 4.810560692910009, + 4.975566045433641, + 5.126469375714378, + 5.264586676637202, + 5.438832155057525, + 5.57754355941491, + 5.619030794759777 + ] + }, + { + "source_file": { + "path": "/scratch/yurenh2/imperfect-learning-physical-systems-v1.0.1/maguzj-imperfect-learning-physical-systems-71b8d72/small network/DriftTests/exp1DriftTest_2.mat", + "sha256": "a3969a1ab6ccf616a6b63be13e633301cd276ebf9cebe4f83a5ab95d1673d151" + }, + "task": "alpha", + "solution_line": { + "gate_plus_slope": 2.7257, + "gate_plus_intercept": -3.3003 + }, + "sample_period_seconds": 0.03055399999999997, + "retained_samples": 9, + "retained_time_seconds": [ + 1.095956, + 1.126512, + 1.157067, + 1.187627, + 1.218176, + 1.248734, + 1.279291, + 1.309842, + 1.340396 + ], + "retained_gate_minus": [ + 2.5433031641269532, + 2.598460885179074, + 2.6534573263450776, + 2.71030848620143, + 2.7676434857161345, + 2.82731704357954, + 2.8861035620693003, + 2.947147998964703, + 3.009805234721279 + ], + "retained_gate_plus": [ + 3.628797437639523, + 3.775723413892394, + 3.9262781875829047, + 4.081510077970818, + 4.238354767219904, + 4.399876573166392, + 4.566720615354751, + 4.738967533728041, + 4.913875570222266 + ], + "retained_line_distance": [ + -0.0010966631510683081, + -0.002273725567717279, + -0.0020495107701148916, + -0.0019555903060644014, + -0.0017604085000549497, + -0.0021497555546336586, + 0.00012679705803813525, + 0.0021444997056754675, + 0.0035646554470346575 + ], + "path_coordinate": [ + 4.282748163383154, + 4.439682006812766, + 4.59996705960825, + 4.765281866414429, + 4.932277437071425, + 5.1044694104998145, + 5.281352440997655, + 5.464085451263993, + 5.649872247298023 + ], + "projected_drift_velocity_v_per_s": [ + 5.073957642099754, + 5.190865900919979, + 5.327645274680347, + 5.4380042889637465, + 5.5506902338683854, + 5.711775466397501, + 5.884944630487621, + 6.030922317661434, + 5.78602799059672 + ] + } + ], + "constant_model": { + "definition": "B(G) = b", + "bias_v_per_s": [ + 3.2711869099585456, + 4.716905017637164 + ], + "rank": 2, + "condition_number": 2.4047328345335246, + "in_sample_rmse_v_per_s": 0.40489007770456675, + "in_sample_r_squared": 0.39348382809096927, + "forward_block": { + "split": "first 60% of each retained trace trains; final 40% tests", + "trace_splits": [ + { + "source": "exp1DriftTest_1.mat", + "train_samples": 7, + "test_samples": 6 + }, + { + "source": "exp1DriftTest_2.mat", + "train_samples": 5, + "test_samples": 4 + } + ], + "parameters": [ + 2.911080025813414, + 4.594710870787166 + ], + "train_rank": 2, + "train_condition_number": 2.395452097552033, + "train_rmse": 0.18337490926920424, + "test_rmse": 0.7471220478750839, + "test_r_squared": -4.401819369148549 + } + }, + "local_affine_model": { + "definition": "B_i(G_i) = b_i + k_i (G_i - G_ref_i)", + "bias_at_reference_v_per_s": [ + 2.6533247829167026, + 4.543278430598633 + ], + "local_slopes_per_s": [ + 0.8613144228168172, + 0.6281431773240994 + ], + "rank": 4, + "condition_number": 8.410487632494219, + "in_sample_rmse_v_per_s": 0.06983797734487046, + "in_sample_r_squared": 0.9819552270127793, + "forward_block": { + "split": "first 60% of each retained trace trains; final 40% tests", + "trace_splits": [ + { + "source": "exp1DriftTest_1.mat", + "train_samples": 7, + "test_samples": 6 + }, + { + "source": "exp1DriftTest_2.mat", + "train_samples": 5, + "test_samples": 4 + } + ], + "parameters": [ + 2.8030215562644067, + 4.40110352313821, + 0.6889298797902501, + 0.7452208221872205 + ], + "train_rank": 4, + "train_condition_number": 11.121808766273288, + "train_rmse": 0.006170014713261239, + "test_rmse": 0.15556417672311493, + "test_r_squared": 0.7658057963184172 + }, + "reference_bias_error_v_per_s": [ + -0.24667521708329732, + -0.15672156940136706 + ] + }, + "diagnostic": { + "in_sample_rmse_ratio_affine_over_constant": 0.17248626526192287, + "forward_test_rmse_ratio_affine_over_constant": 0.20821789045787162, + "affine_improves_forward_test": true + } + }, + "experiment_2": { + "reference_gate": [ + 3.1, + 4.3 + ], + "published_constant_bias_at_reference_v_per_s": [ + -0.3, + 2.0 + ], + "traces": [ + { + "source_file": { + "path": "/scratch/yurenh2/imperfect-learning-physical-systems-v1.0.1/maguzj-imperfect-learning-physical-systems-71b8d72/small network/DriftTests/exp2DriftTest_1.mat", + "sha256": "5d29c3e4e0d88f21d32e046b55519579f68e100ca44aa101c3336d589e628b77" + }, + "task": "beta", + "solution_line": { + "gate_plus_slope": 0.74821, + "gate_plus_intercept": 1.9224 + }, + "sample_period_seconds": 0.0306280000000001, + "retained_samples": 49, + "retained_time_seconds": [ + 1.099045, + 1.129673, + 1.160302, + 1.190932, + 1.221559, + 1.252181, + 1.282806, + 1.313436, + 1.34406, + 1.374678, + 1.405304, + 1.435927, + 1.466557, + 1.497188, + 1.527917, + 1.558541, + 1.589169, + 1.619801, + 1.650432, + 1.681061, + 1.711685, + 1.742315, + 1.772945, + 1.803576, + 1.834198, + 1.864831, + 1.895455, + 1.926073, + 1.956699, + 1.987322, + 2.017955, + 2.048582, + 2.079215, + 2.109842, + 2.140472, + 2.171099, + 2.201721, + 2.232343, + 2.262973, + 2.293597, + 2.324216, + 2.354845, + 2.385478, + 2.416105, + 2.446727, + 2.477349, + 2.507979, + 2.538703, + 2.569333 + ], + "retained_gate_minus": [ + 2.7862713125626843, + 2.805060419295351, + 2.8267525639781295, + 2.847396389401146, + 2.868604694425572, + 2.8874744411012974, + 2.9101342651007798, + 2.9318264097835587, + 2.9552119932705687, + 2.9779524572131097, + 3.000692921155651, + 3.023755944870426, + 3.048028567731082, + 3.06972071241386, + 3.0964125335662755, + 3.120362596654696, + 3.1474576175224045, + 3.173746238959527, + 3.1997929405674728, + 3.22575900223236, + 3.254144262189006, + 3.2797071241386004, + 3.3099471027855967, + 3.338574282571419, + 3.3686529813322985, + 3.39857040020706, + 3.428649098967938, + 3.4602599566469316, + 3.4917095344398072, + 3.522917192403507, + 3.558076207577081, + 3.5923481833770103, + 3.6275071985505845, + 3.662666213724158, + 3.7004057070756096, + 3.7387096800284705, + 3.77475573457569, + 3.814672506389725, + 3.8546699181468185, + 3.89539308939144, + 3.937083939952765, + 3.9790167103432657, + 4.020626920961533, + 4.063849930440972, + 4.106992299977353, + 4.1499733896276165, + 4.192228719790353, + 4.233677650522502, + 4.2742395418810055 + ], + "retained_gate_plus": [ + 4.002402293830277, + 4.017723883011421, + 4.034335711281504, + 4.05078625966547, + 4.066107848846615, + 4.081751997799993, + 4.0992508654437225, + 4.11618525348604, + 4.132474521983888, + 4.15037658934291, + 4.168520576531107, + 4.185696884402601, + 4.203518311818565, + 4.220855899576176, + 4.240773965511663, + 4.260450111617976, + 4.27996497783817, + 4.298834724513896, + 4.319155990164678, + 4.339315975929341, + 4.360040441295416, + 4.37955530751561, + 4.402215131515093, + 4.4246330356854, + 4.445760700766767, + 4.468178604937074, + 4.49116098870879, + 4.514546572195801, + 4.537690235853636, + 4.561720938885115, + 4.587525720663884, + 4.612040263353716, + 4.637603125303309, + 4.664940066000194, + 4.693164046070724, + 4.721065466369019, + 4.7474347277492, + 4.775900627648905, + 4.806624445954253, + 4.835896745284545, + 4.865814164159307, + 4.896376702578538, + 4.925568361965771, + 4.956130900385001, + 4.985, + 5.014998058817821, + 5.044270358148112, + 5.0725749781617, + 5.097492720566826 + ], + "retained_line_distance": [ + -0.003774252312594643, + -0.002762670519732154, + -0.002457169276120157, + -0.0016527732559892293, + -0.002090490432055128, + -0.0008689490514576152, + -0.0004329261236608246, + 0.00013084467331587446, + -0.0008364329146888713, + -0.00012588301081632548, + 0.0007783690580801915, + 0.0007145726043557115, + 0.00044266577289839764, + 0.0013292735115833746, + 0.0012868198080744596, + 0.0026932027709954294, + 0.002086362297624157, + 0.0014460823738319949, + 0.002112945337078738, + 0.0026989834892726305, + 0.0022876943909292975, + 0.0025987432645467982, + 0.002625942276885615, + 0.003425638436819979, + 0.0023226770019321723, + 0.002349413711770708, + 0.002731502208737495, + 0.002518538300423075, + 0.0022084921583465293, + 0.0027536171849184376, + 0.00235203643908527, + 0.0014487871017293524, + 0.0008535041908711466, + 0.0016787038235268033, + 0.001668225827745958, + 0.0010613085191844862, + 0.0005802898698007323, + -0.0005408550329912286, + 9.75769721471591e-05, + -0.0008609937035399608, + -0.001882744860066258, + -0.002532886806753963, + -0.004087434492723206, + -0.005510535889506739, + -0.008241242475830168, + -0.00997138569411014, + -0.011847845716786744, + -0.014016014743249651, + -0.01836460445811316 + ], + "path_coordinate": [ + 4.628700926136281, + 4.652924021089726, + 4.6802445014735605, + 4.706628985877694, + 4.732789102481384, + 4.757270004685695, + 4.785896703351568, + 4.813410423597927, + 4.841893579274408, + 4.870826395156777, + 4.899904140936038, + 4.928660436681094, + 4.958771722976321, + 4.986526993050834, + 5.0198313601027085, + 5.050795506054081, + 5.084181160219508, + 5.116534660776474, + 5.149564038549772, + 5.182432229003467, + 5.217575610866822, + 5.249734484653762, + 5.287522355624115, + 5.3238739489307445, + 5.360614795777427, + 5.39799946729752, + 5.435851443353713, + 5.475171749616551, + 5.514217991205811, + 5.553601940251987, + 5.5972125105707775, + 5.639339880167716, + 5.682805520589612, + 5.727333980255391, + 5.774460005970037, + 5.8218447635405495, + 5.866503744890513, + 5.915518019987271, + 5.965949541510039, + 6.016092590146521, + 6.067396927168149, + 6.1192814460798495, + 6.170086426022458, + 6.223004023147621, + 6.274842543606193, + 6.327228268806916, + 6.378598097821887, + 6.428742533365871, + 6.476147709081599 + ], + "projected_drift_velocity_v_per_s": [ + 0.7508246006659008, + 0.8414299465725285, + 0.8766874316465273, + 0.8577726510194819, + 0.82680117750534, + 0.8670987148152298, + 0.9165064297815321, + 0.914178125758254, + 0.9375275263588382, + 0.9472034122255371, + 0.9442441560240576, + 0.9610512771772265, + 0.9445917193305037, + 0.9948211100106393, + 1.0473958781155777, + 1.0505695225846392, + 1.0731193286458487, + 1.0672494071443286, + 1.0757028704320981, + 1.1103447123411982, + 1.0987501489464184, + 1.1418012529757333, + 1.2102236530082084, + 1.1932894339307194, + 1.2101100630989776, + 1.2282153572495578, + 1.2601249389462414, + 1.279580401767342, + 1.2805143609502787, + 1.354857382175512, + 1.3995698828247278, + 1.397204530067973, + 1.4364072799172218, + 1.4962246174920166, + 1.542857291097899, + 1.5027722104082968, + 1.5295091183907252, + 1.6235458402160727, + 1.6419256795601518, + 1.6564762769665926, + 1.6847680247757024, + 1.6762371568553536, + 1.6931601843080926, + 1.710329030699083, + 1.7017870429641289, + 1.6939173108439396, + 1.6546353289335909, + 1.5898177070821977, + 1.542909605414097 + ] + }, + { + "source_file": { + "path": "/scratch/yurenh2/imperfect-learning-physical-systems-v1.0.1/maguzj-imperfect-learning-physical-systems-71b8d72/small network/DriftTests/exp2DriftTest_2.mat", + "sha256": "808a0d0ed8824b1717597f63e38ec4412034d9171f0d58edb15d098862ddb1ed" + }, + "task": "alpha", + "solution_line": { + "gate_plus_slope": 2.5678, + "gate_plus_intercept": -2.901 + }, + "sample_period_seconds": 0.03062599999999982, + "retained_samples": 19, + "retained_time_seconds": [ + 1.099048, + 1.129669, + 1.16029, + 1.190925, + 1.22154, + 1.252169, + 1.282799, + 1.313423, + 1.344047, + 1.374672, + 1.405303, + 1.43593, + 1.466554, + 1.497174, + 1.527901, + 1.558528, + 1.589145, + 1.619774, + 1.650404 + ], + "retained_gate_minus": [ + 2.7462739008055905, + 2.7657081270827266, + 2.7834489145556316, + 2.801592901743829, + 2.820220728590378, + 2.840783914070336, + 2.8594117409168853, + 2.88013620628296, + 2.899973632275389, + 2.920859377527581, + 2.9411000032353036, + 2.9613406289430264, + 2.9832746934549808, + 3.005289397909994, + 3.0258525833899514, + 3.0464157688699083, + 3.066414474748455, + 3.085042301595005, + 3.1010090103206185 + ], + "retained_gate_plus": [ + 4.179245688957909, + 4.224645976899932, + 4.271336503930894, + 4.319075350221619, + 4.364233718334466, + 4.416085201721182, + 4.464953007214727, + 4.517530250088971, + 4.569139813646511, + 4.622765375780517, + 4.678810136206283, + 4.7325969782264075, + 4.787754699278528, + 4.842670500501472, + 4.897425021838299, + 4.950647384257013, + 4.999676469636675, + 5.04378651848976, + 5.084106490019089 + ], + "retained_line_distance": [ + 0.0102928838202821, + 0.008658815167945599, + 0.00907096246968139, + 0.00948782119683568, + 0.008517390467588221, + 0.00817240292568413, + 0.008548093744283286, + 0.008316192117803585, + 0.00855969965310696, + 0.008557937989690165, + 0.010035224450619176, + 0.010693132578076012, + 0.01027052064448047, + 0.009684975329273742, + 0.010393474216119818, + 0.010545966376681908, + 0.009702755839110155, + 0.008351899455035996, + 0.008105371925304106 + ], + "path_coordinate": [ + 4.890951292266569, + 4.9403092208682535, + 4.990254901253943, + 5.041323756195643, + 5.0901636211405865, + 5.14594266657955, + 5.198239102435053, + 5.254752960510771, + 5.310043205804902, + 5.367592447900904, + 5.42716186727808, + 5.484627286970569, + 5.54398466879315, + 5.603145885589996, + 5.661630073480702, + 5.718686547299655, + 5.771630748549389, + 5.819493756497868, + 5.862859354796883 + ], + "projected_drift_velocity_v_per_s": [ + 1.6087724632953608, + 1.6214951991668174, + 1.64904715422736, + 1.6311393555026201, + 1.7081795573430563, + 1.7642402757671922, + 1.7763921088543277, + 1.8254327222088798, + 1.84230622027992, + 1.9119476944202922, + 1.9105188758276812, + 1.9072829408108736, + 1.9351866959457025, + 1.9177544493326175, + 1.883114736635644, + 1.79608350237785, + 1.6459721135468859, + 1.4892302050103952, + 1.2620512042404304 + ] + } + ], + "constant_model": { + "definition": "B(G) = b", + "bias_v_per_s": [ + 0.23663724932160932, + 1.7766114352081004 + ], + "rank": 2, + "condition_number": 3.9628889816190975, + "in_sample_rmse_v_per_s": 0.26995705909308504, + "in_sample_r_squared": 0.3964148715513893, + "forward_block": { + "split": "first 60% of each retained trace trains; final 40% tests", + "trace_splits": [ + { + "source": "exp2DriftTest_1.mat", + "train_samples": 29, + "test_samples": 20 + }, + { + "source": "exp2DriftTest_2.mat", + "train_samples": 11, + "test_samples": 8 + } + ], + "parameters": [ + -0.16524636483433422, + 1.9423235060216164 + ], + "train_rank": 2, + "train_condition_number": 3.9850204349776597, + "train_rmse": 0.13829635115886643, + "test_rmse": 0.48616449768925685, + "test_r_squared": -7.221033907983498 + } + }, + "local_affine_model": { + "definition": "B_i(G_i) = b_i + k_i (G_i - G_ref_i)", + "bias_at_reference_v_per_s": [ + -0.2839863287520495, + 2.099298282479029 + ], + "local_slopes_per_s": [ + 0.9254562644135597, + -0.17006402648360702 + ], + "rank": 4, + "condition_number": 11.267646483964826, + "in_sample_rmse_v_per_s": 0.1071040687889852, + "in_sample_r_squared": 0.9049917992864138, + "forward_block": { + "split": "first 60% of each retained trace trains; final 40% tests", + "trace_splits": [ + { + "source": "exp2DriftTest_1.mat", + "train_samples": 29, + "test_samples": 20 + }, + { + "source": "exp2DriftTest_2.mat", + "train_samples": 11, + "test_samples": 8 + } + ], + "parameters": [ + -0.11013912378906168, + 1.892594891638608, + 0.5000251775829843, + 0.6507436117634928 + ], + "train_rank": 4, + "train_condition_number": 17.497835518797263, + "train_rmse": 0.021606899405393228, + "test_rmse": 0.2641280985833621, + "test_r_squared": -1.426549566890654 + }, + "reference_bias_error_v_per_s": [ + 0.0160136712479505, + 0.09929828247902917 + ] + }, + "diagnostic": { + "in_sample_rmse_ratio_affine_over_constant": 0.3967448347111167, + "forward_test_rmse_ratio_affine_over_constant": 0.5432895652372083, + "affine_improves_forward_test": true + } + } + }, + "headroom_sensitivity": [ + { + "terminal_headroom_v": 0.03, + "forward_test_rmse_ratios_affine_over_constant": { + "experiment_1": 0.4819119278880803, + "experiment_2": 0.5769371754474453 + }, + "affine_improves_both": true + }, + { + "terminal_headroom_v": 0.05, + "forward_test_rmse_ratios_affine_over_constant": { + "experiment_1": 0.20821789045787162, + "experiment_2": 0.5432895652372083 + }, + "affine_improves_both": true + }, + { + "terminal_headroom_v": 0.08, + "forward_test_rmse_ratios_affine_over_constant": { + "experiment_1": 0.20821789045787162, + "experiment_2": 0.40322524115717306 + }, + "affine_improves_both": true + }, + { + "terminal_headroom_v": 0.1, + "forward_test_rmse_ratios_affine_over_constant": { + "experiment_1": 0.22615952365875847, + "experiment_2": 0.2908505511376861 + }, + "affine_improves_both": true + } + ], + "summary": { + "forward_test_rmse_ratios_affine_over_constant": [ + 0.20821789045787162, + 0.5432895652372083 + ], + "affine_improves_both_forward_tests": true, + "affine_improves_both_for_all_headroom_thresholds": true + } +} -- cgit v1.2.3