""" Smart Freezer v2 — K6-centric. K6 = Encompassment = "cognitive identity" of a cell. Freezing decision uses BOTH: - S (saturation) >= S* - K6 stability over T consecutive measurements A cell is frozen only if BOTH its saturation AND its K6 identity are stable. """ import math class SmartFreezer: def __init__(self, S_star=0.85, K6_star=0.60, T=3, K6_stability=0.02, check_every=100, verbose=False): self.S_star = S_star self.K6_star = K6_star self.T = T self.K6_stability = K6_stability self.check_every = check_every self.verbose = verbose self.n_frozen = 0 self.freeze_log = [] def _k6_identity_stable(self, cell): """Is the cell's K6 identity stable over T measurements?""" if not hasattr(cell, "K_history") or len(cell.K_history) < self.T: return False recent_k6 = [k[5] for k in cell.K_history[-self.T:]] if len(recent_k6) < self.T: return False k6_mean = sum(recent_k6) / len(recent_k6) if k6_mean < self.K6_star: return False # stability = low variance k6_var = sum((x - k6_mean) ** 2 for x in recent_k6) / len(recent_k6) k6_std = math.sqrt(k6_var) return k6_std <= self.K6_stability def maybe_freeze(self, cell, current_step): """Freeze cell if BOTH S-saturation AND K6-identity are stable.""" if getattr(cell, "frozen", False): return False recent_s = cell.S_history[-self.T:] if len(recent_s) < self.T: return False if not all(s >= self.S_star for s in recent_s): return False # K6 identity check if not self._k6_identity_stable(cell): return False cell.frozen = True cell.freeze_step = current_step self.n_frozen += 1 self.freeze_log.append({ "cell_id": cell.cell_id, "step": current_step, "S_mean": sum(recent_s) / len(recent_s), "K6_mean": sum(k[5] for k in cell.K_history[-self.T:]) / self.T, "layer_idx": cell.layer_idx, }) return True def periodic_check(self, cells, current_step): n_new = 0 for c in cells: if c.state != "active": continue if self.maybe_freeze(c, current_step): n_new += 1 if self.verbose and n_new: print(f"[SmartFreezer] step {current_step}: froze {n_new} new cells " f"(total={self.n_frozen})") return n_new def is_saturated(self, cell): recent = cell.S_history[-self.T:] return len(recent) >= self.T and all(s >= self.S_star for s in recent) def stats(self): return { "n_frozen": self.n_frozen, "S_star": self.S_star, "K6_star": self.K6_star, "T": self.T, "K6_stability": self.K6_stability, }