Skip to main content

A Python package for solving Markov Decision Processes with Active Inference

Project description

A Python package for simulating Active Inference agents in Markov Decision Process environments. Please see our companion paper, published in the Journal of Open Source Software: "pymdp: A Python library for active inference in discrete state spaces" for an overview of the package and its motivation. For a more in-depth, tutorial-style introduction to the package and a mathematical overview of active inference in Markov Decision Processes, see the longer arxiv version of the paper.

Citing pymdp

If you use pymdp in your work or research, please cite:

@article{Heins2022,
  doi = {10.21105/joss.04098},
  url = {https://doi.org/10.21105/joss.04098},
  year = {2022},
  publisher = {The Open Journal},
  volume = {7},
  number = {73},
  pages = {4098},
  author = {Conor Heins and Beren Millidge and Daphne Demekas and Brennan Klein and Karl Friston and Iain D. Couzin and Alexander Tschantz},
  title = {pymdp: A Python library for active inference in discrete state spaces},
  journal = {Journal of Open Source Software}
}

This package is hosted on the infer-actively GitHub organization, which was built with the intention of hosting open-source active inference and free-energy-principle related software.

Most of the low-level mathematical operations are NumPy ports of their equivalent functions from the SPM implementation in MATLAB. We have benchmarked and validated most of these functions against their SPM counterparts.

Status

status PyPI version Documentation Status DOI

pymdp in action

Here's a visualization of pymdp agents in action. One of the defining features of active inference agents is the drive to maximize "epistemic value" (i.e. curiosity). Equipped with such a drive in environments with uncertain yet disclosable hidden structure, active inference can ultimately allow agents to simultaneously learn about the environment as well as maximize reward.

The simulation below (see associated JAX notebook here) demonstrates what might be called "epistemic chaining," where an agent (here, analogized to a mouse seeking food) forages for a chain of cues, each of which discloses the location of the subsequent cue in the chain. The final cue (here, "Cue 2") reveals the location a hidden reward. This is similar in spirit to "behavior chaining" used in operant conditioning, except that here, each successive action in the behavioral sequence doesn't need to be learned through instrumental conditioning. Rather, active inference agents will naturally forage the sequence of cues based on an intrinsic desire to disclose information. This ultimately leads the agent to the hidden reward source in the fewest number of moves as possible.

You can run the code behind simulating tasks like this one and others in the Examples section of the official documentation. The GIF generation script used for these animations is available here.


Cue 2 in Location 1, Reward on Top


Cue 2 in Location 3, Reward on Bottom

Quick-start: Installation and Usage

We recommend installing pymdp using uv, with an explicit virtual environment:

uv venv .venv
source .venv/bin/activate
uv pip install inferactively-pymdp

If you prefer pip, use:

pip install inferactively-pymdp

If uv sync --group test or uv sync --extra nb fails while building pygraphviz, install Graphviz first and then retry. On macOS, install graphviz with Homebrew. On Ubuntu/Debian, install graphviz libgraphviz-dev pkg-config build-essential python3-dev (or the version-matched python3.x-dev package if needed). The full troubleshooting notes live in docs-mkdocs/getting-started/installation.md.

Once in Python, you can then directly import pymdp, its sub-packages, and functions.

from jax import numpy as jnp, random as jr
from pymdp import utils
from pymdp.agent import Agent

key = jr.PRNGKey(0)
keys = jr.split(key, 3)

num_obs = [3, 5]
num_states = [3, 2]
num_controls = [3, 1]

A = utils.random_A_array(keys[0], num_obs, num_states)
B = utils.random_B_array(keys[1], num_states, num_controls)
C = utils.list_array_uniform([[no] for no in num_obs])

agent = Agent(A=A, B=B, C=C, batch_size=1)
observation = [jnp.array([1]), jnp.array([4])]

qs, info = agent.infer_states(observation, empirical_prior=agent.D, return_info=True)
# Optional diagnostic: current variational free energy for each batch element.
vfe = info["vfe"]
q_pi, neg_efe = agent.infer_policies(qs)

action_keys = jr.split(keys[2], agent.batch_size + 1)
action = agent.sample_action(q_pi, rng_key=action_keys[1:])

Getting started / introductory material

We recommend starting with the JAX-first official documentation for the repository, which provides practical guides, curated notebooks, and generated API references.

For new users to pymdp, we specifically recommend stepping through following three Jupyter notebooks (can also be used on Google Colab):

We also have (and are continuing to build) a series of notebooks that walk through active inference agents performing different types of tasks in the Notebook Gallery.

Contributing

This package is under active development. If you would like to contribute, please refer to CONTRIBUTING.md.

Recommended local setup:

cd <path_to_repo_fork>
uv venv .venv
source .venv/bin/activate
uv sync --group test

Recommended contributor hooks:

uv sync --group dev
uv run --group dev pre-commit install

Useful variants:

# tests + contributor hooks
uv sync --group test --group dev

# docs work
uv sync --group test --extra docs

# notebook/media extras
uv sync --group test --extra nb

# model fitting extras
uv sync --group test --extra modelfit

Run tests:

pytest test

Build docs locally:

./scripts/docs_build.sh

Contributors

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inferactively_pymdp-1.0.1.tar.gz (701.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inferactively_pymdp-1.0.1-py3-none-any.whl (636.6 kB view details)

Uploaded Python 3

File details

Details for the file inferactively_pymdp-1.0.1.tar.gz.

File metadata

  • Download URL: inferactively_pymdp-1.0.1.tar.gz
  • Upload date:
  • Size: 701.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for inferactively_pymdp-1.0.1.tar.gz
Algorithm Hash digest
SHA256 ff1570f4b312f034adc239f9f73755c3219d76a414632592d813fd580778a5b6
MD5 0fd2d220d97d4cf9561bb11b9e0c00c9
BLAKE2b-256 b08bb76e545698e08e2d3bac8ec38c7075656359dad1139f5f03c0c3074c5799

See more details on using hashes here.

Provenance

The following attestation bundles were made for inferactively_pymdp-1.0.1.tar.gz:

Publisher: release-please.yml on infer-actively/pymdp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file inferactively_pymdp-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for inferactively_pymdp-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 86d55f96982be8cdeca9ad010eeb174f17c610ca77ef548c42a2b898a9b572a8
MD5 0a9323dcfd876a75c25908c640fcbcf5
BLAKE2b-256 43144bb966ea73c696e66cbec9746cb99ad575da4d0bf93d41530bbad6e4bf95

See more details on using hashes here.

Provenance

The following attestation bundles were made for inferactively_pymdp-1.0.1-py3-none-any.whl:

Publisher: release-please.yml on infer-actively/pymdp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page