| import numpy as np | |
| class MultiAttractorSystem: | |
| """ | |
| MUCE‑Ω v2 Core Engine | |
| """ | |
| def __init__(self, dim=2, K=3): | |
| self.dim = dim | |
| self.K = K | |
| self.Xi = np.random.randn(dim) | |
| self.history = [] | |
| self.w = np.ones(K) / K | |
| self.lr = 0.05 | |
| self.beta = 0.2 | |
| self.gamma = 0.1 | |
| self.max_norm = 5.0 | |
| def potentials(self, Xi): | |
| return np.array([ | |
| np.linalg.norm(Xi), | |
| -np.linalg.norm(Xi - 2.0), | |
| np.linalg.norm(Xi + 1.0), | |
| ]) | |
| def grad_potentials(self, Xi): | |
| eps = 1e-6 | |
| return np.array([ | |
| Xi / (np.linalg.norm(Xi) + eps), | |
| -(Xi - 2.0) / (np.linalg.norm(Xi - 2.0) + eps), | |
| (Xi + 1.0) / (np.linalg.norm(Xi + 1.0) + eps), | |
| ]) | |
| def project_constraints(self, Xi): | |
| norm = np.linalg.norm(Xi) | |
| if norm > self.max_norm: | |
| return Xi / norm * self.max_norm | |
| return Xi | |
| def utilities(self): | |
| stability = -np.linalg.norm(self.Xi) | |
| exploitation = np.linalg.norm(self.Xi) | |
| oscillation = np.var(self.history[-10:], axis=0).mean() if len(self.history) > 10 else 0.0 | |
| return np.array([stability, exploitation, -oscillation]) | |
| def step(self): | |
| grads = self.grad_potentials(self.Xi) | |
| total_grad = np.sum(self.w[:, None] * grads, axis=0) | |
| if len(self.history) > 5: | |
| osc = np.var(self.history[-5:], axis=0) | |
| else: | |
| osc = 0.0 | |
| self.Xi -= self.lr * (total_grad + self.gamma * osc) | |
| self.Xi = self.project_constraints(self.Xi) | |
| self.history.append(self.Xi.copy()) | |
| self.w += self.beta * self.utilities() | |
| self.w = np.exp(self.w) / np.sum(np.exp(self.w)) | |
| return self.Xi.copy(), self.w.copy() |