Metadata-Version: 2.4
Name: optimal-transport-ica
Version: 0.1.0
Summary: Optimal Transport Independent Component Analysis
Author-email: Ashutosh Jha <ashutoshjha3103@github.to>
Project-URL: Homepage, https://github.com/ashutoshjha3103/ot_ica
Project-URL: Repository, https://github.com/ashutoshjha3103/ot_ica.git
Project-URL: Issues, https://github.com/ashutoshjha3103/ot_ica/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: torch
Requires-Dist: numpy
Requires-Dist: scipy

# ot-ica: Linear Independent Component Analysis via Optimal Transport

[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![PyTorch](https://img.shields.io/badge/PyTorch-1.10+-ee4c2c.svg)](https://pytorch.org/)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

**ot-ica** is a Python library that recovers independent source signals from linear mixtures by maximizing the 1D squared Wasserstein distance ($W_2^2$) between each projected component and a standard Gaussian. 

Unlike classical ICA algorithms (FastICA, JADE, InfoMax) that use proxies (such as kurtosis or parametric approximations) that can fail on heterogeneous source distributions, `ot-ica` computes the **exact** 1D Wasserstein distance via quantile sorting. This provides an assumption-free, exact non-Gaussianity contrast function that is computed efficiently without density estimation or binning.

---

## Key Features

- **Exact Contrast Evaluation**: Bypasses heuristic approximations by utilizing the exact 1D squared Wasserstein distance ($W_2^2$) computed analytically via sorted quantiles.
- **Flexible Optimization Modes**: 
  - *Deflationary*: Extract independent components one by one.
  - *Symmetric*: Solve for all components simultaneously under orthogonal constraints.
- **Diverse Optimizers**: 
  - Riemannian gradient ascent on the Stiefel manifold.
  - Standard Stochastic Gradient Descent (SGD) and L-BFGS.
  - A fast Fixed-Point update rule (OT-Mapping) for extremely quick convergence.
- **Robust Costs**: Supports standard L2 Wasserstein distance and a robust Huber-like `logcosh` Wasserstein cost to handle extreme outliers.
- **Continuous Smoothing (Dithering)**: Inject continuous noise to smooth discrete CDF steps and avoid flat gradients.
- **Fully Vectorized**: Written in PyTorch, supporting GPU acceleration out of the box.

---

## Installation

Install from PyPI:

```bash
pip install ot-ica
```

Or install from source:

```bash
git clone https://github.com/ashutoshjha3103/ot_ica.git
cd ot_ica
pip install .
```

Verify your installation:
```bash
python -c 'from ot_ica import WassersteinICA; print("OK")'
```

---

## Quick Start

Here are three ways to use the `ot_ica` package for source separation:

### 1. Deflationary Optimization (Extracting One Component)

```python
import numpy as np
import torch
from ot_ica import WassersteinICA

# Generate synthetic mixed data
rng = np.random.default_rng(0)
S = rng.laplace(0, 1, size=(3, 2000))          # 3 Laplace sources
A = rng.standard_normal((3, 3))                # Mixing matrix
X = torch.tensor(A @ S, dtype=torch.float32)   # Mixed signals

# Initialize and Whiten
ica = WassersteinICA(X)
ica.whiten()

# Optimize one component using deflationary gradient ascent
w_est, w2_score = ica.optimize_wasserstein2(continuous=True)

print("Estimated unmixing row:", w_est)
print("Wasserstein distance score:", float(w2_score))
```

### 2. Symmetric Optimization (Riemannian SGD on the Stiefel Manifold)

```python
# Solves for all components simultaneously using Stiefel manifold SGD
W_est = ica.optimize_symmetric(n_components=3, optimizer='stiefel', lr=0.5)

# Reconstruct independent sources
S_est = torch.matmul(W_est, ica.X_white)
print("Estimated unmixing matrix W:\n", W_est)
```

### 3. Fast Fixed-Point Optimization (OT-Mapping)

```python
# Runs a fast fixed-point rule by stepping away from the ideal Gaussian target
W_est_fp = ica.optimize_fixed_point(n_components=3, step_size=0.5)

# Reconstruct independent sources
S_est_fp = torch.matmul(W_est_fp, ica.X_white)
print("Fixed-Point unmixing matrix W:\n", W_est_fp)
```

---

## Visualizing the Contrast

### 1. Mixing Two Sources (Central Limit Theorem)
Mixing two independent sources (e.g., Laplace and Uniform) results in a more Gaussian distribution due to the Central Limit Theorem. The 1D squared Wasserstein distance ($W_2^2$) provides the contrast by dipping toward the Gaussian mixture and peaking at the pure, non-Gaussian sources.

<p align="center">
  <img src="https://raw.githubusercontent.com/ashutoshjha3103/ot_ica/main/assets/mixing_clt.gif" width="80%">
</p>

### 2. Contrast Function Race
Comparing how FastICA (logcosh), JADE, InfoMax, and OT-ICA ($W_2^2$) scan a 2D mixture. All four rotate the projection and scan for a non-Gaussianity peak, landing on the independent components with varying sharpness.

<p align="center">
  <img src="https://raw.githubusercontent.com/ashutoshjha3103/ot_ica/main/assets/contrast_race.gif" width="80%">
</p>

---

## Citation

If you use this package or method in your research, please cite our paper:

```bibtex
@misc{jha2026linearindependentcomponentanalysis,
      title={Linear Independent Component Analysis via Optimal Transport}, 
      author={Ashutosh Jha and Michel Besserve and Simon Buchholz},
      year={2026},
      eprint={2607.14081},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2607.14081}, 
}
```

---

## License

This project is licensed under the GNU General Public License v3 (GPLv3) - see the [LICENSE](LICENSE) file for details.
