app: stacked_cores: 52-xx: add some facilities for plotting 52-xx or gate runs

it's primitive; not the *best* results
This commit is contained in:
colin 2022-11-02 17:21:29 -07:00
parent ff68e57fa5
commit 286a267f75
2 changed files with 102 additions and 0 deletions

View File

@ -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())

View File

@ -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)