codexhomeostasis-feedback-lag-capacity.py
homeostasis-feedback-lag-capacity.py
"""Original synthetic feedback curves: offset, finite response time and cap.
Python 3.14, NumPy 2.3.5, Matplotlib 3.10.7. Run from _media; writes to CWD.
Exact analytic curves, invented parameters; no human measurements or fitted data.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def responses(t):
instantaneous = -np.expm1(-5*t) / 5
lagged = .2 + np.exp(-t) * (-.2*np.cos(2*t) + .4*np.sin(2*t))
lagged_u = .8 + np.exp(-t) * (-.8*np.cos(2*t) - .4*np.sin(2*t))
tc = np.log(8/3) / 5
capped = np.where(t <= tc, instantaneous, .5 - .375*np.exp(-(t-tc)))
return [(instantaneous, 4*instantaneous, "Instantaneous, k = 4", "#0369a1", "-"),
(lagged, lagged_u, "Effector time constant = 1, k = 4", "#7c3aed", "-"),
(capped, np.minimum(4*capped, .5), "Instantaneous, cooling capped at 0.5", "#b45309", "--")]
def main():
plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
"axes.spines.right": False, "savefig.facecolor": "white"})
fig, axs = plt.subplots(2, 1, figsize=(9.6, 6.8), sharex=True,
facecolor="white", gridspec_kw={"hspace": .2})
t = np.linspace(0, 8, 1601)
for x, u, label, color, style in responses(t):
axs[0].plot(t, x, label=label, color=color, linestyle=style, linewidth=2.4)
axs[1].plot(t, u, color=color, linestyle=style, linewidth=2.4)
axs[0].set(ylabel="Temperature displacement x", ylim=(-.02, .56))
axs[1].set(ylabel="Additional cooling u", xlabel="Time (arbitrary units)",
ylim=(-.04, 1.08), xlim=(0, 8))
axs[0].axhline(.2, color="#94a3b8", linestyle=":", linewidth=1)
axs[1].axhline(.8, color="#94a3b8", linestyle=":", linewidth=1)
axs[0].text(6.0, .217, "Uncapped offset = 0.2", fontsize=10, color="#475569")
axs[0].text(5.5, .51, "Capped offset = 0.5", fontsize=10, color="#92400e")
peak_t = np.pi/4
peak_x = .2 + .4*np.exp(-peak_t)
axs[0].plot(peak_t, peak_x, "o", color="#7c3aed", markersize=5)
axs[0].annotate("Lag produces an overshoot\nof the eventual displacement",
xy=(peak_t, peak_x), xytext=(2.0, .32), fontsize=10,
arrowprops={"arrowstyle": "->", "color": "#7c3aed"})
for ax in axs:
ax.axhline(0, color="#94a3b8", linewidth=.8)
ax.grid(alpha=.15)
fig.suptitle("SYNTHETIC PLOTS — feedback response and capacity", fontsize=15,
fontweight="bold", y=.985)
axs[0].set_title("Identical sustained heat load d = 1 from t = 0; x(0) = u(0) = 0",
fontsize=11, loc="left")
fig.legend(*axs[0].get_legend_handles_labels(), loc="lower center",
bbox_to_anchor=(.5, .025), ncol=1, frameon=False, fontsize=10)
fig.subplots_adjust(left=.13, right=.97, top=.88, bottom=.24)
fig.text(.5, .012, "Invented dimensionless curves, not experiments. Plant: dx/dt = 1 − x − u.",
ha="center", fontsize=10, color="#475569")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=120,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()