Metadata-Version: 2.4
Name: rc_predication
Version: 0.1.0
Summary: Parameter-aware reservoir computing for critical transition and system collapse prediction
Project-URL: Homepage, https://github.com/jinchen7-cmd/Reservoir-Computing
Project-URL: Documentation, https://github.com/jinchen7-cmd/Reservoir-Computing#readme
Project-URL: Repository, https://github.com/jinchen7-cmd/Reservoir-Computing
Project-URL: Issues, https://github.com/jinchen7-cmd/Reservoir-Computing/issues
Author: Jincheng (Jeffery) Rao
License-Expression: MIT
License-File: LICENSE
Keywords: critical-transition,echo-state-network,esn,machine-learning,reservoir-computing,time-series,tipping-point,transient-chaos
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Requires-Dist: scikit-learn>=1.3
Requires-Dist: scipy>=1.10
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: examples
Requires-Dist: ipykernel>=6.0; extra == 'examples'
Requires-Dist: jupyter>=1.0; extra == 'examples'
Requires-Dist: matplotlib>=3.7; extra == 'examples'
Description-Content-Type: text/markdown

# RC_predication

**Model-free prediction of critical transitions and system collapse** using parameter-aware reservoir computing.

Based on Kong, Fan, Grebogi & Lai, [*Machine learning prediction of critical transition and system collapse*](https://doi.org/10.1103/PhysRevResearch.3.013090), Phys. Rev. Research **3**, 013090 (2021).

---

## What this package does

Nonlinear systems can undergo a **catastrophic bifurcation** when a control parameter drifts:

| Regime | Dynamics | Outcome |
|--------|----------|---------|
| **Pre-critical** ($p < p_c$) | Sustained chaos on a normal attractor | System is safe |
| **Post-critical** ($p > p_c$) | Transient chaos, then escape | Irreversible collapse |

The governing equations are usually unknown. **RC_predication** learns from observed time series taken **only in the pre-critical regime** and predicts:

1. Whether a given parameter value leads to collapse
2. The critical transition point $p_c^*$
3. The distribution of transient lifetimes beyond $p_c$

---

## Method

Standard reservoir computing is extended with a **bifurcation-parameter input channel** $\mathcal{W}_b$. The reservoir receives both the dynamical state $\mathbf{u}(t)$ and the parameter $p$:

$$
\mathbf{r}(t+\Delta t) = (1-\alpha)\mathbf{r}(t) + \alpha\,\tanh\!\big[\mathcal{A}\mathbf{r}(t) + \mathcal{W}_{in}\mathbf{u}(t) + k_b\mathcal{W}_b(p + b_0)\big]
$$

$$
\mathbf{v}(t) = \mathcal{W}_{out}\mathbf{r}(t)
$$

- $\mathcal{W}_{out}$ is **trained** (ridge regression, one-step ahead: $\mathbf{v}(t) \approx \mathbf{u}(t+\Delta t)$)
- $\mathcal{W}_{in}$, $\mathcal{W}_b$, $\mathcal{A}$ are **fixed** after random initialization

### Training rule: at least 3 parameter values

Training **requires time series from at least three distinct parameter values**, all in the **pre-critical** (sustained chaos) regime. This is how the RC learns how dynamics change with $p$.

| Rule | Requirement |
|------|-------------|
| Minimum training parameters | **≥ 3** distinct $p_i$ |
| Parameter range | All $p_i < p_c$ (pre-critical, safe) |
| Dynamics at each $p_i$ | Sustained chaos on the attractor |
| Data per $p_i$ | Long enough to capture attractor structure |

Paper examples: Ikeda map at $\mu = 0.91,\, 0.94,\, 0.97$; food chain at $K = 0.97,\, 0.98,\, 0.99$.

### Prediction: closed-loop rollout

At prediction time, hold parameter $p_{\text{test}}$ fixed and run the RC autonomously:

$$
\mathbf{u}(t+\Delta t) = \mathbf{v}(t)
$$

- $p_{\text{test}} < p_c$ → trajectory stays on the attractor (**safe**)
- $p_{\text{test}} > p_c$ → trajectory escapes after transient chaos (**collapse**)

Scan $p_{\text{test}}$ to estimate $p_c^*$. Use an **ensemble** of independent reservoir seeds for robust estimates.

---

## Architecture

```mermaid
flowchart TB
    subgraph Input
        U["u(t) — observed state"]
        P["p — bifurcation parameter"]
    end

    subgraph RC["ParameterAwareRC"]
        WIN["W_in (fixed)"]
        WB["W_b (fixed) → all nodes"]
        A["A (fixed)"]
        R["r(t) reservoir state"]
        WOUT["W_out (trained)"]
        V["v(t) prediction"]
    end

    U --> WIN --> TANH
    P --> WB --> TANH
    A --> TANH["tanh(·) + leak α"]
    TANH --> R --> WOUT --> V
    V -.->|"closed loop"| U
```

```mermaid
flowchart LR
    subgraph Train["Training (pre-critical only)"]
        P1["p₁"] --> D1["u₁(t)"]
        P2["p₂"] --> D2["u₂(t)"]
        P3["p₃"] --> D3["u₃(t)"]
        D1 & D2 & D3 --> FIT["Fit W_out\n(n ≥ 3 required)"]
    end

    subgraph Predict["Prediction"]
        FIT --> CL["Closed-loop at p_test"]
        CL --> SAFE["p < p_c → safe"]
        CL --> COLLAPSE["p > p_c → collapse"]
    end

    subgraph Analysis
        COLLAPSE --> PC["Estimate p*_c"]
        COLLAPSE --> TAU["Transient lifetime τ"]
    end
```

---

## Installation

### From PyPI (any machine)

```bash
pip install rc_predication
```

Optional extras:

```bash
pip install "rc_predication[examples]"   # matplotlib, Jupyter
pip install "rc_predication[dev]"        # pytest, ruff, build tools
```

### From source (development)

```bash
git clone https://github.com/jinchen7-cmd/Reservoir-Computing.git
cd Reservoir-Computing
pip install -e ".[dev]"
```

This registers `rc_predication` in editable mode so local changes apply immediately.

**Requirements:** Python ≥ 3.10 · NumPy · SciPy · scikit-learn

See [Tests](#tests) for how to run the test suite.

### Publishing to PyPI (maintainers)

The package is not on PyPI until you publish it once:

1. Create an account at [pypi.org](https://pypi.org/account/register/).
2. Create an API token (Account settings → API tokens) scoped to project `rc_predication`.
3. In GitHub: **Settings → Secrets and variables → Actions** → add `PYPI_API_TOKEN`.
4. Push this repo and either:
   - **GitHub → Actions → Publish to PyPI → Run workflow**, or
   - Create a **Release** (e.g. tag `v0.1.0`) to publish automatically.

Manual upload from the repo root:

```bash
pip install -e ".[dev]"
python -m build
twine upload dist/*
```

---

## Quick start

### Critical transition prediction (main use case)

```python
from rc_predication import ParameterAwareRC
from rc_predication.systems import IkedaMap

# 1. Generate training data — at least 3 pre-critical parameter values
system = IkedaMap()
training_data = {
    0.91: system.simulate(mu=0.91, n_steps=10_000),
    0.94: system.simulate(mu=0.94, n_steps=10_000),
    0.97: system.simulate(mu=0.97, n_steps=10_000),
}

# 2. Train
model = ParameterAwareRC(n_units=1000, random_state=42)
model.fit(training_data, parameter_name="mu")

# 3. Closed-loop prediction
safe = model.predict_closed_loop(p_test=0.99, n_steps=5000)
collapse = model.predict_closed_loop(p_test=1.01, n_steps=5000)
print(safe.collapsed)      # False
print(collapse.collapsed)  # True

# 4. Scan parameter range → critical point
scan = model.scan_critical_point(p_range=(0.98, 1.02), n_points=20)
print(f"p*_c ≈ {scan.p_critical:.4f}")

# 5. Ensemble for robust estimate
result = model.ensemble_predict(n_realizations=100, p_test=1.01)
print(f"Mean transient lifetime: {result.mean_lifetime:.1f}")
```

### Food chain (Hastings–Powell / McCann–Yodzis)

```python
from rc_predication import FoodChain
from rc_predication.systems.food_chain import DEFAULT_TRAINING_K

model = FoodChain()
training_data = model.simulate_training_set(DEFAULT_TRAINING_K, random_state=42)
# training_data: {0.97: array(...), 0.98: array(...), 0.99: array(...)}
# each array shape (n_steps, 3) — columns [R, C, P]
```

### Basic ESN (building block)

```python
from rc_predication import ESN
from rc_predication.utils import lorenz_system, train_test_split_sequence

data = lorenz_system(5000)
X, y = data[:-1], data[1:]
X_train, X_test, y_train, y_test = train_test_split_sequence(X, y)

model = ESN(n_units=500, spectral_radius=0.9, leaking_rate=0.3, warmup=500)
model.fit(X_train, y_train)
print(model.score(X_test, y_test, warmup=0))
```

---

## Package structure

Everything lives in a single package: `rc_predication`.

```
src/rc_predication/
├── __init__.py                  # Public API
│
├── base.py                      # BaseEstimator, array validation
├── reservoir.py                 # Leaky integrator reservoir
├── readout.py                   # Ridge readout
├── esn.py                       # Echo State Network
├── topology.py                  # Sparse weights, spectral radius
├── metrics.py                   # RMSE, NRMSE, memory capacity
├── utils.py                     # Lorenz generator, standardize, splits
│
├── arc/                         # Parameter-aware RC (paper method)
│   ├── parameter_aware_rc.py    # RC with bifurcation-parameter channel
│   ├── trainer.py               # Multi-parameter training (≥3 values)
│   ├── predictor.py             # Closed-loop rollout
│   └── exceptions.py            # InsufficientParameterValues, etc.
│
├── systems/                     # Benchmark dynamical systems
│   ├── ikeda.py                 # Ikeda map (μ_c ≈ 1.0027) ✅
│   ├── food_chain.py            # Hastings–Powell / McCann–Yodzis (K bifurcation) ✅
│   └── kuramoto_sivashinsky.py  # Spatiotemporal chaos (SI) ✅
│
├── analysis/                    # Post-prediction analysis
│   ├── critical_point.py        # Parameter scan → p*_c
│   ├── transient_lifetime.py    # Lifetime distribution P(τ)
│   └── ensemble.py              # Ensemble over reservoir seeds
│
└── hpo/                         # Hyperparameter optimization
    └── bayesian_opt.py          # 7 hyperparameters (optional)
```

### Public API

| Import | Description |
|--------|-------------|
| `ParameterAwareRC` | Main model — parameter channel + closed-loop prediction |
| `ESN` | Standard Echo State Network |
| `Reservoir` | Leaky integrator dynamics |
| `RidgeReadout` | L2-regularized linear readout |
| `IkedaMap`, `FoodChain` | Paper benchmark systems |
| `scan_critical_point` | Estimate $p_c^*$ from parameter sweep |
| `ensemble_predict` | Robust prediction over reservoir realizations |
| `memory_capacity` | Jaeger (2001) memory benchmark |

---

## Hyperparameters

The paper optimizes seven hyperparameters via Bayesian optimization:

| Parameter | Role |
|-----------|------|
| Average degree | Reservoir connectivity |
| Spectral radius $\rho(\mathcal{A})$ | Echo state property |
| $\mathcal{W}_{in}$ scale | Input weight magnitude |
| $k_b$ | Parameter channel gain |
| $b_0$ | Parameter channel bias |
| $\alpha$ | Leak rate |
| Ridge $\lambda$ | Readout regularization |

---

## Benchmark systems

| System | Parameter | $p_c$ (paper) | Training values |
|--------|-----------|---------------|-----------------|
| Ikeda map | $\mu$ | 1.0027 | 0.91, 0.94, 0.97 |
| Food chain | $K$ | 0.99976 | 0.97, 0.98, 0.99 |
| Kuramoto–Sivashinsky | — | (see SI) | Pre-critical regime |

---

## Tutorials

Open the Jupyter notebook:

```bash
pip install -e ".[examples]"
python -m ipykernel install --user --name rc_predication
jupyter notebook tutorials/rc_predication_tutorial.ipynb
```

In Jupyter, select kernel **rc_predication**. If you skip the install, run the first code cell in the notebook — it adds `src/` to the path automatically.

| Section | Content |
|---------|---------|
| 1 | Ikeda map — train, predict, scan $p_c^*$ |
| 2 | Food chain — predator collapse |
| 3 | Ensemble averaging for robust $p_c^*$ |
| 4 | Transient lifetime distribution $P(\tau)$ |
| 5 | Optional hyperparameter fine-tuning |

---

## Project status

| Module | Status |
|--------|--------|
| Core RC (`Reservoir`, `ESN`, `RidgeReadout`) | ✅ Implemented |
| `arc/` — parameter-aware RC | ✅ Implemented |
| `systems/` — Ikeda, food chain, Kuramoto–Sivashinsky | ✅ Implemented |
| `analysis/` — critical point, lifetime, ensemble | ✅ Implemented |
| `hpo/` — hyperparameter search | ✅ Implemented |
| Tutorials (`tutorials/rc_predication_tutorial.ipynb`) | ✅ Implemented |

---

## Tests

### 1. Install dev dependencies

From the repo root (required once):

```bash
pip install -e ".[dev]"
```

On Windows with a specific Python:

```powershell
cd C:\Users\jinchen7\Desktop\Reservoir-Computing
python -m pip install -e ".[dev]"
```

### 2. Run tests with pytest

**Use `pytest`**, not `python tests/test_*.py`. Test files are not standalone scripts.

```bash
# All tests
pytest

# One file
pytest tests/test_food_chain.py

# One test by name
pytest tests/test_parameter_aware_rc.py::test_fit_and_closed_loop

# Verbose (extra pytest detail)
pytest -v
```

### 3. Expected output

Each test prints `PASS` or `FAIL` as it runs. At the end you should see:

```
rc_predication test suite
----------------------------------------
  PASS  tests/test_food_chain.py::test_rhs_shape
  PASS  tests/test_food_chain.py::test_simulate_shape_and_positive_predator
  ...
----------------------------------------
RESULT: PASSED - all 22 test(s) passed.
----------------------------------------
```

If something fails:

```
  FAIL  tests/test_food_chain.py::test_rhs_shape
----------------------------------------
RESULT: FAILED - 1 failed, 21 passed, 0 skipped.
----------------------------------------
```

### 4. Test layout

| File | What it tests |
|------|----------------|
| `tests/test_reservoirkit.py` | Core ESN, reservoir, readout, metrics |
| `tests/test_food_chain.py` | Food chain system (Hastings–Powell / McCann–Yodzis) |
| `tests/test_ikeda.py` | Ikeda map and Kuramoto–Sivashinsky simulators |
| `tests/test_parameter_aware_rc.py` | `ParameterAwareRC` fit, predict, scan, ensemble |
| `tests/test_hyperparameter_tuning.py` | Hyperparameter search / fine-tuning (`optimize_hyperparameters`) |

### 5. Troubleshooting

| Problem | Fix |
|---------|-----|
| `ModuleNotFoundError: No module named 'rc_predication'` | Run `pip install -e ".[dev]"` from repo root |
| Ran `python tests/test_food_chain.py` and nothing useful happened | Use `pytest tests/test_food_chain.py` instead |
| `pytest: command not found` | Use `python -m pytest` |

```bash
python -m pytest
```

## Examples

```bash
python examples/lorenz_prediction.py
python examples/food_chain_simulation.py
python examples/ikeda_prediction.py
python examples/food_chain_prediction.py
```

---

## References

1. Kong, L.-W., Fan, H.-W., Grebogi, C., & Lai, Y.-C. (2021). Machine learning prediction of critical transition and system collapse. *Phys. Rev. Research*, 3, 013090. [doi:10.1103/PhysRevResearch.3.013090](https://doi.org/10.1103/PhysRevResearch.3.013090)
2. Lai, Y.-C., Kong, L.-W., Fan, H.-W., & Grebogi, C. (2024). Adaptable reservoir computing. *Chaos*, 34, 120401. [doi:10.1063/5.0200898](https://doi.org/10.1063/5.0200898)
3. Jaeger, H. (2001). The "echo state" approach to analysing and training recurrent neural networks. GMD Report 148.

---

## License

MIT
