Metadata-Version: 2.4
Name: mobiu-q
Version: 6.2
Summary: Soft Algebra Optimizer + O(N) Linear Attention + Streaming Anomaly Detection
Author-email: Mobiu Technologies <support@mobiu.ai>
License: Proprietary
Project-URL: Homepage, https://mobiu.ai
Project-URL: Documentation, https://docs.mobiu.ai
Project-URL: Repository, https://github.com/mobiuai/mobiu-q
Keywords: quantum,optimization,VQE,QAOA,machine-learning,deep-learning,pytorch,optimizer,attention,transformer,linear-attention,long-context,llm,anomaly-detection,streaming,trainguard,monitoring
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.21.0
Requires-Dist: requests>=2.25.0
Requires-Dist: torch>=1.9.0
Requires-Dist: scipy
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black>=21.0; extra == "dev"
Requires-Dist: isort>=5.0; extra == "dev"
Requires-Dist: flake8>=3.9; extra == "dev"
Provides-Extra: quantum
Requires-Dist: qiskit>=0.40.0; extra == "quantum"
Requires-Dist: pennylane>=0.28.0; extra == "quantum"
Provides-Extra: detection
Requires-Dist: pyod>=1.0.0; extra == "detection"
Provides-Extra: all
Requires-Dist: qiskit>=0.40.0; extra == "all"
Requires-Dist: pennylane>=0.28.0; extra == "all"
Requires-Dist: pyod>=1.0.0; extra == "all"

# Mobiu-Q

**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 applies **Klein-Maimon Soft Algebra** to optimization and streaming computation. Its optimizer maintains a soft number with two interacting components, composes incoming signals with that state, and reads the result to control learning rates and, depending on the method, gradient scaling.

The optimization mechanism follows a concrete path:

**Objective history → soft signal → algebraic state composition → control decision → optimizer update.**

The soft state is part of the computation. In an audit of SDK 6.1.9 captures, all **367 server decisions** from a LunarLander PPO run and a VQE run were independently reproduced from the supplied source. A traced PPO decision shows historical composition changing the learning-rate multiplier from **1.82023 for the current signal alone to 3.0 for the composed state**, with the chosen rate applied for 50 optimizer updates. See [Verified execution](#verified-execution).

The package includes:

1. **MobiuOptimizer** — soft-state control around a compatible base optimizer.
2. **MobiuAttention** — experimental attention components.
3. **MobiuSignal** — streaming signal processing.
4. **MobiuAD** — streaming anomaly detection.
5. **TrainGuard** — training monitoring.

Different optimization methods read different properties of the soft state. The mechanism descriptions below distinguish the shared algebra from each method's control rule. The latest execution audit covers **adaptive for PPO** and **standard for VQE**; it does not rank the other methods.

---

## 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",   # audited PPO method; select explicitly for your workload
    base_lr=3e-4,        # always pass base_lr to match your optimizer's LR
    boost="none",        # "none" (default) | "normal" | "aggressive"
    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

A license key is required to use MobiuOptimizer and MobiuQCore. MobiuAttention and MobiuSignal run entirely on the client and need no key — see the notes in their sections below.

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

| Tier | API Calls | Price | Includes |
|------|-----------|-------|----------|
| Free | 20/month | $0 | Cloud access |
| Research | Unlimited | $490/month | Cloud access + priority support |
| Enterprise | Unlimited | Contact us | Self-hosted / air-gapped + SLA |

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

---

## MobiuOptimizer

### Methods and their control rules

The methods share the signal-to-soft-number mapping and the state law
`S_next = (0.9 * S) ⊗ delta + delta`. Their readouts determine how the composed state affects the optimizer. Formulas below describe the supplied 6.1.9 core; use an explicit method when reproducing a benchmark.

| Method | How the soft state controls optimization | Audit coverage |
|---|---|---|
| `standard` | Uses the trust readout to set the learning rate and the internal soft-state factor to scale the gradient in server-side optimization. | Captured VQE run |
| `adaptive` | Combines trust with the super-equation score to set the learning rate, capped at 3 times the base rate. Hybrid PyTorch execution applies a separate gradient multiplier. | Captured LunarLander PPO run |
| `deep` | Reads the super-equation score and applies state-dependent damping to the rate. The sine contribution is the exact first-order soft coefficient, not a second-order nilpotent term. | Not exercised in this audit |
| `mobius` | Reads `M = B * sign(A) / (abs(A) + abs(B))`; the supplied 6.1.9 core uses `lr = base_lr * (1 + M)` with a `0.05 * base_lr` floor. | Not exercised in this audit |
| `mobius_full` | Uses the same signed measurement coordinate for the rate and its potential complement `abs(A)/(abs(A)+abs(B))` for gradient scaling. | Not exercised in this audit |
| `pure` | Reads geometric functions of the state to set rate and gradient scaling. | Not exercised in this audit |
| `use_deltadagger=True` | Selects a separate experimental state and calibration path using `DeltaSoftNumber`. This flag is distinct from the super-equation already used by `adaptive`. | Disabled in both captures |

### Using the new logic (`use_deltadagger`)

Instead of using `method="deltadagger"`, we recommend activating the new logic via the parameter:

```python
# Recommended way
opt = MobiuOptimizer(
    base_opt,
    license_key=KEY,
    method="mobius",           # or "adaptive", "standard", etc.
    use_deltadagger=True       # activates the new DeltaSoftNumber + theoretical peak logic
)ֿ
```

**Select the method explicitly.** The audited PPO configuration uses `adaptive`; the audited VQE configuration uses `standard`. The other methods remain available for workload-specific evaluation. The capture audit does not establish a universal best method.

**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 hybrid PyTorch execution the client optimizer uses the rate returned by the controller; pass `base_lr` explicitly as the reference rate.

### 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`.

### LR Boost (optional)

The `boost` parameter controls a client-side learning rate engine that runs alongside Soft Algebra. **Off by default (`boost="none"`).**

```python
# Default — Soft Algebra only, no LR modification
opt = MobiuOptimizer(base_opt, license_key=KEY, method="adaptive", base_lr=3e-4)

# Gentle warmup + stagnation recovery
opt = MobiuOptimizer(base_opt, ..., boost="normal")

# Strong warmup + stagnation recovery (RL, sparse reward)
opt = MobiuOptimizer(base_opt, ..., boost="aggressive")
```

| Value | Warmup LR | Stagnation Spike | Smart Brake |
|-------|-----------|------------------|-------------|
| `"none"` | — | — | — |
| `"normal"` | 1.5× base_lr | 1.5× spike | ✅ cancels if improving |
| `"aggressive"` | 3.0× base_lr | 3.0× spike | ✅ cancels if improving |

**When to use boost:**

| Environment | Recommended | Reason |
|-------------|-------------|--------|
| Supervised learning, VQE | `"none"` | Smooth loss landscape, SA sufficient |
| SB3 / stable frameworks | `"normal"` | Framework manages policy updates internally |
| Portfolio / regime-switching trading | `"normal"` | Stable reward signal per episode |
| PPO from scratch, sparse reward | `"aggressive"` | High variance, needs strong LR push |
| MuJoCo, Atari, Crypto PPO | `"aggressive"` | Sparse/delayed reward signal |

**Key finding:** `"aggressive"` hurts SB3 (60% win rate vs 70% for `"normal"`). SB3's internal update loop conflicts with strong LR boosts. Use `"normal"` for any framework that manages its own optimizer calls.

**`update_interval`** — set to `1` when `optimizer.step()` is called once per episode (e.g. portfolio trading, crypto). Default is `320` (standard PPO mini-batch size).

```python
# Per-episode training loop
opt = MobiuOptimizer(base_opt, ..., boost="aggressive", update_interval=1)
```

**Verbose feedback:** set `verbose=True` to see what the boost engine is doing:
```
⚡ Boost (aggressive): attempting warmup (3.0x LR)...
💡 Boost (aggressive): warmup cancelled — training already improving
⚡ Boost (aggressive): attempting stagnation spike (3.0x LR)...
```
No message means training is going well on its own — no boost was applied.

### Benchmark protocol

Adam comparisons use the **baseline configuration specified by each benchmark for its task**: for example, the PPO setup's default learning rate or the VQE script's stated baseline rate. These are task-level defaults, not necessarily the optimizer library's constructor defaults. Where a table names another optimizer or a boost configuration, that label defines the comparison.

Report the exact learning rate, optimizer settings, method, boost, synchronization interval, training budget, seeds, and evaluation procedure with each result. Compare **Pure Adam** with **Adam wrapped by MobiuOptimizer** using matched initialization and controlled random streams:

```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
    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

The following tables retain the previously reported results and their version labels. The 6.1.9 capture audit below verifies execution of the mechanism; it is separate from these multi-seed performance experiments. Interpret each improvement relative to its stated task baseline and metric. For rewards that can be negative or near zero, report absolute reward differences alongside any percentage.

#### Reinforcement Learning (v4.5)

**boost=none** (Soft Algebra only):

| Domain | Improvement | Win Rate | Seeds | p-value |
|--------|-------------|----------|-------|---------|
| LunarLander-v3 (PPO) | **+30.6%** | 77% (23/30) | 30 | 0.000566 |
| LunarLander-v3 (SB3 PPO) | **+109%** | 67% (20/30) | 30 | 0.047 |
| Portfolio Trading (PPO) | **+133.9%** | 100% (10/10) | 10 | 0.000977 |
| MuJoCo InvertedPendulum-v5 | **+17.7%** | 40% (4/10) | 10 | — |
| MuJoCo Hopper-v5 | **+9.8%** | 70% (7/10) | 10 | — |
| Crypto Trading (BTC-like) | **+168%** | 95% (19/20) | 20 | 0.000002 |
| Crypto Trading (BTC-USD real) | **+48.7%** | 100% (20/20) | 20 | 0.000001 |

**boost=aggressive** (recommended for PPO from scratch):

| Domain | Improvement | Win Rate | Seeds | p-value |
|--------|-------------|----------|-------|---------|
| LunarLander-v3 (PPO) | **+74.1%** | 97% (29/30) | 30 | <0.000001 |
| MuJoCo InvertedPendulum-v5 | **+68.5%** | 60% (6/10) | 10 | — |
| MuJoCo Hopper-v5 | **+33.4%** | 90% (9/10) | 10 | — |
| Portfolio Trading (PPO) | **+160.4%** | 100% (10/10) | 10 | 0.000977 |
| Crypto Trading (BTC-like) | **+318.1%** | 95% (19/20) | 20 | 0.000002 |
| Atari Breakout | **+53.1%** | 100% (5/5) | 5 | — |

**boost=normal** (recommended for SB3 and stable frameworks):

| Domain | Improvement | Win Rate | Seeds | p-value |
|--------|-------------|----------|-------|---------|
| LunarLander-v3 (SB3 PPO) | **+138.7%** | 70% (21/30) | 30 | 0.008705 |
| Portfolio Trading (PPO) | **+165.2%** | 100% (10/10) | 10 | 0.000977 |
| Crypto Trading (BTC-like) | **+275%** | 95% (19/20) | 20 | 0.000002 |

#### 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,
    boost="aggressive",   # optional: helps in high-variance RL
    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",
            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)

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

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 feedback

opt.end()
```

### How objective feedback enters the controller

Federated, imbalanced, simulation-transfer and noisy-label workloads can produce changing loss trajectories. Mobiu extracts temporal variation and signed realized change from those trajectories, composes them with its soft state, and adjusts the optimizer's controls.

The realized signal measures relative objective change. It does not directly measure the angle between the supplied gradient and an unknown true gradient. Scalar gradient scaling preserves the instantaneous direction; its interaction with Adam's evolving moments can affect later parameter updates. Reported gains on these workloads should be interpreted through the specified experiment rather than as proof of a general gradient-bias detector.

### 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)
    gradient = simulator_gradient(policy, step)  # biased (wrong physics)
    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())

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,
    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,
    boost="normal",       # helpful for regime-switching environments
    update_interval=1,    # one step() call per episode
    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,
    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,
    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()
```

---

## Known Limitations

### Workload and execution considerations

Mobiu changes the optimization trajectory through a state-dependent learning rate and, for applicable methods, gradient scaling. Its effect depends on the selected method, objective signal, synchronization interval and base optimizer. The observations below describe particular workloads and configurations.

### When Mobiu-Q does not help (or can hurt slightly)

**1. Already-converged policies in continuous-control RL.**

Mobiu-Q's strongest wins are when a base optimizer is stuck. When the base has already found a good local optimum, the additional warping sometimes perturbs rather than helps.

| Benchmark | Result | Win rate | p-value |
|-----------|--------|----------|---------|
| SAC HalfCheetah-v5 (Actor+Critic wrap, already converged) | regression on some seeds | 9/20 | 0.849 (not significant) |
| SAC HalfCheetah-v5 (stuck seeds only, <-100 reward) | **+163% to +309%** | 100% on stuck seeds | — |

The pattern is bimodal: **strong gains when the base is stuck, marginal or slightly negative when already converged.** A conditional-wrapping mode (activate Mobiu-Q only when recent reward is below threshold) is planned for a future release. For now, the practical rule is: don't wrap an SAC policy that's already training well — there's nothing to fix.

**2. Data-quality problems misdiagnosed as gradient bias.**

The controller receives objective feedback; it does not directly repair labels, features, or distribution mismatch in the input data.

| Benchmark | Bias source | Result |
|-----------|-------------|--------|
| Logistics ranker (feature-level noise) | non-systematic label noise | Mobiu loses |
| Logistics ranker (random label flip) | stochastic, not directional | Mobiu loses |

If your baseline Adam is struggling because the data is noisy or mislabeled in a random (non-systematic) way, a data-cleaning pipeline will beat any optimizer change. See "How objective feedback enters the controller" for the measured inputs and their interpretation.

**2b. Optimizers already at their stability-ceiling LR (e.g. DQN / Atari).**

Because `mobius` dials the LR *upward* when learning is going well (`lr` up to
`2·base_lr`), it can hurt on setups whose default LR is already the maximum stable
value. Deep Q-learning is the clearest case: DQN/Atari with `lr=1e-4` does not
tolerate higher rates (the bootstrapped Q-targets destabilize), so `mobius` climbing
above `1e-4` degrades training. **Rule:** if your `base_lr` is already at the edge of
stability, either pass a **lower** `base_lr` (so the climb stays in the stable range,
e.g. `5e-5`) or use plain Adam. `mobius` helps when the default LR is *conservative*
(room to climb), not when it is already maxed out.

### Startup and cloud execution

The controller needs two objective observations to compute signed change and three to compute temporal curvature. In the captured hybrid setup with `sync_interval=50`, these correspond to approximately 100 and 150 optimizer updates. Rate adaptation can begin before the curvature signal is available; such a run is not necessarily plain Adam until update 150.

Verify cloud responses and actual client controls when diagnosing activation. If connectivity fails, inspect the SDK's reported fallback behavior and exclude incomplete or fallback runs from claims about verified server execution.

### Hard constraints

**5. Rate limit.** 20 requests/second per license key. Production training at very high step rates should use `sync_interval ≥ 50` (the default) — this has been tuned for typical deep-learning workloads.

**6. Quantum/NumPy base optimizers.** In `MobiuQCore` (quantum mode), the server-side base optimizer is limited to: `Adam`, `NAdam`, `AMSGrad`, `SGD`, `Momentum`, `LAMB`. No RMSprop or Adagrad. PyTorch hybrid mode has no such restriction — any optimizer with `.step()`, `.zero_grad()`, and `.param_groups` works.

### How to tell if Mobiu-Q is actually helping

Run a fair A/B on your own problem before relying on it:

```python
# Toggle Soft Algebra on/off with the same base optimizer, same seed, same data
opt_on  = MobiuOptimizer(base_opt, license_key=KEY, use_soft_algebra=True,  method="adaptive")
opt_off = MobiuOptimizer(base_opt, license_key=KEY, use_soft_algebra=False, method="adaptive")
```

Similar results with `use_soft_algebra=False` and `True` indicate no demonstrated benefit under that protocol. They do not diagnose the presence or absence of gradient-direction bias.

---

## 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. Boost not showing messages?

If you set `boost="aggressive"` but see no `⚡` messages:
- Check `verbose=True` is set on `MobiuOptimizer`
- If you call `step()` once per episode, add `update_interval=1`

### 6. Common Fixes by Domain

| Domain | Issue | Fix |
|--------|-------|-----|
| **RL (PPO)** | rewards unstable | `boost="aggressive"` + `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` |
| **Portfolio/Crypto** | boost not firing | add `update_interval=1` |

---

## MobiuOptimizer — A/B Testing

To measure the effect of enabling the soft-state controller, compare `use_soft_algebra=True` and `False` under the same benchmark protocol:

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

# SA OFF (soft-state controller disabled)
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)

**Interpretation:** In this previously reported experiment, the implemented soft controller outperformed the listed alternatives. Changing multiplication changes the subsequent state and control trajectory. The result compares those complete implementations under that protocol; it does not allocate a percentage of the gain to an isolated algebraic term.

---

## 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 numbers and the zero axis

Klein and Maimon's *Foundations of Soft Logic* develops a zero axis, bridge numbers and soft numbers, together with a geometric coordinate system related to the Möbius strip. Mobiu uses a two-coefficient representation:

```text
S = A·ε + B                ε ≠ 0, ε² = 0
(A,B) + (a,b) = (A+a, B+b)
(A,B) ⊗ (a,b) = (A·b+B·a, B·b)
```

A zero real component does not erase the soft coordinate: `SoftNumber(3, 0)` differs from `SoftNumber(4, 0)` and from `SoftNumber(0, 0)`. The book's zero-axis interpretation motivates retaining these distinct soft multiples instead of collapsing them to a single real zero. Here `ε` denotes the soft zero-axis unit, not the ordinary real number `0`.

For example, `(3,0) ⊗ (0,2) = (6,0)`: a purely soft state can participate in later composition. In contrast, the product of two purely soft states vanishes under nilpotency.

### Relation to dual numbers: interpretation and use

Appendix A.2 of the book explicitly identifies an algebraic isomorphism with dual numbers and locates the distinction in the geometric interpretation: the zero axis and the associated soft coordinate system. Distinct elements `3ε` and `4ε` also exist in the dual-number algebra. Their existence is therefore not a property absent from dual numbers.

**Mobiu's use of this structure is a temporal optimization state.** The soft coefficient represents an objective-derived potential signal, while the real coefficient represents realized change. They evolve through soft multiplication and are read jointly to control optimization. The soft coefficient is not required to be a derivative of the real coefficient, as it would be in a forward-mode differentiation use of dual numbers. This is a distinction in interpretation and application, not a claim of a different multiplication table.

The current pair representation preserves the zero-axis coordinate. It does not by itself implement every geometric construction in the book. Mobiu's signal mapping and controller laws are the application's design, built using that representation and algebra.

Reference: Moshe Klein and Oded Maimon, *Foundations of Soft Logic*, Springer, 2024, Chapters 3–5 and Appendix A.2, printed pp. 136–137. [Book DOI](https://doi.org/10.1007/978-3-031-58233-2).

### Signal extraction and composition

For a minimization objective, the audited legacy path computes:

```text
curvature = abs(E_t - 2*E_(t-1) + E_(t-2))
a = curvature / (curvature + abs(mean(last_three_energies)))
b = clip((E_(t-1) - E_t) / (abs(E_(t-1)) + 1e-9), -1, 1)

S_next = (γ*S) ⊗ (a,b) + (a,b)          γ = 0.9
A_next = a + γ*A*b + γ*B*a
B_next = b + γ*B*b
```

The code includes startup and near-zero guards. Temporal curvature describes changes along the observed objective sequence; it is not a Hessian calculation. In the captured PPO run, each server input is the mean of 50 training losses. In VQE it is a measured energy.

The two cross terms carry history into the new soft coordinate. Their size and sign depend on the relationship between past state and present signal. Consequently, this update is different from independently averaging each component with a fixed EMA weight.

### From soft state to optimization controls

| Component | Audited rule | Optimization role |
|---|---|---|
| Trust | Usually `abs(B)/(abs(A)+abs(B))`, with explicit origin and near-zero branches | Sets the trust-based rate multiplier; this absolute-value readout alone does not encode the sign of improvement. |
| Soft sine coefficient | `π*A*cos(π*B)` | Exact coefficient of `ε` in `sin(π*S)`; enters the adaptive super-equation. |
| Super-equation | Combines the sine coefficient with `τ=3*A*B`, a Gaussian gate and soft/real component gates | Modulates adaptive acceleration. It is a control law using soft calculus and scalar functions. |
| `standard` rate | `base_lr * clip(1+trust, 0.5, 2)`, plus the zero-rate branch | Sets the rate in the captured VQE run. |
| `adaptive` rate | `base_lr * min(3, clip(1+trust, 0.5, 2)*(1+2*delta_dagger))` | Sets the rate in the captured PPO run. |
| Internal warp | `1 + abs(A)/(abs(A)+B**2)`, with numerical guards | Scales the gradient before server-side Adam in VQE. The “Soft Inverse” name denotes this control factor, not direct inversion in the ring. |
| Hybrid warp | `clip(1+0.1*A*(1-r), 0.5, 2)`, where `r=abs(B)/(abs(A)+abs(B)+1e-8)` | Scales actual PPO client gradients at synchronization. |
| Base optimizer | Existing moment and parameter-update rules | Converts the controller's rate and gradient into parameter changes. |

The first-order soft-calculus identity is `f(B+Aε)=f(B)+A*f′(B)*ε`. Nilpotency removes the soft-soft term from multiplication; it does not automatically remove noise from measured inputs or cross terms.

### Verified execution

Two complete SDK 6.1.9 captures were audited: one LunarLander PPO seed in `adaptive` mode and one VQE seed in `standard` mode. Both had `use_soft_algebra=True` and the experimental `use_deltadagger` branch disabled.

| Check | LunarLander PPO | VQE |
|---|---:|---:|
| Independently replayed server decisions | 307 | 60 |
| Maximum discrepancy in checked response outputs | 0 | 0 |
| Recorded optimizer updates | 15,360 | 60 |
| Synchronization | Every 50 updates | Every step |

The replay checked returned learning rates, warp factors and new parameters where present. Source hashes matched the capture manifests. All 307 PPO synchronization snapshots were additionally checked against gradient scaling, Adam moments and parameter updates, with differences consistent with float32 rounding.

At PPO update **10,000**, the composed state selected **3.0 × base_lr**. Reading the current signal alone at the same observed instant selected **1.82023 × base_lr**. The actual 3.0 multiplier was applied for updates **10,000–10,049**. This traces algebraic composition through a control decision to executed optimization steps.

The relative contribution of the history terms changed differently across tasks: its mean rose from **11.52% to 18.63%** between the first and final thirds of PPO, and fell from **20.50% to 3.50%** in VQE. These values describe the sum of absolute history contributions relative to all contributions to the soft-state update, excluding the first two server decisions. They are not percentages of performance gain.

This audit establishes active use of the algebra on the observed trajectories. Performance comparisons remain the separate, task-specific benchmark results above.

## 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) |
| Research | Unlimited | $490/month | [Subscribe](https://app.mobiu.ai) |
| Enterprise | Self-hosted + SLA | Contact us | [enterprise@mobiu.ai](mailto:enterprise@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}
}
```
