Metadata-Version: 2.4
Name: riskit
Version: 1.0.2
Summary: A library providing implementations of various risk metrics for risk-aware trajectory planning.
Author-email: Zurab Mujirishvili <zurab.mu@gmail.com>
License-File: LICENSE
Keywords: autonomous systems,risk metrics,robotics,safety,trajectory planning,uncertainty quantification
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.13
Requires-Dist: jaxtyping>=0.3.6
Requires-Dist: lazy-loader>=0.5
Requires-Dist: numpy>=2.2
Provides-Extra: accelerated
Requires-Dist: jax>=0.9.0; extra == 'accelerated'
Provides-Extra: test
Requires-Dist: anyio>=4.13.0; extra == 'test'
Requires-Dist: numtypes>=0.5.1; extra == 'test'
Requires-Dist: pyneedy>=1.4.0; extra == 'test'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'test'
Requires-Dist: pytest>=9.0.3; extra == 'test'
Requires-Dist: scipy>=1.17.1; extra == 'test'
Provides-Extra: type-checking
Requires-Dist: beartype>=0.22.9; extra == 'type-checking'
Provides-Extra: visualization
Requires-Dist: anyio>=4.13.0; extra == 'visualization'
Requires-Dist: kaleido>=1.3.0; extra == 'visualization'
Requires-Dist: plotly>=6.7.0; extra == 'visualization'
Requires-Dist: rich>=15.0.0; extra == 'visualization'
Requires-Dist: scipy>=1.17.1; extra == 'visualization'
Description-Content-Type: text/markdown

[![CI](https://gitlab.com/risk-metrics/riskit/badges/main/pipeline.svg)](https://gitlab.com/risk-metrics/riskit/-/pipelines) [![Coverage](https://codecov.io/gl/risk-metrics/riskit/graph/badge.svg)](https://codecov.io/gl/risk-metrics/riskit) [![PyPI](https://img.shields.io/pypi/v/riskit)](https://pypi.org/project/riskit/) [![Python](https://img.shields.io/pypi/pyversions/riskit)](https://pypi.org/project/riskit/) [![License](https://img.shields.io/pypi/l/riskit)](https://gitlab.com/risk-metrics/riskit/-/blob/main/LICENSE)

# RisKit: Risk Metrics for Risk-Aware Planning

RisKit is a Python library for computing risk metrics of arbitrary uncertain variables. It was designed to be used for risk-aware trajectory optimization, however, the API is flexible and can be used for (probably) anything else. It currently supports **NumPy** and **JAX** (optional) backends, but can easily be extended to support other backends in the future.

> RisKit is being actively developed. Some features may be missing and some of the API might change. You can help by [reporting issues](https://gitlab.com/risk-metrics/riskit/-/issues) or contributing fixes and features.

## Installation

RisKit requires Python 3.13 or higher. Install the `riskit` package with `pip`:

```bash
pip install riskit
```

Or, if you want GPU acceleration with JAX, you can instead run:

```bash
pip install riskit[accelerated]
```

You can check out the full list of optional dependencies [below](#optional-dependencies).

## Quick Start

### Defining Risk Metrics

When measuring risk for a typical trajectory optimization use case, some physical quantity is first modeled with a simple distribution. Then, the distribution is transformed to represent some meaningful quantity for which the risk is computed. For example, we can choose to model the location of an obstacle with a Gaussian. Then, to measure the risk of collision based on the distance between our system and the obstacle, we can define a transform that computes this distance.

For this reason, RisKit splits the definition of the uncertainty distribution, for which risk metrics are computed, into two parts: the **uncertain variables** and the **cost function** (an arbitrary transform applied to the uncertain variables). Let's start with the **uncertain variables**.

### 1D Collision Avoidance

Let's assume we have an obstacle at an uncertain location in a one-dimensional space. The obstacle moves completely unpredictably, but we know it should roughly stay around `0.0`, so we model it as a Gaussian distribution, like this:

```python
from numtypes import array
from riskit import distribution

uncertainties = distribution.numpy.gaussian(
    mean=array([[0.0], [0.0], [0.0], [0.0]], shape=(T := 4, V := 1)),
    covariance=array([[[1.0]], [[1.0]], [[1.0]], [[1.0]]], shape=(T, V, V)),
    seed=42,
)
```

Our system plans to execute a trajectory consisting of `T` time steps. The planned trajectory looks like this:

```python
from riskit import NumPyInputAndState

trajectories = NumPyInputAndState(
    # Input is just velocity.
    u=array([[[1.0]], [[1.0]], [[1.0]], [[1.0]]], shape=(T, D_u := 1, M := 1)),
    # State is just the 1D position.
    x=array([[[-5.0]], [[-4.0]], [[-3.0]], [[-2.0]]], shape=(T, D_x := 1, M)),
)
```

> **What's `numtypes`?** `numtypes` is a tiny wrapper around NumPy that provides utilities for array shape-checking. In this case, we just use it to make sure we don't mess up the square braces. You can just use regular NumPy arrays, if you prefer.

To evaluate the risk the system would take by executing this trajectory, we need to also define a cost function that computes the proximity to the obstacle. We can use a hinge loss for simplicity:

```
h(x, ξ) = max(0, d₀ − ‖x − ξ‖)
```

`‖x − ξ‖` is the distance between a planned position `x` and the obstacle position `ξ`, and `d₀` is just some threshold distance.

Here's the `riskit` implementation:

```python
import numpy as np
from riskit import NumPyCosts, NumPyUncertaintySamples

D_0 = 2


def proximity(
    *,
    trajectories: NumPyInputAndState,
    uncertainties: NumPyUncertaintySamples,
) -> NumPyCosts:
    x = trajectories.x
    xi = uncertainties

    distance = np.abs(x[:, 0, :, None] - xi[:, 0, None, :])
    return np.maximum(0, D_0 - distance)
```

Finally, we can compute a risk metric, e.g. the Conditional Value at Risk (CVaR), like so:

```python
from riskit import risk

metric = risk.cvar_of(proximity, alpha=0.9)

results = metric.compute(trajectories=trajectories, uncertainties=uncertainties)
```

If your cost function works with JAX and returns a JAX array instead, use the corresponding type annotation (e.g. `JaxCosts`) and the JAX backend will be inferred automatically.

RisKit provides some built-in classes for trajectories and uncertainties, but you can use your own implementations, as long as they are compatible with the [TrajectoriesProvider](https://risk-metrics.gitlab.io/riskit/api/types/#trajectoriesprovider) and [Uncertainties](https://risk-metrics.gitlab.io/riskit/api/types/#uncertainties) interfaces.

## Risk Metrics

Here's a list of all risk metrics that are currently supported by `riskit`:

| Metric          | Factory                               | Description                                                                     |
| --------------- | ------------------------------------- | ------------------------------------------------------------------------------- |
| Expected Value  | `risk.expected_value_of(f)`           | Mean cost across samples                                                        |
| Mean-Variance   | `risk.mean_variance_of(f, gamma=...)` | Mean + γ · Variance tradeoff                                                    |
| Value at Risk   | `risk.var_of(f, alpha=...)`           | α-quantile of the cost distribution                                             |
| Conditional VaR | `risk.cvar_of(f, alpha=...)`          | Expected cost in the worst (1-α)-fraction                                       |
| Entropic Risk   | `risk.entropic_risk_of(f, theta=...)` | A risk measure based on the moment-generating function of the cost distribution |

## Optional Dependencies

| Dependency Group | What does it do?                                                                                                  |
| ---------------- | ----------------------------------------------------------------------------------------------------------------- |
| accelerated      | Provides the JAX backend for (GPU) accelerated computations                                                       |
| type-checking    | Uses `beartype` for runtime type checking (including array shapes)                                                |
| visualization    | Includes additional components for visualizing uncertain variable distributions, computed risk, convergence, etc. |

## Documentation

You can check out the docs [here](https://risk-metrics.gitlab.io/riskit/).

## Developer Documentation

To build the Typst-based documentation, install the custom Typst packages locally:

```bash
typi --project-directory=documents
```

`typi` is available after you've set up the project environment with `uv sync`.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

MIT, see [LICENSE](LICENSE).
