From 92f3cdf016bc4baab3f8b060f8f4524a2cc0e4d2 Mon Sep 17 00:00:00 2001 From: mayge Date: Wed, 17 Sep 2025 05:43:45 -0400 Subject: [PATCH] feat: OVF formula 70 --- img_formula_70.png | Bin 0 -> 49695 bytes main.py | 554 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 475 insertions(+), 79 deletions(-) create mode 100644 img_formula_70.png diff --git a/img_formula_70.png b/img_formula_70.png new file mode 100644 index 0000000000000000000000000000000000000000..5b8eed476491c89904142c3168b9c62eb8fcacf1 GIT binary patch literal 49695 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 h|M$iB|LG+|ykXnBiYEiC7tmL+`_g_zj 0: + z[i] = -np.conj(z[i]) + return z + + # ---------- build Ax=b for (70) ----------1 + def build_vf70_system(self,s, H_list, z_prev, d0=1.0): + """ + s: (Kf,) complex sample points (e.g. j*2πf) + H_list: list of (Kf,) complex responses, one per MIMO element you want to fit + z_prev: (P,) complex poles from previous iteration + d0: fixed scalar, usually 1.0 + + Returns: A (2*Kf*M, (M+1)*P), b (2*Kf*M,), plus Psi for convenience + Unknown vector x = [c (P), r^(1) (P), ..., r^(M) (P)] + """ + H_list = [np.asarray(h, dtype=np.complex128).reshape(-1) for h in H_list] + Kf = len(s) + P = len(z_prev) + M = len(H_list) + + Psi = self._psi(s, z_prev) # Kf x P + zerosP = np.zeros((Kf, P)) # convenience + + rows = [] + rhs = [] + + for m, H in enumerate(H_list): + Hp = H[:, None] # Kf x 1 + + # Left block (shared c): H * Psi + L_re = np.real(Hp * Psi) # Kf x P + L_im = np.imag(Hp * Psi) # Kf x P + + # Right block for this response: -Psi + R_re = -np.real(Psi) # Kf x P + R_im = -np.imag(Psi) # Kf x P + + # Assemble columns: [c | r^(1) | r^(2) | ... | r^(M)] + # Real rows + cols_re = [L_re] + for j in range(M): + cols_re.append(R_re if j == m else zerosP) + rows.append(np.hstack(cols_re)) + + # Imag rows + cols_im = [L_im] + for j in range(M): + cols_im.append(R_im if j == m else zerosP) + rows.append(np.hstack(cols_im)) + + # RHS (move d0*H to the right) + rhs.append(-np.real(d0 * H)) + rhs.append(-np.imag(d0 * H)) + + A = np.vstack(rows) # (2*Kf*M) x ((M+1)*P) + b = np.concatenate(rhs) # (2*Kf*M,) + return A, b, Psi + + # ---------- one relocation step ---------- + def vf70_step_once(self,s, H_list, z_prev, d0=1.0, column_scale=True): + """ + Returns: z_new (P,), c (P,), residues (list of M arrays length P) + """ + P = len(z_prev) + M = len(H_list) + + A, b, Psi = self.build_vf70_system(s, H_list, z_prev, d0=d0) + + # optional simple column scaling for conditioning + if column_scale: + col_norm = np.maximum(np.linalg.norm(A, axis=0), 1e-12) + x, *_ = np.linalg.lstsq(A / col_norm, b, rcond=None) + x = x / col_norm + else: + x, *_ = np.linalg.lstsq(A, b, rcond=None) + + # unpack unknowns + c = x[:P] + residues = [] + off = P + for _ in range(M): + residues.append(x[off:off+P]) + off += P + + # pole relocation (zeros of d0 + Psi @ c) + Sigma = np.diag(-np.asarray(z_prev, dtype=np.complex128)) + T = Sigma - (np.ones((P, 1), dtype=np.complex128) @ (c.reshape(1, -1) / d0)) + z_new = -np.linalg.eigvals(T) + z_new = self._enforce_lhp_conjugate(z_new) + + return z_new, c, residues + + # ---------- iterate K times (K == n_iter) ---------- + def vf70_iterate(self,s, H_list, z0, n_iter=15, d0=1.0, verbose=True): + z = np.array(z0, dtype=np.complex128) + c = None + residues = None + for it in range(n_iter): + z_next, c, residues = self.vf70_step_once(s, H_list, z, d0=d0) + if verbose: + rel = np.linalg.norm(z_next) / max(1.0, np.linalg.norm(z)) + print(f"[VF-70] iter {it+1:02d}/{n_iter:02d} Δz_rel = {rel}") + z = z_next + return z, c, residues + + def eval_Hfit_from_70(self,s, z_prev, c, residues_m, d0=1.0): + """ + Evaluate H_fit for one response m using (70): + H_fit = (Psi @ residues_m) / (d0 + Psi @ c) + """ + Psi = 1.0 / (s[:, None] + np.asarray(z_prev)[None, :]) + D_ratio = d0 + Psi @ c + N_part = Psi @ residues_m + return N_part / D_ratio + + def rms_abs(self,y): + return np.sqrt(np.mean(np.abs(y)**2)) + + def rms_error(self,H, Hfit): + """ + Returns (abs_rms, relative_rms). Relative RMS is normalized by RMS of H. + """ + err = Hfit - H + abs_rms = self.rms_abs(err) + ref = max(self.rms_abs(H), 1e-16) + rel_rms = abs_rms / ref + return abs_rms, rel_rms + + # --- run K (== n_iter) VF-(70) steps and record history --- + def run_vf70_with_history(self,s, H, z0, K=25, d0=1.0, verbose=True): + """ + H: 1D complex array (single response). If you want multi-response, + pass a list [H11, H21, ...] and adapt the evaluation below. + """ + # Wrap single response as a list for the step function + H_list = [np.asarray(H, dtype=np.complex128)] + z = np.array(z0, dtype=np.complex128) + hist = { + "z": [z.copy()], + "c": [], + "r": [], + "Hfit": [], + "rms_abs": [], + "rms_rel": [], + } + for it in range(K): + z_new, c, residues = self.vf70_step_once(s, H_list, z, d0=d0, column_scale=True) + # Evaluate fitted response after this iteration + Hfit = self.eval_Hfit_from_70(s, z, c, residues[0], d0=d0) + abs_r, rel_r = self.rms_error(H, Hfit) + + if verbose: + drel = np.linalg.norm(z_new - z) / max(1.0, np.linalg.norm(z)) + print(f"[VF-70] iter {it+1:02d}/{K:02d} Δz_rel={drel:.3e} RMS={abs_r:.3e} RMSrel={rel_r:.3e}") + + # save + hist["c"].append(c.copy()) + hist["r"].append(residues[0].copy()) + hist["Hfit"].append(Hfit.copy()) + hist["rms_abs"].append(abs_r) + hist["rms_rel"].append(rel_r) + z = z_new + hist["z"].append(z.copy()) + + return hist + + def evaluate(self, s_eval, z_ref, c, residues, d0=1.0): + """ + Evaluate the (70) model on any frequency grid. + + Parameters + ---------- + s_eval : (K_eval,) complex + Points where to evaluate (e.g., 1j*2π*freq_eval). + z_ref : (P,) complex + The *reference* poles used in the LS system that produced (c, residues). + For the last iteration in run_vf70_with_history, this is hist['z'][-2]. + c : (P,) complex + Denominator-update coefficients from (70). + residues : (P,) complex OR list of (P,) for multi-response + Residues for the response(s) from (70). + d0 : scalar, default 1.0 + + Returns + ------- + H_eval : (K_eval,) complex OR (K_eval, M) for M responses + """ + s_eval = np.asarray(s_eval, dtype=np.complex128).reshape(-1) + z_ref = np.asarray(z_ref, dtype=np.complex128).reshape(-1) + Psi_eval = 1.0 / (s_eval[:, None] + z_ref[None, :]) # K_eval x P + Den = d0 + Psi_eval @ np.asarray(c, dtype=np.complex128) + + # Single response + if not isinstance(residues, (list, tuple)): + r = np.asarray(residues, dtype=np.complex128).reshape(-1) + Num = Psi_eval @ r + return Num / Den + + # Multi-response + M = len(residues) + H_eval = np.empty((s_eval.size, M), dtype=np.complex128) + for m, r_m in enumerate(residues): + r_m = np.asarray(r_m, dtype=np.complex128).reshape(-1) + H_eval[:, m] = (Psi_eval @ r_m) / Den + return H_eval + +def auto_select(H, freq, + n_baseline=64, # log-spaced backbone points + peak_prominence=0.05, # fraction of |H| dB dynamic range for peak detection + peak_window=5, # take ±peak_window samples around each peak + topgrad_q=0.98, # keep top 2% largest slope/phase-change points + max_points=25, # final cap on selected samples (None = no cap) + ensure_ends=True): + """ + Select several significant sample points for vector fitting. + + Strategy: + 1) Always keep endpoints (optional). + 2) Add a log-spaced baseline over the band. + 3) Detect resonance peaks in |H| (on a log scale) and keep small windows around them. + 4) Add points with the largest magnitude slope and phase-change (w.r.t log-f). + 5) De-duplicate, sort, and optionally thin to 'max_points' with priority + to endpoints and detected peaks. + + Parameters + ---------- + H : (N,) complex array + Frequency response samples. + freq : (N,) float array + Frequency axis [Hz], strictly increasing. + n_baseline : int + Count of log-spaced baseline samples across the band. + peak_prominence : float + Peak prominence threshold as a fraction of the dynamic range in log|H|. + 0.05 ≈ keep peaks ≥ 5% of the range. + peak_window : int + Number of neighbor indices to include on each side of every detected peak. + topgrad_q : float in (0,1) + Quantile for selecting strong slope/phase points. + 0.98 ⇒ keep the top 2% largest derivatives. + max_points : int or None + If not None, cap the total number of selected indices to this value. + ensure_ends : bool + Always include the first and last samples. + + Returns + ------- + H_sel : (K,) complex array + freq_sel : (K,) float array + """ + H = np.asarray(H).reshape(-1) + f = np.asarray(freq).reshape(-1) + if H.size != f.size: + raise ValueError("H and freq must have the same length.") + N = f.size + if N < 4: + return H.copy(), f.copy() + + eps = 1e-16 + mag = np.abs(H) + logmag = np.log10(mag + eps) + phase = np.unwrap(np.angle(H)) + + # log-frequency axis (scale-invariant derivatives) + # keep it linear if any non-positive freq sneaks in + if np.all(f > 0): + lf = np.log(f) + else: + lf = f.copy() + + dlf = np.gradient(lf) + d_logmag = np.gradient(logmag) / (dlf + 1e-16) + d_phase = np.gradient(phase) / (dlf + 1e-16) + + idx = set() + if ensure_ends: + idx.update([0, N-1]) + + # 1) log-spaced baseline + if n_baseline > 0: + # map a log grid to nearest indices + grid = np.linspace(lf.min(), lf.max(), n_baseline) + base_idx = np.clip(np.searchsorted(lf, grid), 0, N-1) + idx.update(np.unique(base_idx).tolist()) + + # 2) peaks in |H| + try: + from scipy.signal import find_peaks + dyn = logmag.max() - logmag.min() + prom = peak_prominence * (dyn + 1e-12) + peaks, _ = find_peaks(logmag, prominence=prom) + except Exception: + # simple fallback: strict local maxima + peaks = np.where((mag[1:-1] > mag[:-2]) & (mag[1:-1] > mag[2:]))[0] + 1 + + for p in peaks: + lo = max(0, p - peak_window) + hi = min(N, p + peak_window + 1) + idx.update(range(lo, hi)) + + # 3) strongest slope / phase-change points + thr_slope = np.quantile(np.abs(d_logmag), topgrad_q) + thr_phase = np.quantile(np.abs(d_phase), topgrad_q) + idx.update(np.where(np.abs(d_logmag) >= thr_slope)[0].tolist()) + idx.update(np.where(np.abs(d_phase) >= thr_phase)[0].tolist()) + + # 4) finalize set + sel = np.array(sorted(idx), dtype=int) + + # 5) optional thinning with priority to endpoints and peaks + if max_points is not None and sel.size > max_points: + priority = np.zeros(sel.size, dtype=int) + if ensure_ends: + priority[(sel == 0) | (sel == N-1)] = 3 + if peaks.size: + priority[np.isin(sel, peaks)] = np.maximum(priority[np.isin(sel, peaks)], 2) + + keep = [] + budget = max_points + # keep highest-priority first + for lev in (3, 2, 1, 0): + cand = sel[priority == lev] + if cand.size == 0: + continue + if cand.size <= budget: + keep.extend(cand.tolist()) + budget -= cand.size + else: + step = max(1, int(np.ceil(cand.size / budget))) + keep.extend(cand[::step][:budget].tolist()) + budget = 0 + if budget == 0: + break + sel = np.array(sorted(set(keep)), dtype=int) + + return H[sel], f[sel] +if __name__ == "__main__": + # formula_67(s,y) + H11 = np.array([y[i,0,0] for i in range(len(y))]) + H11_slice,freqs_slice = auto_select(H11,freqs,max_points=20) + s_slice = freqs_slice * 2j * np.pi + P_pairs = 2 + z0 = generate_starting_poles(P_pairs, beta_min=1e8, beta_max=freqs_slice[-1]) + z0 = np.array(z0, dtype=np.complex128) + + f70 = formula_70() + K = 25 + hist = f70.run_vf70_with_history(s_slice, H11_slice, z0, K=K, d0=1.0, verbose=True) + + it_show = K-1 + Hfit_final = hist["Hfit"][it_show] + + s_dense = 1j * 2*np.pi * freqs + c_final = hist["c"][it_show] + r_final = hist["r"][it_show] # single response + z_ref = hist["z"][it_show] + Hfit_dense = f70.evaluate(s_dense, z_ref, c_final, r_final, d0=1.0) + + fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=False) + + # (1) Magnitude plot like your screenshot + ax0 = axes[0] + ax0.plot(freqs, np.abs(H11), 'o', ms=4, color='red', label='Samples') + ax0.plot(freqs, np.abs(Hfit_dense), '-', lw=2, color='k', label='Fit') + ax0.plot(freqs_slice, np.abs(H11_slice), 'x', ms=4, color='blue', label='Input Samples') + ax0.set_title("Response i=0, j=0") + ax0.set_ylabel("Magnitude") + ax0.legend(loc="best") + + # (2) RMS error vs iteration + ax1 = axes[1] + its = np.arange(1, K+1) + ax1.plot(its, hist["rms_rel"], '-o', lw=2) + ax1.set_xlabel("Iteration") + ax1.set_ylabel("RMS error (relative)") + ax1.grid(True, alpha=0.3) + ax1.set_title(f"RMS(final) = {hist['rms_rel'][-1]:.3e}") + + fig.tight_layout() + plt.savefig(f"img_formula_70.png")