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 or contributing fixes and features.
Installation
RisKit requires Python 3.13 or higher. Install the riskit package with pip:
pip install riskit
Or, if you want GPU acceleration with JAX, you can instead run:
pip install riskit[accelerated]
You can check out the full list of optional dependencies below.
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:
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:
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?numtypesis 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:
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:
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 and 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.
Developer Documentation
To build the Typst-based documentation, install the custom Typst packages locally:
typi --project-directory=documents
typi is available after you've set up the project environment with uv sync.
Contributing
See CONTRIBUTING.md.
License
MIT, see LICENSE.
Release files for riskit 1.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| riskit-1.0.3.tar.gz | 25.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| riskit-1.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.7 kB
Release files / riskit-1.0.3.tar.gz
| Download URL | riskit-1.0.3.tar.gz |
|---|---|
| Size | 25.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
163adc89c70e7b759fabd76c8d555d8d9cfa01cca5b17eaf52172e1fd00dd6bc
|
|
BLAKE2b-256 checksum How to use checksums |
5fc70a270246de96ec703e14e2b0a0ecb3ead3461c25b5e0e8b3a73fd86d9fbe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / riskit-1.0.3-py3-none-any.whl
| Download URL | riskit-1.0.3-py3-none-any.whl |
|---|---|
| Size | 40.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
967d693afc82c7e0524b69f4c817832388d495acaab9611483e96b9bbd65d84d
|
|
BLAKE2b-256 checksum How to use checksums |
959db967235fa1d4c7c3898dcb0aae49da275f03100d91759840f9fd7d06d535
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|