import json, math, random import numpy as np from scipy.optimize import least_squares, minimize from scipy.signal import residue SEED=7 np.random.seed(SEED); random.seed(SEED) def tf_step(t, T, z): # Exact inverse Laplace response of (1+z s)/(s prod(1+T_i s)). den=np.poly([-1.0/x for x in T]) num=np.array([z,1.0]) # append integrator for the step; residue gives y=sum(r exp(p t)). p,r,k=residue(num, np.polymul(den,[1.,0.])) y=np.zeros_like(t,dtype=float) for pi,ri in zip(p,r): y += np.real(ri*np.exp(np.real(pi)*t)) return y+float(np.real(k[0])) if len(k) else y def moment_rho(T,z): B=float(sum(T)-z) C=float(T[0]*T[1]+T[0]*T[2]+T[1]*T[2]-z*sum(T)+z*z) return B*B/C def twostate_response(t,p): Tf,Ts,z=np.exp(p) den=np.poly([-1/Tf,-1/Ts]) q,r,k=residue(np.array([z,1.]),np.polymul(den,[1.,0.])) y=np.zeros_like(t,dtype=float) for qi,ri in zip(q,r): y += np.real(ri*np.exp(np.real(qi)*t)) return y+(float(np.real(k[0])) if len(k) else 0.) def fit_window(t,y,init=None): if init is None: init=np.log([.3,1.5,.1]) r=least_squares(lambda p:twostate_response(t,p)-y,init,max_nfev=70) Tf,Ts,z=np.exp(r.x); a1=1/Tf+1/Ts; a0=1/(Tf*Ts) return float(a1*a1/a0),r.x,float(np.mean(r.fun*r.fun)) def find_case(): t=np.linspace(.01,10,121); best=None for _ in range(180): T=np.exp(np.random.uniform(np.log(.08),np.log(4),3)); z=np.random.uniform(-1,1) rm=moment_rho(T,z) if not 4.35