diff --git a/crates/applications/stacked_cores/scripts/extract_meas.py b/crates/applications/stacked_cores/scripts/extract_meas.py index 22e6c0e..1d85e0c 100755 --- a/crates/applications/stacked_cores/scripts/extract_meas.py +++ b/crates/applications/stacked_cores/scripts/extract_meas.py @@ -46,6 +46,16 @@ class ParameterizedMeas: def add_meas(self, params: tuple, meas_rows: list): self.meas[tuple(params)] = meas_rows + def all_rows(self) -> list: + # this is just `sum(self.meas.values())` but python is a idiot + rows = [] + for mrows in self.meas.values(): + rows.extend(mrows) + return rows + + def runs(self) -> list: + return self.meas.values() + def __repr__(self) -> str: meas_entries = "\n".join( f" {format_float_tuple(k)}: {indented(format_list(v))}," for (k, v) in sorted(self.meas.items()) diff --git a/crates/applications/stacked_cores/scripts/plot_52xx.py b/crates/applications/stacked_cores/scripts/plot_52xx.py new file mode 100755 index 0000000..9faf792 --- /dev/null +++ b/crates/applications/stacked_cores/scripts/plot_52xx.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +from math import sqrt + +import plotly.express as px +from pandas import DataFrame + +from stacked_cores_52xx import * + +def plot(name: str, x_name: str, y_series: list): + df = DataFrame(data={ x_name: sweep_1d(len(y_series)), "y": y_series }) + fig = px.line(df, x=x_name, y="y", title=name) + fig.show() + +def eval_series(meas: 'ParameterizedMeas', points: list, y_idx: int = -1): + return [sample_all(meas, *p)[y_idx] for p in points] + +def sample_all(meas: 'ParameterizedMeas', a0: float, a1: float) -> tuple: + runs = [extract_transfer_from_meas_rows(r) for r in meas.runs()] + distances = [(distance_to(m, (a0, a1)), m) for m in runs] + + return weighted_sum_of_neighbors_by_inv_distance(distances) + +def extract_transfer_from_meas_rows(meas_rows: list) -> tuple: + return (meas_rows[0].m[0], meas_rows[0].m[1], meas_rows[1].m[2], meas_rows[2].m[3]) + +def interpolate(meas: 'ParameterizedMeas', a0: float, a1: float) -> tuple: + """ + this interpolates a point among four neighboring points in 2d. + the implementation only supports 2d, but the technique is extendable to N dim. + """ + rows = [r.m for r in meas.all_rows()] + distances = [(distance_to(m, (a0, a1)), m) for m in rows] + # a0_below_dist, a0_below_val = min(d for d in distances if d[1][0] <= a0) + # a0_above_dist, a0_above_val = min(d for d in distances if d[1][0] >= a0) + # a1_below_dist, a1_below_val = min(d for d in distances if d[1][1] <= a1) + # a1_above_dist, a1_above_val = min(d for d in distances if d[1][1] >= a1) + a0_below = min((d for d in distances if d[1][0] <= a0), default=None) + a0_above = min((d for d in distances if d[1][0] >= a0), default=None) + a1_below = min((d for d in distances if d[1][1] <= a1), default=None) + a1_above = min((d for d in distances if d[1][1] >= a1), default=None) + + neighbors = [a for a in [a0_below, a0_above, a1_below, a1_above] if a is not None] + return weighted_sum_of_neighbors_by_inv_distance(neighbors) + +def weighted_sum_of_neighbors_by_inv_distance(neighbors: list) -> tuple: + """ + each neighbor is (distance, value). + return a weighted sum of these neighbors, where lower-distance neighbors are more strongly weighted. + """ + D = sum(a[0] for a in neighbors) + weight_n = lambda n: 1/max(n[0], 1e-3) # non-normalized weight for neighbor + W = sum(weight_n(n) for n in neighbors) + weighted_n = lambda n: weighted(n[1], weight_n(n)/W) # normalized weighted contribution for neighbor + return element_sum([weighted_n(n) for n in neighbors]) + +def weighted_sum_of_neighbors(neighbors: list) -> tuple: + """ + each neighbor is (distance, value). + return a weighted sum of these neighbors, where lower-distance neighbors are more strongly weighted. + """ + D = sum(a[0] for a in neighbors) + weight_n = lambda n: D - n[0] # non-normalized weight for neighbor + W = sum(weight_n(n) for n in neighbors) + weighted_n = lambda n: weighted(n[1], weight_n(n)/W) # normalized weighted contribution for neighbor + return element_sum([weighted_n(n) for n in neighbors]) + +def distance_to(p0: tuple, p1: tuple) -> float: + return sqrt(sum((x0-x1)*(x0-x1) for (x0, x1) in zip(p0, p1))) + +def element_sum(lists: list) -> list: + elems = lists[0] + for l in lists[1:]: + for i, e in enumerate(l): + elems[i] += e + return elems + +def weighted(l: list, scale: float) -> list: + return [e*scale for e in l] + + +or_gates = DB + +sweep_1d = lambda points=101: [unit_to_m(x/(points-1)) for x in range(points)] +sweep_a0 = lambda a1, points=101: [(unit_to_m(x/(points-1)), a1) for x in range(points)] +sweep_a1 = lambda a0, points=101: [(a0, unit_to_m(x/(points-1))) for x in range(points)] + +unit_to_m = lambda u: -17000 + 34000 * u + +for name, meas in sorted(or_gates.items()): + trace = eval_series(meas, sweep_a1(-17000)) + plot(f"{name}", "a1", trace)