D = 0.01
N_ERRORS = 1e6
N_TRIALS = 100
N_CYCLES = np.logspace(1, 3, 10).astype(np.int)
RECORDS = []
for trial in tqdm(range(N_TRIALS)):
    for n_cycles in N_CYCLES:
        n = int(N_ERRORS / n_cycles)
        channel = Channel(kx=0.7, ky=0.2, kz=0.1,
                          Q=np.linalg.qr(np.random.randn(3,3))[0],
                          n=n, d=D)

        RECORDS.append({
                "trial": trial,
                "cycle_length": n,
                "n_cycles": n_cycles,
                "time": 0,
                "Mdist": np.linalg.norm(channel.Mhat-channel.C),
                "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3))
            })
        for cycle in range(n_cycles):
            channel.update()
            RECORDS.append({
                    "trial": trial,
                    "cycle_length": n,
                    "n_cycles": n_cycles,
                    "time": (cycle+1)*n,
                    "Mdist": np.linalg.norm(channel.Mhat-channel.C),
                    "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3))
                })

df = pd.DataFrame(RECORDS)
df.to_csv("{}errorsd{}.csv".format(N_ERRORS,D))

df["cycle_length"] = (N_ERRORS / df["n_cycles"]).astype(np.int)

df.tail(10)

PAL = sns.color_palette("hls", len(N_CYCLES))
fig, ax = plt.subplots(1, 1, figsize=(8,6))

for idx, n_cycles in enumerate(N_CYCLES):
    sel = (df["n_cycles"] == n_cycles)
    subdf = df.loc[sel, :]
    v = subdf.groupby("time").mean()
    s = subdf.groupby("time").std()
    t = v.index.values
    y = v["Mdist"].values
    e = s["Mdist"].values
    ax.loglog(t, y, label=str(subdf.iloc[0, 2]), c=PAL[idx])
    ax.fill_between(t, y-e, y+e, alpha=0.1, color=PAL[idx])
plt.title("Recover error over time for varied ratios of cycles to realignments")
plt.xlabel("Time [cycles]")
plt.ylabel("Basis recovery error")
plt.legend()

"""
Explanation: Original basis Q0
Recovered basis Qc (Controlled-bsais)
Effected basis Qeff = Qt.T * Q0
Use effected basis for error sampling
Learn Qt progressively better
When data comes in from the Qeff alignment, you must transform it back to the standard basis before average with the existing channel estimate

Error x Time x Cycle_ratio
End of explanation
"""


D = 0.01
N_TRIALS = 100
MAX_N = int(1e8)
N_STEP = int(1e5)
RECORDS = []
for trial in tqdm(range(N_TRIALS)):
    channel = Channel(kx=0.7, ky=0.2, kz=0.1,
                      Q=np.linalg.qr(np.random.randn(3,3))[0],
                      n=N_STEP, d=D)
    pxhat, pyhat, pzhat = list(np.linalg.svd(channel.Mhat)[1])
    RECORDS.append({
            "trial": trial,
            "time": 0,
            "Mdist": np.linalg.norm(channel.Mhat-channel.C),
            "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3)),
            "pxval": channel.kx, "pyval": channel.ky, "pzval": channel.kz,
            "pxhat": pxhat, "pyhat": pyhat, "pzhat": pzhat
        })
    for time in range(0, MAX_N, N_STEP):
        channel.update()
        pxhat, pyhat, pzhat = list(np.linalg.svd(channel.Mhat)[1])
        RECORDS.append({
                "trial": trial,
                "time": time,
                "Mdist": np.linalg.norm(channel.Mhat-channel.C),
                "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3)),
                "pxval": channel.kx, "pyval": channel.ky, "pzval": channel.kz,
                "pxhat": pxhat, "pyhat": pyhat, "pzhat": pzhat
            })

df = pd.DataFrame(RECORDS)
df.to_csv("regime1.csv")

df = pd.read_csv("regime1.csv")
v = df.groupby("time").mean()["Qdist"]
s = df.groupby("time").std()["Qdist"]

fig, ax = plt.subplots(1, 1, figsize=(8, 6))
t = v.index.values
y = v.values
e = s.values
ax.plot(t, y,)
ax.fill_between(t, y-e, y+e, alpha=0.25)
plt.ylabel("Measure of orthonormality between $Q_{hat}$ and $Q_{val}$")
plt.xlabel("Time [n_errors]")

df = pd.read_csv("regime1.csv")
v = df.groupby("time").mean()["Mdist"]
s = df.groupby("time").std()["Mdist"]

fig, ax = plt.subplots(1, 1, figsize=(8, 6))
t = v.index.values
y = v.values
e = s.values
ax.loglog(t, y,)
ax.fill_between(t, y-e, y+e, alpha=0.25)
plt.ylabel("Norm distance between $M_{hat}$ and $M_{val}$")
plt.xlabel("Time [n_errors]")

"""
Explanation: Regime 1 basis alignment
End of explanation
"""


D = 0.01
N_TRIALS = 100
MAX_N = int(1e8)
N_STEP = int(1e5)
RECORDS = []
for trial in tqdm(range(N_TRIALS)):
    channel = Channel(kx=0.985, ky=0.01, kz=0.005,
                      Q=np.linalg.qr(np.random.randn(3,3))[0],
                      n=N_STEP, d=D)
    pxhat, pyhat, pzhat = list(np.linalg.svd(channel.Mhat)[1])
    RECORDS.append({
            "trial": trial,
            "time": 0,
            "Mdist": np.linalg.norm(channel.Mhat-channel.C),
            "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3)),
            "pxval": channel.kx, "pyval": channel.ky, "pzval": channel.kz,
            "pxhat": pxhat, "pyhat": pyhat, "pzhat": pzhat
        })
    for time in range(0, MAX_N, N_STEP):
        channel.update()
        pxhat, pyhat, pzhat = list(np.linalg.svd(channel.Mhat)[1])
        RECORDS.append({
                "trial": trial,
                "time": time,
                "Mdist": np.linalg.norm(channel.Mhat-channel.C),
                "Qdist": np.linalg.norm(np.dot(channel.Qc.T, channel.Q) - np.eye(3)),
                "pxval": channel.kx, "pyval": channel.ky, "pzval": channel.kz,
                "pxhat": pxhat, "pyhat": pyhat, "pzhat": pzhat
            })

df = pd.DataFrame(RECORDS)
df.to_csv("regime2.csv")

df = pd.read_csv("regime2.csv")
v = df.groupby("time").mean()["Qdist"]
s = df.groupby("time").std()["Qdist"]

fig, ax = plt.subplots(1, 1, figsize=(8, 6))
t = v.index.values
y = v.values
e = s.values
ax.plot(t, y)
ax.plot(t, y-e, ls="--")
ax.plot(t, y+e, ls="--")
plt.ylabel("Measure of orthonormality between $Q_{hat}$ and $Q_{val}$")
plt.xlabel("Time [n_errors]")

df = pd.read_csv("regime2.csv")
v = df.groupby("time").mean()["Mdist"]
s = df.groupby("time").std()["Mdist"]

fig, ax = plt.subplots(1, 1, figsize=(8, 6))
t = v.index.values
y = v.values
e = s.values
ax.loglog(t, y)
ax.fill_between(t, y-e, y+e, alpha=0.25)
plt.ylabel("Norm distance between $M_{hat}$ and $M_{val}$")
plt.xlabel("Time [n_errors]")

"""
Explanation: Regime 2 basis alignment
End of explanation
"""


df1 = pd.read_csv("regime1.csv")
df1["dpx"] = df1["pxval"] - df1["pxhat"]
df1["dpy"] = df1["pyval"] - df1["pyhat"]
df1["dpz"] = df1["pzval"] - df1["pzhat"]

v1 = df1.groupby("time").mean()
s1 = df1.groupby("time").std()

df2 = pd.read_csv("regime2.csv")
df2["dpx"] = df2["pxval"] - df2["pxhat"]
df2["dpy"] = df2["pyval"] - df2["pyhat"]
df2["dpz"] = df2["pzval"] - df2["pzhat"]

v2 = df2.groupby("time").mean()
s2 = df2.groupby("time").std()


fig, axs = plt.subplots(2, 3, figsize=(12, 8), sharey=True, sharex=True,
                        tight_layout={"h_pad": 1.0, "rect": [0.0, 0.0, 1.0, 0.95]})
for idx, stat in enumerate(["dpx", "dpy", "dpz"]):
    t1 = v1[stat].index.values
    y1 = v1[stat].values
    e1 = s1[stat].values
    axs[0, idx].semilogy(t1, y1, color=sns.color_palette()[idx])
    axs[0, idx].semilogy(t1, y1+e1, ls="--", color=sns.color_palette()[idx])
    axs[0, idx].set_title(stat)
    
    t2 = v2[stat].index.values
    y2 = v2[stat].values
    e2 = s2[stat].values
    axs[1, idx].semilogy(t2, y2, color=sns.color_palette()[idx])
    axs[1, idx].semilogy(t2, y2+e2, ls="--", color=sns.color_palette()[idx])
    axs[1, idx].set_xlabel("Number of errors")

fig.suptitle("Average difference in effective error probability")
axs[0, 0].set_ylabel("kx=0.7, ky=0.2, kz=0.1")
axs[1, 0].set_ylabel("kx=0.985, ky=0.01, kz=0.005")

"""
Explanation: The only thing that matters: effective error probabilities
End of explanation
"""


