# Lambda Happy
A high‑performance solver for estimating the $\lambda_{happy}$ factor in sparse linear models (≈99% sparsity) using C++/CUDA and PyTorch.

---

## Installation

```bash
# Core functionality
pip install lambda-happy

# Benchmark GUI (PyQt5)
pip install lambda-happy[benchmark]

# Validation tools (PyQt5 + pandas)
pip install lambda-happy[validation]

# All extras (Benchmark + Validation tools)
pip install lambda-happy[all]
```
## What is lambda happy ?
In sparse regression, $\lambda_{happy}$ balances data fidelity against model sparsity.
Given:

- $X$ ∈ ℝⁿˣᵖ — The feature matrix
- $Z$ ∈ ℝⁿˣᵐ — A random gausian projection matrix
- $Z^{centrer}$ — centrer

$\lambda_{happy}$ is estimated as the 95ᵗʰ percentile of
$ \frac{ \| X^\top Z^{centrer} \|_{\infty} }{ \| Z^{centrer} \|_2 } $

$$
\lambda_{happy} = \text{Quantile}_{0.95} \left( \frac{ \| X^\top Z^{centrer} \|_{\infty} }{ \| Z^{centrer} \|_2 } \right)
$$

which requires:
- p: The number of feature in The feature matrix X  (affects only the matmul)
- n: The number of row in The feature matrix x 
- m: number of projections (larger m ⇒ higher precision, but each step’s cost scales with m)

## Quickstart

```py
import torch
from lambda_happy import LambdaHappy

# Prepare data
X = torch.randn(1000, 5000)
# Initialize solver (auto‐select fastest backend)
solver = LambdaHappy(X, force_fastest=True)

# Single estimate
λ = solver.compute(m=5000)
print(f"λ ≈ {λ:.4f}")

# Multiple runs
λs = solver.compute_many(m=5000, nb_run=50)

# Aggregated (mean)
λ_mean = solver.compute_agg(m=5000, nb_run=50, func=torch.mean)
```

## Performance Trade-Offs

### Projection Dimension (m)
- ↑ **m** → improves $\lambda_{happy}$ precision.
- ↑ **m** → linearly increases compute time (all kernels scale with m).
- Recommended: **m = 10,000** provides good accuracy in most cases.

> ℹ️ Use `float16` on **GPU** only if the input matrix **X** is normalized.  
> Otherwise, $\lambda_{happy}$ estimation may be unstable or inconsistent.



### Sample Dimension (n)
- ↑ **n** → increases cost in all kernels (since $ Z \in \mathbb{R}^{n \times m} $), except for the quantile post-processing step.

### Feature Dimension (p)
- ↑ **p** → only affects the **Xᵀ·Z** matrix multiplication.

---

## Recommended Settings

| Context | Data Type | Notes |
|-|-|-|
| CPU         | `float32`     | Stable, widely supported, and generally the fastest on CPU.          |
| CUDA GPU    | `float16`     | High performance if `X` is normalized; otherwise use `float32`.      |
| Backend     | `"AUTOMATIC"` | Selects the best available implementation based on hardware and dtype. |

## Extras

### Benchmark

The `lambda-happy-benchmark` script measures and compares the performance of LambdaHappy on CPU and GPU.
It offers various benchmarking options and displays live throughput plots.
Example usage:
```sh
lambda-happy-benchmark --benchmark_2D --benchmark_3D --device cuda --dtyoe float16 -n 1000 -p 1000 -m 10000
```
This runs a 2D benchmark using CUDA with specified matrix dimensions and then run a 3D benchmark.
> ℹ️ Note: Not all hyperparameters are used for every plot, but if provided, they will be applied when relevant.

### Validation

The `lambda-happy-validation` script runs tests to validate $\lambda_{happy}$ estimation accuracy.
It generates detailed reports and distribution plots using pandas and PyQt5.

Example usage:
```sh
lambda-happy-validation --distribution_small --device cpu --dtyoe float32 -n 1000 -p 1000
```
This plots small-scale $\lambda_{happy}$ distributions on CPU for the given parameters.


# About This Project
This package is developed as part of the Bachelor’s thesis by Yerly Sevan at HE-Arc, supervised by Cédric Billat.

For questions or contact: xxx@he-arc.ch