Skip to main content

Approximate Numerics in Applied Transition Environments

ANIATE

pypi python tests website guide licence


Fibonacci squares 1, 1, 2, 3, 5, 8 and 13 tiling a 21 by 13 rectangle, with the golden spiral drawn through them

Reference implementation of aniate, a Python library for finite decision problems: Markov decision processes and problems whose reward depends on the history of the episode.

A problem is specified by its states, actions, transition probabilities, rewards and discount factor. The specification is validated at construction, and a model is rejected when a probability row does not sum to one, when a terminal state continues to move or to accrue reward, or when its value is unbounded. The library computes optimal policies together with their exact values, simulates episodes in batches, and compares any external simulator with the model through per-transition chi-square tests and the value martingale M_t = G_<t + γ^t V(s_t). History-dependent objectives are expressed with event labels and a Mealy automaton, and the exact product model is solved. Every operation writes one structured log line, and every figure is saved as a PDF with embedded Computer Modern fonts. The library can be run in a web browser, without installation, at aniate.com/playground.

Installation

pip install aniate            # numpy and scipy
pip install 'aniate[vis]'     # adds matplotlib, required for plots
pip install 'aniate[gym]'     # adds gymnasium, required for aniate.gym

Verifying the installation

from aniate import ant
ant()

ant() prints the Fibonacci drawing, the installed version of Python and of each dependency, and the result of a self-test that builds, solves, simulates and checks a small model. It returns True when aniate is working. The same report is printed by python -m aniate.

aniate 2.1.0   Approximate Numerics in Applied Transition Environments

python      3.12.4      ok             required, 3.10 or later
numpy       2.1.0       ok             required, 1.24 or later
scipy       1.14.1      ok             required, 1.12 or later
matplotlib  -           not installed  optional, for plots in aniate.vis
pytest      -           not installed  optional, for running the tests
hypothesis  -           not installed  optional, for property-based tests
gymnasium   -           not installed  optional, for the Gymnasium adapter in aniate.gym

self-test   model valid | solved, value 3.20876 | 2,000 episodes simulated | check passed | 13 ms
            plots unavailable; install them with: pip install 'aniate[vis]'

aniate is working.

Quick start

import aniate as an
from aniate import vis

m = an.from_functions(
    states=range(5), actions=["left", "right"],
    transition=lambda s, a: {max(s - 1, 0): 1.0} if a == "left" else {min(s + 1, 4): 0.8, s: 0.2},
    reward=lambda s, a, s_next: 10.0 if s_next == 4 else -1.0,
    gamma=0.9, terminal=[4], initial=0,
)

sol = m.solve()                                   # optimal policy, its exact value, an error bound
runs = an.simulate(m, sol, episodes=10_000)       # 10,000 episodes, run in parallel
report = an.check(m, policy=sol)                  # compares simulated behaviour with the model
vis.save(vis.overview(runs), "overview.pdf")      # four standard plots in one PDF
m.describe()                                      # the model as a JSON-compatible dict

Each operation writes one line to standard error:

aniate | model    | 5 states | 2 actions | gamma 0.9 | horizon inf | 14 transitions | valid
aniate | solve    | policy_iteration | 4 iterations | 2.8 ms | start value 3.20876 | bound 8.9e-15
aniate | simulate | 10,000 episodes | 49,768 steps | 4 ms | mean return 3.23989 +/- 0.014 | 10,000 terminated | 0 truncated
aniate | check    | PASSED | 300 episodes | 1,505 steps | 4 pairs tested | return 3.1863 vs model 3.2088
aniate | vis      | saved overview.pdf

Validation

Construction fails, and the error names each offending state and action, if any of the following hold:

code condition
row_sum a row of transition probabilities does not sum to 1
dead_end a state-action pair has no successor
terminal_not_absorbing a terminal state moves to another state or pays a reward
unbounded_value the discount factor is 1 and no terminal state is reachable

an.check(model, env=simulator) runs episodes through an external simulator and reports impossible_transition, transition_frequency, reward_mismatch, termination_mismatch and return_mismatch. These properties are verified by runtime checks and by the test suite; they are not formally proved.

History-dependent rewards

from aniate import nmdp

world  = an.problems.gridworld(rows=5, cols=5, goals=((0, 4),), start=(4, 0))
labels = nmdp.Labels(world).at("r4c4", "A").at("r0c4", "B")
task   = an.NMDP(world, labels, nmdp.Ordering(["A", "B"], violation_penalty=-1))
policy = task.solve()        # a MemoryPolicy: policy.step(state) returns the next action

nmdp.Ordering, nmdp.Budget and nmdp.Deadline cover common patterns, and nmdp.Mealy expresses any finite-memory rule.

Notebooks

In Jupyter, a model, solution, set of episodes, check report, automaton or non-Markovian task that ends a cell is displayed as a table. A long table is shortened, and the number of omitted rows is stated.

Gymnasium

from aniate import gym

env = gym.make(m)                               # a gymnasium.Env with Discrete spaces
obs, info = env.reset(seed=0)
obs, reward, terminated, truncated, info = env.step(env.action_space.sample())

gym.register("aniate/Corridor-v0", lambda: m)   # gymnasium.make("aniate/Corridor-v0") then builds it

Transitions are sampled from the model with the seeded generator of Gymnasium, so equal seeds give equal episodes, and the environment passes the Gymnasium environment checker. The adapter requires pip install 'aniate[gym]'.

Interface

call purpose
ant() report installed dependencies and run a self-test
an.from_functions(states, actions, transition, reward, gamma, terminal=, initial=) define a model with Python functions
an.Builder(gamma) define a model one transition at a time
an.MDP(P, R, gamma) define a model from matrices
m.solve() optimal policy and exact value
an.evaluate(m, policy) exact value of any policy
an.simulate(m, policy, episodes) batched episodes, returned as Episodes
m.env() a Gym-style environment with reset and step
an.check(m, env=simulator, policy=) statistical comparison of a simulator with the model
an.NMDP(world, labels, automaton) a problem whose reward depends on history
gym.make(m), gym.register(id, model) the model as a Gymnasium environment
vis.overview(runs), vis.graph(m), vis.grid(m, sol) plots; vis.save(fig, "name.pdf") writes a PDF
obj.describe() a JSON-compatible summary of any model, solution, report or set of episodes
an.verbosity("quiet") set the log level

A decision tree for choosing among these calls, the package layout and the conventions for extending the library are given in tree.md.

Worked examples

folder problem result verified by the tests
tests/stsp stochastic travelling salesman with randomly blocked roads the exact solution equals the best of all 24 tours, with expected cost 17.6227
tests/gaussian Gaussian random walk between two absorbing edges the hitting probability is 0.5 by symmetry and 0.956 under drift; Monte Carlo estimates agree
tests/heavy_tail travel time with power-law delays the value equals the closed form, the martingale mean is constant, and an incorrect simulator is detected
pip install -e '.[dev]'
pytest                               # all tests
python tests/stsp/plot.py            # writes route.pdf and overview.pdf into tests/stsp

Importing aniate prints a Fibonacci rectangle to standard error once per process; ANIATE_BANNER=0 disables it.

Citation

@software{murjani2026aniate,
  author  = {Murjani, Kabir},
  title   = {aniate: Approximate Numerics in Applied Transition Environments},
  year    = {2026},
  version = {2.1.0},
  url     = {https://github.com/Kcbir/aniate}
}

Licence

Released under the MIT Licence.

Metadata

Release files for aniate 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aniate 2.1.0
File Size Uploaded Provenance
aniate-2.1.0.tar.gz 85.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for aniate 2.1.0
File Interpreter ABI Platform
aniate-2.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 165.4 kB

Release files / aniate-2.1.0.tar.gz

Download URL aniate-2.1.0.tar.gz
Size 85.4 kB
Tags Source
SHA-256 checksum
How to use checksums
11fb6ab380c6c2613268ff748d1c42da341fe1abdebcb53213827027ca7941b7
BLAKE2b-256 checksum
How to use checksums
56f8507f3f3b7f9e76d8ceb44c6607cc772e6b859d49e0cf7d0940b11a6906da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / aniate-2.1.0-py3-none-any.whl

Download URL aniate-2.1.0-py3-none-any.whl
Size 79.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4223684a3e9e7c17e5d98e72a188e997b9c3e76c516185a05cd71818c78fd0cc
BLAKE2b-256 checksum
How to use checksums
52416cc67b91edc462f77c08cda467ec3b71412c05a7b054dd2a1e76c80e6367
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for aniate 2.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page