# Mobiu-Q v4.4.6

**Soft Algebra for Optimization & Attention**

[![PyPI version](https://badge.fury.io/py/mobiu-q.svg)](https://pypi.org/project/mobiu-q/)
[![License](https://img.shields.io/badge/license-Proprietary-blue.svg)](LICENSE)

---

## Overview

Mobiu-Q is a framework built on **Soft Algebra** (nilpotent ε²=0) that provides:

1. **MobiuOptimizer** - Stable optimization in noisy environments
2. **MobiuAttention** 🧪 - O(N) linear attention for long sequences
3. **MobiuSignal** 🆕 - Trading signals using Soft Algebra
4. **MobiuAD** - Streaming anomaly detection        
5. **TrainGuard** - Safe ML training monitor      

---

## Installation

```bash
pip install mobiu-q
```

---

## Quick Start

### MobiuOptimizer — PyTorch (wrap your optimizer)

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"

model = MyModel()

# Step 1: define your base optimizer exactly as you normally would
base_opt = torch.optim.Adam(model.parameters(), lr=3e-4)

# Step 2: wrap it — your optimizer still runs, Mobiu-Q enhances via SA
opt = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",   # standard | deep | adaptive
    base_lr=3e-4,        # always pass base_lr to match your optimizer's LR
    verbose=False
)

for batch in dataloader:
    loss = criterion(model(batch))
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())   # pass dynamic loss — not a static scalar

opt.end()   # important: release session
```

### MobiuOptimizer — Quantum/NumPy (MobiuQCore)

For VQE, QAOA, and black-box optimization with SPSA:

```python
import numpy as np
from mobiu_q import MobiuQCore

LICENSE_KEY = "your-license-key-here"

params = np.random.uniform(-np.pi, np.pi, num_params)
opt = MobiuQCore(
    license_key=LICENSE_KEY,
    method="standard",
    mode="hardware",    # simulation | hardware
    base_lr=0.02,       # standard+hardware default
    verbose=False
)

for step in range(150):
    energy, grad = get_batched_energy_and_gradient(params, spsa_delta)
    params = opt.step(params, grad, energy)

opt.end()
```

### MobiuAttention (🧪 Experimental)

```python
from mobiu_q.experimental import MobiuAttention, MobiuBlock

# Drop-in replacement for nn.MultiheadAttention — no license key needed
attn = MobiuAttention(d_model=512, num_heads=8)
out = attn(x)  # x: [batch, seq, dim]

block = MobiuBlock(d_model=512, num_heads=8)
out = block(x)
```

### MobiuAD

```python
from mobiu_q import MobiuAD, TrainGuard

detector = MobiuAD(license_key=LICENSE_KEY)
result = detector.detect(value)

guard = TrainGuard(license_key=LICENSE_KEY)
result = guard.step(loss, gradient, val_loss)
```

### MobiuSignal

```python
from mobiu_q.signal import MobiuSignal

# Runs locally — no license key needed
signal = MobiuSignal(lookback=20)
result = signal.compute(prices)
if result.is_strong:
    print(f"Strong {'📈' if result.is_bullish else '📉'} signal: {result.magnitude:.2f}")

backtest = signal.backtest(historical_prices, future_window=5)
print(f"Correlation: {backtest.correlation:.3f}")
print(f"Q4/Q1 Ratio: {backtest.q4_q1_ratio:.2f}x")
```

---

## License Key

```python
LICENSE_KEY = "your-license-key-here"  # https://app.mobiu.ai
```

| Tier | API Calls | Price |
|------|-----------|-------|
| Free | 20/month | $0 |
| Pro | Unlimited | $19/month |

**Note:** MobiuAttention and MobiuSignal run locally — no license key required.

---

## MobiuOptimizer

### Methods

| Method     | Use Case                                      | Default LR (simulation) | Default LR (hardware) |
|------------|-----------------------------------------------|-------------------------|-----------------------|
| `standard` | VQE, chemistry, smooth landscapes             | 0.01                    | 0.02                  |
| `deep`     | Deep circuits, rugged landscapes, QAOA        | 0.1                     | 0.1                   |
| `adaptive` | RL, LLM fine-tuning, high-variance problems   | 0.0003                  | 0.0003                |

**Important:** Always pass `base_lr=` explicitly to match your base optimizer's LR and prevent auto-replacement.

**Mode (`mode=`) is for quantum/NumPy only.** In PyTorch mode, the `mode` parameter has no effect — your optimizer always runs at the LR you set.

### Supported Base Optimizers (PyTorch mode)

Any PyTorch-compatible optimizer works. Common choices:

```python
# Supervised learning / VQE-classical
base_opt = torch.optim.Adam(model.parameters(), lr=3e-4)

# RL / high-variance
base_opt = torch.optim.Adam(model.parameters(), lr=3e-4)

# LLM fine-tuning (LoRA)
base_opt = torch.optim.SGD(model.parameters(), lr=5e-3, momentum=0.9)

# Custom / external
from muon import Muon
base_opt = Muon(model.parameters(), lr=0.02, momentum=0.95)
```

Supported server-side (Quantum/NumPy mode): `Adam`, `NAdam`, `AMSGrad`, `SGD`, `Momentum`, `LAMB`.

### minimize vs maximize

```python
# Loss minimization (default) — supervised learning, VQE
opt = MobiuOptimizer(base_opt, license_key=LICENSE_KEY, method="adaptive",
                     base_lr=3e-4, maximize=False)
opt.step(loss.item())

# Reward maximization — RL with SB3 callback (set_metric provides reward signal)
opt = MobiuOptimizer(base_opt, license_key=LICENSE_KEY, method="adaptive",
                     base_lr=3e-4, maximize=True)
# SB3: opt.set_metric(episode_reward)
```

| Use Case | maximize= | Pass to step() |
|----------|-----------|----------------|
| Supervised learning | `False` | `loss.item()` |
| VQE / QAOA | `False` | `energy` |
| PPO policy loss | `False` | `loss.item()` |
| SB3 RL (via callback) | `True` | `set_metric(reward)` |

### Fair Benchmarking

The correct customer-view test compares **Pure Adam** (baseline) vs **Adam wrapped by MobiuOptimizer** (test). Both start from identical weights, same seed, same RNG state:

```python
import torch
import numpy as np

# --- Shared init ---
torch.manual_seed(seed)
model_template = MyModel()
init_weights = {k: v.clone() for k, v in model_template.state_dict().items()}

# Save RNG state so both runs see identical data/noise
torch_state = torch.get_rng_state()
np_state    = np.random.get_state()

# --- Baseline: Pure Adam ---
model_adam = MyModel()
model_adam.load_state_dict(init_weights)
optimizer_adam = torch.optim.Adam(model_adam.parameters(), lr=LR)

for batch in dataloader:
    loss = criterion(model_adam(batch))
    optimizer_adam.zero_grad()
    loss.backward()
    optimizer_adam.step()

# --- Restore RNG: Mobiu sees identical batches ---
torch.set_rng_state(torch_state)
np.random.set_state(np_state)

# --- Test: Adam + Mobiu-Q ---
model_mobiu = MyModel()
model_mobiu.load_state_dict(init_weights)
base_opt = torch.optim.Adam(model_mobiu.parameters(), lr=LR)
optimizer_mobiu = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,       # prevent auto-replace
    maximize=False,
    verbose=False
)

for batch in dataloader:
    loss = criterion(model_mobiu(batch))
    optimizer_mobiu.zero_grad()
    loss.backward()
    optimizer_mobiu.step(loss.item())   # pass dynamic loss

optimizer_mobiu.end()
```

### Benchmarks

#### Reinforcement Learning

| Domain | Improvement | Win Rate | Seeds | p-value |
|--------|-------------|----------|-------|---------|
| LunarLander-v3 (PPO) | **+98.8%** | 97% (29/30) | 30 | <0.000001 |
| LunarLander-v3 (SB3 PPO) | **+197.4%** | 80% (24/30) | 30 | 0.000189 |
| Portfolio Trading (PPO) | **+219.3%** | 100% | 10 | 0.000977 |
| MuJoCo InvertedPendulum-v5 | **+330.2%** | 90% | 10 | — |
| MuJoCo Hopper-v5 | **+29.9%** | 90% | 10 | — |
| Atari Breakout | **+135.9%** | 100% | 3 | — |

#### Quantum Computing (VQE — IBM FakeFez)

| Molecule / Model | Improvement | Win Rate | Seeds |
|------------------|-------------|----------|-------|
| BeH₂ | **+85.8%** | 100% | 5 |
| HeH⁺ | **+78.8%** | 100% | 5 |
| H₄ Chain | **+61.2%** | 100% | 5 |
| H₂ | **+50.6%** | 100% | 5 |
| H₂O | **+47.3%** | 100% | 5 |
| LiH | **+40.8%** | 100% | 5 |
| Ferro Ising (6 spins) | **+37.2%** | 100% | 5 |
| Antiferro Heisenberg | **+30.0%** | 100% | 5 |
| Transverse Ising | **+29.9%** | 100% | 5 |
| Heisenberg XXZ (Δ=2.0) | **+26.0%** | 80% | 5 |
| C₁₃Cl₂ Half-Möbius | **+20.5%** | 100% | 5 |

#### QAOA (IBM FakeFez)

| Problem | Improvement | Win Rate | Seeds |
|---------|-------------|----------|-------|
| MaxCut | **+45.3%** | 90% | 10 |
| Max Independent Set | **+28.9%** | 100% | 5 |

#### Machine Learning (Systematic Gradient Bias)

| Domain | Bias Source | Improvement | Win Rate |
|--------|-------------|-------------|----------|
| Federated Learning | Non-IID client data | **+67.3%** | 100% |
| Imbalanced Data | 90% majority class | **+52.5%** | 100% |
| Sim-to-Real | Wrong simulator physics | **+47.0%** | 100% |
| Noisy Labels | 30% systematic mislabeling | **+40.3%** | 100% |
| LLM Full Fine-tuning | Momentum optimizer | **+43.5%** | 100% |
| LLM LoRA Fine-tuning | Momentum optimizer | **+5.6%** | 100% |

#### Signal Processing & Black-box Optimization

| Domain | Improvement | Win Rate | Seeds |
|--------|-------------|----------|-------|
| 5G Antenna Beamforming (16 elements) | **+965.5%** | 100% | 10 |
| Noisy Periodic (deep SA) | **+547.9%** | 90% | 10 |
| Beale function (shot noise) | **+99.1%** | 100% | 10 |
| Rosenbrock (shot noise) | **+90.2%** | 100% | 10 |
| Sphere (shot noise) | **+81.1%** | 90% | 10 |
| Rastrigin (shot noise) | **+29.9%** | 90% | 10 |
| Ackley (shot noise) | **+27.7%** | 80% | 10 |

---

## Examples by Domain

### Reinforcement Learning — PPO

```python
import torch
import torch.nn as nn
import torch.nn.functional as F
import gymnasium as gym
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 3e-4  # industry standard for PPO

class ActorCritic(nn.Module):
    def __init__(self, obs_dim, act_dim, hidden=64):
        super().__init__()
        self.shared = nn.Sequential(
            nn.Linear(obs_dim, hidden), nn.Tanh(),
            nn.Linear(hidden, hidden), nn.Tanh()
        )
        self.actor  = nn.Linear(hidden, act_dim)
        self.critic = nn.Linear(hidden, 1)

model   = ActorCritic(8, 4)
base_opt = torch.optim.Adam(model.parameters(), lr=LR, eps=1e-5)
opt = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,
    maximize=False,   # minimizing PPO surrogate loss
    verbose=False
)

# PPO update inner loop
for epoch in range(n_epochs):
    for batch in rollout_batches:
        loss = ppo_loss(model, batch)  # surrogate + value + entropy
        opt.zero_grad()
        loss.backward()
        nn.utils.clip_grad_norm_(model.parameters(), 0.5)
        opt.step(loss.item())   # pass dynamic loss

opt.end()
```

### Reinforcement Learning — Stable-Baselines3

SB3 calls `optimizer.step()` internally. Use the callback pattern with `set_metric()`:

```python
import gymnasium as gym
import numpy as np
from stable_baselines3 import PPO
from stable_baselines3.common.callbacks import BaseCallback
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"

class MobiuCallback(BaseCallback):
    def __init__(self, verbose=0):
        super().__init__(verbose=verbose)
        self._mobiu      = None
        self._ep_returns = []

    def _on_training_start(self):
        base_opt    = self.model.policy.optimizer
        self._mobiu = MobiuOptimizer(
            base_opt,
            license_key=LICENSE_KEY,
            method="adaptive",
            maximize=True,        # SB3 maximizes episode reward
            sync_interval=50,
            verbose=False
        )
        self.model.policy.optimizer = self._mobiu

    def _on_step(self):
        for info in self.locals.get("infos", []):
            if "episode" in info:
                self._ep_returns.append(info["episode"]["r"])
                self._mobiu.set_metric(np.mean(self._ep_returns[-4:]))
        return True

    def _on_training_end(self):
        if self._mobiu:
            self._mobiu.end()

env   = gym.make("LunarLander-v3")
model = PPO("MlpPolicy", env, learning_rate=3e-4, verbose=0)
model.learn(total_timesteps=200_000, callback=MobiuCallback())
```

### Quantum Chemistry (VQE)

```python
import numpy as np
from qiskit.circuit.library import EfficientSU2
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer import AerSimulator
from qiskit.primitives import BackendEstimatorV2
from mobiu_q import MobiuQCore

try:
    from qiskit_ibm_runtime.fake_provider import FakeFezV2 as FakeBackend
except ImportError:
    from qiskit_ibm_runtime.fake_provider import FakeFez as FakeBackend

LICENSE_KEY = "your-license-key-here"
LR          = 0.02   # standard + hardware default

# H₂ Hamiltonian
hamiltonian = SparsePauliOp.from_list([
    ("II", -0.4804), ("ZZ", 0.3435), ("ZI", -0.4347),
    ("IZ",  0.5716), ("XX",  0.0910), ("YY",  0.0910)
])

backend   = AerSimulator.from_backend(FakeBackend())
estimator = BackendEstimatorV2(backend=backend)
estimator.options.default_shots  = 4096
estimator.options.seed_simulator = 42

ansatz     = EfficientSU2(2, reps=4, entanglement="linear")
pm         = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_ansatz = pm.run(ansatz)
isa_ops    = hamiltonian.apply_layout(isa_ansatz.layout)

# Same baseline optimizer (Pure Adam) and Mobiu use base_lr=LR
# Pre-generate SPSA deltas so both see identical gradients
np.random.seed(seed * 1000)
spsa_deltas = [np.random.choice([-1, 1], size=ansatz.num_parameters)
               for _ in range(NUM_STEPS)]

# --- Pure Adam baseline ---
class PureAdam:
    def __init__(self, params_np, lr=LR):
        self._tensor = torch.tensor(params_np, dtype=torch.float64, requires_grad=True)
        self._opt    = torch.optim.Adam([self._tensor], lr=lr)
    def step(self, params_np, grad_np):
        self._opt.zero_grad()
        self._tensor.grad = torch.tensor(grad_np, dtype=torch.float64)
        self._opt.step()
        return self._tensor.detach().numpy().copy()

# --- Mobiu-Q ---
params    = init_params.copy()
mobiu_opt = MobiuQCore(
    license_key=LICENSE_KEY,
    method="standard",
    mode="hardware",
    base_lr=LR,
    verbose=False
)

for step in range(NUM_STEPS):
    job = estimator.run([
        (isa_ansatz, isa_ops, params),
        (isa_ansatz, isa_ops, params + 0.1 * spsa_deltas[step]),
        (isa_ansatz, isa_ops, params - 0.1 * spsa_deltas[step])
    ])
    results = job.result()
    energy  = float(results[0].data.evs)
    grad    = (float(results[1].data.evs) - float(results[2].data.evs)) / 0.2 * spsa_deltas[step]
    params  = mobiu_opt.step(params, grad, energy)

mobiu_opt.end()
print(f"Final energy: {energy:.4f}")   # H₂ ground state: -1.846 Ha
```

### QAOA (MaxCut / MIS)

```python
import torch
import torch.nn as nn
import numpy as np
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR          = 0.1   # deep + hardware default

class QAOAModel(nn.Module):
    def __init__(self, n_params, init_values):
        super().__init__()
        self.theta = nn.Parameter(torch.tensor(init_values, dtype=torch.float32))

# Wrap SGD — customer's optimizer runs, Mobiu enhances
model    = QAOAModel(n_params, init_params)
base_opt = torch.optim.SGD(model.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="deep",
    mode="hardware",
    base_lr=LR,
    verbose=False
)

for step in range(100):
    params_np = model.theta.detach().cpu().numpy()
    energy, grad_np = get_qaoa_energy_and_gradient(params_np, spsa_deltas[step])

    opt.zero_grad()
    model.theta.grad = torch.tensor(grad_np, dtype=torch.float32)
    opt.step(energy)

opt.end()
```

### Machine Learning — Federated Learning

```python
import torch
from mobiu_q import MobiuQCore
import numpy as np

LICENSE_KEY = "your-license-key-here"
LR          = 0.01

params  = np.random.randn(dim) * 0.5
opt     = MobiuQCore(
    license_key=LICENSE_KEY,
    method="standard",
    mode="simulation",
    base_optimizer="Adam",
    base_lr=LR,
    verbose=False
)

for step in range(N_STEPS):
    energy   = global_loss(params)
    gradient = federated_gradient(params, step)   # biased from non-IID clients
    params   = opt.step(params, gradient, energy)

opt.end()
```

### Machine Learning — Imbalanced / Noisy Labels / Sim-to-Real

Same pattern for all systematic-bias domains — just swap the gradient source:

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 0.001

model    = Classifier()
base_opt = torch.optim.Adam(model.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="standard",
    base_lr=LR,
    verbose=False
)

for batch_x, noisy_labels in train_loader:
    loss = criterion(model(batch_x), noisy_labels)
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())   # dynamic loss — Soft Algebra detects label bias

opt.end()
```

### Why Soft Algebra Works for Systematic Bias

In all these domains the **gradient is systematically biased** away from the true loss direction:
- **Federated:** each client sees different data distribution → aggregated gradient biased
- **Imbalanced:** gradient dominated by majority class → minority classes underfit
- **Sim-to-Real:** simulator has wrong physics (friction, mass) → gradient points to wrong target
- **Noisy Labels:** labels consistently confused (e.g., 3↔8) → gradient points wrong way

Soft Algebra tracks the gap between gradient direction and actual loss improvement, then corrects for it. This is exactly what the realized component `b_t` measures.

### Federated Learning — Detailed Example

```python
import numpy as np
from mobiu_q import MobiuQCore

LICENSE_KEY = "your-license-key-here"
LR = 0.01

class FederatedTrainer:
    def __init__(self, n_clients=10, non_iid_strength=0.8):
        self.n_clients = n_clients
        self.client_biases = [np.random.randn(dim) * non_iid_strength
                              for _ in range(n_clients)]

    def federated_gradient(self, params, step):
        np.random.seed(step)
        sampled = np.random.choice(self.n_clients, size=5, replace=False)
        grads = []
        for c in sampled:
            target = true_optimum + self.client_biases[c]
            grads.append(2 * (params - target) / dim)
        return np.mean(grads, axis=0)

trainer = FederatedTrainer()
params  = np.random.randn(dim) * 0.5
opt     = MobiuQCore(
    license_key=LICENSE_KEY,
    method="standard",
    mode="simulation",
    base_optimizer="Adam",
    base_lr=LR,
    verbose=False
)

for step in range(80):
    energy   = global_loss(params)
    gradient = trainer.federated_gradient(params, step)
    params   = opt.step(params, gradient, energy)

opt.end()
```

### Imbalanced Data — Detailed Example

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 0.001

# 90% class 0, 10% class 1 — gradient dominated by majority
train_loader = create_imbalanced_loader(imbalance_ratio=0.9)

model    = FraudDetector()
base_opt = torch.optim.Adam(model.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="standard",
    base_lr=LR,
    verbose=False
)

for batch_x, labels in train_loader:
    loss = criterion(model(batch_x), labels)
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())   # Soft Algebra detects majority-class bias

opt.end()
```

### Sim-to-Real — Detailed Example

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 0.001

policy   = RobotPolicy()
base_opt = torch.optim.Adam(policy.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="standard",
    base_lr=LR,
    verbose=False
)

for step in range(80):
    energy   = real_world_loss(policy)        # evaluated in reality
    gradient = simulator_gradient(policy, step)  # biased (wrong physics)
    # Use MobiuQCore NumPy-style if working with param arrays,
    # or opt.zero_grad() + loss.backward() + opt.step(loss.item()) in PyTorch
    opt.zero_grad()
    apply_grad_to_policy(policy, gradient)
    opt.step(energy)

opt.end()
```

### Noisy Labels — Detailed Example

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 0.001

# Systematic confusion: class i mislabeled as class (i+1) — 30% rate
train_loader = create_noisy_label_loader(noise_rate=0.3)

model    = Classifier()
base_opt = torch.optim.Adam(model.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="standard",
    base_lr=LR,
    verbose=False
)

for batch_x, noisy_labels in train_loader:
    loss = criterion(model(batch_x), noisy_labels)
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())   # Soft Algebra detects systematic label mismatch

opt.end()
```

### REINFORCE

```python
import torch
import gymnasium as gym
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 3e-4

policy   = torch.nn.Sequential(
    torch.nn.Linear(8, 64), torch.nn.Tanh(),
    torch.nn.Linear(64, 64), torch.nn.Tanh(),
    torch.nn.Linear(64, 4)
)
base_opt = torch.optim.Adam(policy.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,
    maximize=False,   # minimizing policy surrogate loss
    verbose=False
)

env = gym.make("LunarLander-v3")

for episode in range(1000):
    state, _    = env.reset()
    log_probs, rewards = [], []
    done = False
    while not done:
        logits = policy(torch.FloatTensor(state))
        dist   = torch.distributions.Categorical(logits=logits)
        action = dist.sample()
        log_probs.append(dist.log_prob(action))
        state, reward, terminated, truncated, _ = env.step(action.item())
        rewards.append(reward)
        done = terminated or truncated

    returns = []
    G = 0
    for r in reversed(rewards):
        G = r + 0.99 * G
        returns.insert(0, G)
    returns = torch.tensor(returns)
    returns = (returns - returns.mean()) / (returns.std() + 1e-8)

    loss = sum(-lp * G for lp, G in zip(log_probs, returns))
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())   # pass surrogate loss, not episode return

opt.end()
```

### Trading / Finance (RL)

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR = 3e-4

policy   = TradingPolicy()  # outputs Hold/Buy/Sell
base_opt = torch.optim.Adam(policy.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,
    maximize=False,   # minimizing policy loss
    verbose=False
)

for episode in range(500):
    log_probs, rewards = collect_episode(policy, market_data)
    returns = compute_returns(rewards, gamma=0.99)

    loss = sum(-lp * G for lp, G in zip(log_probs, returns))
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())

opt.end()
```

### Custom / External Optimizers

Mobiu-Q wraps **any** optimizer with a standard PyTorch interface:

```python
# Muon optimizer
from muon import Muon
base_opt = Muon(model.parameters(), lr=0.02, momentum=0.95)
opt = MobiuOptimizer(base_opt, license_key=LICENSE_KEY, method="adaptive", base_lr=0.02)

# LAMB from apex
from apex.optimizers import FusedLAMB
base_opt = FusedLAMB(model.parameters(), lr=0.001)
opt = MobiuOptimizer(base_opt, license_key=LICENSE_KEY, method="standard", base_lr=0.001)

# Adafactor from transformers
from transformers import Adafactor
base_opt = Adafactor(model.parameters(), lr=1e-3, relative_step=False)
opt = MobiuOptimizer(base_opt, license_key=LICENSE_KEY, method="adaptive", base_lr=1e-3)
```

**Requirements:** optimizer must have `.step()`, `.zero_grad()`, and `.param_groups`.

### MobiuSignal + MobiuOptimizer Integration (RL Trading)

Use MobiuSignal features as your policy state, MobiuOptimizer as your optimizer:

```python
from mobiu_q import MobiuOptimizer
from mobiu_q.signal import MobiuSignal
import torch, torch.nn as nn

LICENSE_KEY = "your-license-key-here"
LR = 3e-4

class TradingPolicy(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(5, 64), nn.Tanh(),
            nn.Linear(64, 64), nn.Tanh(),
            nn.Linear(64, 3)  # Hold, Buy, Sell
        )
    def forward(self, features):
        # features: [potential, realized, magnitude, position, pnl]
        return self.net(features)

signal   = MobiuSignal(lookback=20)
policy   = TradingPolicy()
base_opt = torch.optim.Adam(policy.parameters(), lr=LR)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,
    maximize=False,
    verbose=False
)

for episode in range(500):
    signal.reset()
    log_probs, rewards = [], []
    for price in price_series:
        result = signal.update(price)
        if result is None:
            continue
        state  = [result.potential, result.realized, result.magnitude, position, pnl]
        logits = policy(torch.FloatTensor(state))
        dist   = torch.distributions.Categorical(logits=logits)
        action = dist.sample()
        log_probs.append(dist.log_prob(action))
        rewards.append(execute_trade(action.item()))

    returns = compute_returns(rewards)
    loss    = sum(-lp * G for lp, G in zip(log_probs, returns))
    opt.zero_grad()
    loss.backward()
    opt.step(loss.item())

opt.end()
```

### LLM Fine-tuning (LoRA / Full)

```python
import torch
from mobiu_q import MobiuOptimizer

LICENSE_KEY = "your-license-key-here"
LR          = 5e-3

# SGD with momentum works best for LoRA adapter layers
base_opt = torch.optim.SGD(lora_params, lr=LR, momentum=0.9)
opt      = MobiuOptimizer(
    base_opt,
    license_key=LICENSE_KEY,
    method="adaptive",
    base_lr=LR,
    maximize=False,
    sync_interval=50,
    verbose=False
)

for epoch in range(num_epochs):
    for batch in train_loader:
        loss = criterion(model(batch))
        opt.zero_grad()
        loss.backward()
        opt.step(loss.item())
        # Optionally: opt.set_metric(-eval_loss)  # use eval signal

opt.end()
```

### Black-box / SPSA Optimization (Classical)

For antenna design, hyperparameter optimization, sensor calibration — landscapes similar to VQE:

```python
import numpy as np
from mobiu_q import MobiuQCore

LICENSE_KEY = "your-license-key-here"
LR          = 0.1

params  = np.random.uniform(-5, 5, N_PARAMS)
opt     = MobiuQCore(
    license_key=LICENSE_KEY,
    method="standard",
    mode="hardware",
    base_lr=LR,
    verbose=False
)

# Pre-generate deltas — same for baseline and Mobiu (fair comparison)
np.random.seed(seed * 1000)
spsa_deltas = [np.random.choice([-1, 1], size=N_PARAMS) for _ in range(N_STEPS)]

for step in range(N_STEPS):
    delta = spsa_deltas[step]
    ck    = 0.1 / ((step + 1) ** 0.101)

    e_plus  = evaluate_with_noise(params + ck * delta)
    e_minus = evaluate_with_noise(params - ck * delta)
    e_center = evaluate_with_noise(params)
    grad    = (e_plus - e_minus) / (2 * ck) * delta

    params = opt.step(params, grad, e_center)

opt.end()
```

---

## Troubleshooting

### 1. Switch Base Optimizer

| Problem Type | Recommended |
|--------------|-------------|
| LoRA / LLM | `torch.optim.SGD(momentum=0.9)` |
| VQE / Chemistry | `torch.optim.Adam` |
| QAOA | `torch.optim.SGD` or `NAdam` |
| RL / Trading | `torch.optim.Adam` |
| Federated / Imbalanced | `torch.optim.Adam` |

### 2. Switch Method

| Current | Try Instead |
|---------|-------------|
| `standard` → not improving | `adaptive` |
| `adaptive` → too noisy | `deep` |
| `deep` → slow | `standard` |

### 3. Mode (Quantum/NumPy only)

| Current | Try Instead |
|---------|-------------|
| `simulation` | `hardware` |

### 4. Adjust Learning Rate

Always pass `base_lr=` explicitly. If diverging, lower LR on the base optimizer. If stuck, raise it.

### 5. Common Fixes by Domain

| Domain | Issue | Fix |
|--------|-------|-----|
| **RL (PPO)** | rewards unstable | `maximize=False` + `loss.item()` |
| **SB3** | can't pass loss | use callback + `set_metric(reward)` |
| **VQE** | gradient mismatch | pre-generate SPSA deltas, same for both |
| **LoRA** | slow convergence | `SGD(momentum=0.9)` + `adaptive` |
| **Federated** | high variance | `standard` + `base_lr=0.01` |

---

## MobiuOptimizer — A/B Testing

To verify Soft Algebra provides value (not just LR scheduling), compare `use_soft_algebra=True` vs `False` with the same optimizer:

```python
# SA ON
opt_on  = MobiuOptimizer(base_opt, license_key=LICENSE_KEY,
                          use_soft_algebra=True)

# SA OFF (same LR scheduling, no nilpotent algebra)
opt_off = MobiuOptimizer(base_opt, license_key=LICENSE_KEY,
                          use_soft_algebra=False)
```

**Ablation result (H₂ VQE, FakeFez, 20 seeds):**

| Method | Mean Energy | Gap to Ground State | vs Baseline |
|--------|-------------|---------------------|-------------|
| Mobiu-Q SA ON (ε²=0) | -1.6678 Ha | 178 mHa | **+53.8%** ✅ |
| Baseline SA OFF | -1.4603 Ha | 386 mHa | — |
| Fake SA (regular ×) | -1.4597 Ha | 386 mHa | -0.2% ❌ |

- SA ON vs Baseline: **20/20** wins
- SA ON vs Fake SA: **20/20** wins  
- Fake SA vs Baseline: **9/20** (random)

**Conclusion:** The nilpotent property ε²=0 is what drives the improvement — not LR scaling alone. Fake SA (regular multiplication) is statistically indistinguishable from the baseline. The difference between Real SA and Fake SA is **270×**.

---

## MobiuSignal 🆕

Trading signal generator using the same Soft Algebra potential/realized framework.

### Validated Results (3,080 days BTC/USDT)

| Metric | Result |
|--------|--------|
| Spearman correlation | **+0.222** (p<0.0001) |
| Q4/Q1 ratio | **1.83x** larger moves |
| Precision lift | **1.18x** vs random |

### Mathematical Framework

```
Potential (aₜ) = σₜ/μₜ × scale    # Normalized volatility
Realized (bₜ)  = (Pₜ - Pₜ₋₁)/Pₜ₋₁  # Price change
Magnitude      = √(aₜ² + bₜ²)      # Signal strength
```

### Usage

```python
from mobiu_q.signal import MobiuSignal, backtest_signal

signal = MobiuSignal(lookback=20, vol_scale=100)
result = signal.compute(prices)

print(f"Potential:  {result.potential:.3f}")
print(f"Realized:   {result.realized:.3f}%")
print(f"Magnitude:  {result.magnitude:.3f}")
print(f"Direction:  {result.direction}")   # +1, -1, or 0
print(f"Quartile:   Q{result.quartile}")   # 1–4 (4=strongest)

# Streaming
for price in live_price_stream:
    result = signal.update(price)
    if result and result.is_strong:
        execute_trade(result.direction)

# Backtest
bt = signal.backtest(historical_prices, future_window=5)
print(f"Correlation: {bt.correlation:.3f} (p={bt.correlation_pvalue:.4f})")
print(f"Q4/Q1 Ratio: {bt.q4_q1_ratio:.2f}x")
```

**Note:** MobiuSignal runs **100% locally** — no API calls, no license key.

---

## MobiuAttention 🧪

### Performance

| Seq Length | Transformer | MobiuAttention | Speedup |
|------------|-------------|----------------|---------|
| 4,096      | 16.9ms      | 16.4ms         | ~1x     |
| 8,192      | 75.3ms      | **33.8ms**     | **2.2x** ✅ |
| 16,384     | **OOM** 💥  | Works          | ∞       |

*Tested on T4 GPU, batch=2, d_model=128*

### Usage

```python
from mobiu_q.experimental import MobiuBlock
import torch.nn as nn

class LongContextLM(nn.Module):
    def __init__(self, vocab, d=512, h=8, layers=6):
        super().__init__()
        self.embed  = nn.Embedding(vocab, d)
        self.blocks = nn.Sequential(*[MobiuBlock(d, h) for _ in range(layers)])
        self.head   = nn.Linear(d, vocab)
    def forward(self, x):
        return self.head(self.blocks(self.embed(x)))

model = LongContextLM(50000)
x     = torch.randint(0, 50000, (1, 16384))
out   = model(x)   # no OOM
```

### Combining with MobiuOptimizer

| Configuration | Result |
|---------------|--------|
| Standard Attention + MobiuOptimizer | ✅ **Best quality** |
| MobiuAttention + Adam | Good for long context |
| MobiuAttention + MobiuOptimizer | May interfere — test first |

**Note:** MobiuAttention runs **100% locally** — no license key.

---

## 🛡️ Anomaly Detection

### MobiuAD — Streaming Detector

```python
from mobiu_q import MobiuAD

detector = MobiuAD(license_key=LICENSE_KEY, method="deep")
for value in data_stream:
    result = detector.detect(value)
    if result.is_anomaly:
        print(f"⚠️ Anomaly! Δ†={result.delta_dagger:.4f}")
```

### TrainGuard — Safe ML Training

```python
from mobiu_q import TrainGuard

guard = TrainGuard(license_key=LICENSE_KEY)
for epoch in range(100):
    result = guard.step(loss=train_loss, gradient=grad_norm, val_loss=val_loss)
    if result.alert:
        if result.alert_type == 'GRADIENT_EXPLOSION':
            reduce_lr()
        elif result.alert_type == 'OVERFITTING':
            apply_regularization()
guard.end()
```

### MobiuAD vs PyOD

| Feature | MobiuAD | PyOD |
|---------|---------|------|
| Type | Streaming | Batch |
| Detects | Behavioral changes | Statistical outliers |
| Real-time | ✅ Yes | ❌ No |
| Early warning | ✅ Yes | ❌ No |
| Pattern changes | ✅ Excellent | ⚠️ Limited |
| Value outliers | ⚠️ Good | ✅ Excellent |

---

## How It Works

### Soft Algebra

```
SoftNumber multiplication:  (a,b) × (c,d) = (ad + bc, bd)
```

The nilpotent property ε²=0 separates "potential" (what could happen) from "realized" (what did happen). Applied to optimization:

```
a_t = curvature / (curvature + mean_energy)   # landscape uncertainty
b_t = improvement ∈ [-1, 1]                   # actual progress
trust = |real| / (|real| + |soft| + ε)        # confidence in update
lr_t  = base_lr × (1 + trust × soft_factor)   # adaptive scaling
```

In quantum optimization, the realized component captures the gap between gradient direction and actual energy improvement — exactly the signal needed to handle shot noise and SPSA variance.

---

## Full Examples

### Quantum Chemistry (VQE)
| File | Description |
|------|-------------|
| `vqe_fakefez_ibm_customer_adam.py` | H₂ on IBM FakeFez |
| `test_heh_customer.py` | HeH⁺ molecule |
| `test_h4_customer.py` | H₄ chain |
| `test_h2o_customer.py` | H₂O molecule |
| `test_lih_customer.py` | LiH molecule |
| `test_beh2_customer.py` | BeH₂ molecule |
| `vqe_c13cl2_fakefez_customer.py` | C₁₃Cl₂ Half-Möbius |

### Condensed Matter Physics
| File | Description |
|------|-------------|
| `test_heisenbeg_xxz_deep.py` | Heisenberg XXZ (Δ=2.0) |
| `test_transverse_ising.py` | Transverse field Ising |
| `test_xy_model.py` | XY model |
| `test_ferro_ising_fair.py` | Ferromagnetic Ising |
| `test_antiferro_heisenberg.py` | Antiferromagnetic Heisenberg |
| `test_hubbard_dimer.py` | Hubbard dimer |
| `test_ssh_model.py` | SSH model (topological) |
| `test_kitaev_chain.py` | Kitaev chain |

### QAOA
| File | Description |
|------|-------------|
| `test_fakefez_qaoa_new.py` | MaxCut on FakeFez |
| `test_fakefez_qaoa_mis_new.py` | Max Independent Set on FakeFez |

### Reinforcement Learning
| File | Description |
|------|-------------|
| `ppo_lunarlander.py` | PPO from scratch, 30 seeds |
| `sb3_customer.py` | SB3 PPO with MobiuCallback |
| `test_portfolio_ppo.py` | PPO portfolio trading |
| `test_mujoco_customer.py` | MuJoCo InvertedPendulum + Hopper |
| `atari_breakout_customer.py` | Atari Breakout DQN |
| `crypto_trading_fair.py` | Crypto Trading PPO — BTC-like synthetic, regime switching |
| `crypto_trading_realdata.py` | Crypto Trading PPO — BTC-USD real daily data |

### Machine Learning
| File | Description |
|------|-------------|
| `test_federated_customer.py` | Federated learning (non-IID) |
| `test_noisy_labels_customer.py` | Systematic label noise |
| `test_sim_to_real_customer.py` | Sim-to-real transfer |
| `test_imbalanced_customer.py` | 90% class imbalance |
| `test_llm_finetuning_v3.py` | LoRA + Full fine-tuning |

### Black-box & Signal Processing
| File | Description |
|------|-------------|
| `test_sphere.py` | Sphere (shot noise) |
| `test_ackley.py` | Ackley (shot noise) |
| `test_beale.py` | Beale (shot noise) |
| `test_rosenbrok.py` | Rosenbrock (shot noise) |
| `blackbox_spsa_customer.py` | Rastrigin + SPSA |
| `antenna_customer.py` | 5G antenna beamforming |
| `periodic_benchmark.py` | Noisy periodic landscape |

### Utilities & Demos
| File | Description |
|------|-------------|
| `double_mobiu_customer.py` | MobiuAttention + MobiuOptimizer |
| `nilpotency_ablation.py` | Real SA vs Fake SA ablation |
| `benchmark_behavioral_customer.py` | MobiuAD behavioral detection |
| `example_signal_customer.py` | MobiuSignal demo |

---

## License

| Tier | API Calls | Price | Get Started |
|------|-----------|-------|-------------|
| Free | 20/month | $0 | [Sign up](https://app.mobiu.ai) |
| Pro | Unlimited | $19/month | [Get one](https://app.mobiu.ai) |

**Note:** MobiuAttention & MobiuSignal run locally — no API calls required.

---

## Links

- [PyPI](https://pypi.org/project/mobiu-q/)
- [GitHub](https://github.com/mobiuai/mobiu-q/)
- [Website](https://mobiu.ai)

---

## Citation

```bibtex
@software{mobiu_q,
  title={Mobiu-Q: Soft Algebra for Optimization, Attention and Anomaly Detection},
  author={Mobiu Technologies},
  year={2026},
  url={https://mobiu.ai}
}
```