Overview of POMDPTools
masterPOMDPs.jl ecosystem. It provides essential utility functions and tools designed to work seamlessly with POMDP models and solvers defined within the broader POMDPs.jl framework.repository·master·Indexed 21 days ago
https://github.com/juliapomdp/pomdps.jlA standardized programming interface for working with Markov Decision Processes (MDPs) and Partially Observable Markov Decision Processes (POMDPs) in Julia. It provides a core architecture for expressing problems, developing solvers, and running simulations. The ecosystem includes POMDPTools for utility functions, QuickPOMDPs for rapid problem definition, and various solvers such as QMDP, SARSOP, and POMCPOW, as well as integrations with Reinforcement Learning via CommonRLInterface.jl.
POMDPs.jl ecosystem. It provides essential utility functions and tools designed to work seamlessly with POMDP models and solvers defined within the broader POMDPs.jl framework.POMDPs.jl provides a core interface for Markov decision processes (MDPs) and partially observable Markov decision processes (POMDPs). It is designed for:
Key ecosystem components:
Integrations:
quickpomdps or pyjulia to define/solve problems via Python.POMDPTools provides two-way integration with CommonRLInterface.jl and the JuliaReinforcementLearning ecosystem.The POMDPs.jl ecosystem consists of several specialized packages that implement the core interface. Depending on your needs, you can choose from tools for belief filtering, pre-implemented models, MDP/POMDP solvers, or Reinforcement Learning algorithms.
Used for implementing commonly-used components like filters:
POMDPTools: Core interface components.ParticleFilters: Particle filter implementations.GaussianFilters: Gaussian filter implementations.Commonly used POMDP models implemented via the interface:
POMDPModels, LaserTag, RockSample, TagPOMDPProblem, DroneSurveillance, ContinuumWorld, VDPTag2, RoombaPOMDPs.DiscreteValueIteration: Offline, discrete states/actions (High reliability).LocalApproximationValueIteration: Offline, continuous states, discrete actions.GlobalApproximationValueIteration: Offline, continuous states, discrete actions.MCTS: Online, continuous states/actions (Monte Carlo Tree Search).QMDP: Offline, discrete (Suboptimal).AdaOPS: Online, continuous states/observations.ARDESPOT: Online, continuous states.BasicPOMCP: Online, continuous states.CompressedBeliefMDPs: Offline, continuous states/actions/observations.NativeSARSOP: Offline, discrete.SARSOP: Offline, discrete.POMCPOW: Online, continuous states/actions.ParticleFilterTrees: Online, continuous states/actions.TabularTDLearning: Discrete states/actions.DeepQLearning: Continuous states (uses observations as input).Crux: Continuous states and actions.The JuliaPOMDP ecosystem is split into specialized packages to separate the core interface from implementations:
The distinction between these functions depends on whether you are implementing a problem (the model) or a solver/simulator.
transition: Implement this to define the state transition distribution. You can provide an explicit distribution or use an ImplicitDistribution if you only have a sampler.gen: Implement this only if your simulator outputs multiple values (next state, observation, and reward) simultaneously (e.g., when rewards are tied to the movement between states).@gen: Do not implement or modify this. It is a tool used by solvers and simulators.@gen: Call this to sample the next state, observation, and/or reward. It automatically orchestrates calls to rand, transition, observation, reward, and gen without overhead.transition: Call this only when you need the explicit transition probability distribution.gen: Do not call this directly. It is intended for problem implementers to use when defining joint distributions.A distribution object represents a probability distribution used within a POMDP (e.g., for transition or observation models). To ensure compatibility with solvers, your distribution object should implement the following functions:
rand([rng,] d): Samples from the distribution. Note: It is highly recommended to implement Base.rand(rng::AbstractRNG, s::Random.SamplerTrivial{<:YourDistribution}) to support both rand(d) and rand(rng, d) via the standard Julia rand interface.support(d): Returns the set of values for which the distribution is defined.pdf(d, x): Returns the probability density/mass function at x.mode(d): Returns the mode of the distribution.mean(d): Returns the mean of the distribution.For pre-made distributions, you can use Distributions.jl or POMDPTools.
The standard workflow for using POMDPs.jl follows three sequential steps:
Most examples in the documentation are designed to be executed in this order. For instance, simulation examples typically assume a POMDP has already been defined and a policy has been computed using a solver.
A POMDP simulation typically requires a pomdp model and a policy. Other inputs are optional and should be inferred using standard POMDPs.jl functions if not provided:
| Input | Type | Default/Inference Logic |
|---|---|---|
pomdp | POMDP | Required |
policy | Policy | Required |
up | Updater | up = updater(policy) |
b0 | Initial Belief | b0 = initialstate(pomdp) |
s | Initial State | s = rand(initialstate(pomdp)) |
To implement a new solver, you must provide four distinct components that work together to bridge the gap between problem definition and action selection:
Solver that stores the solver's configuration parameters and options.Policy that holds the data/structures required to select actions (e.g., a value function for offline solvers or a search tree for online solvers).solve method: A function with the signature solve(solver, problem) that performs the offline computation and returns the Policy object.action method: A function with the signature action(policy, state_or_belief) that returns an action based on the current state or belief.Tip: You can often reuse existing Policy types from the POMDPTools package to satisfy requirements 2 and 4, allowing you to focus on the solve logic.
# Conceptual structure of a solver
# 1. Solver type (configuration)
# 2. Policy type (data for action selection)
# 3. solve(solver, problem) -> policy (offline work)
# 4. action(policy, state_or_belief) -> action (online work)Decision-making in POMDPs.jl is divided into offline and online components:
An agent uses a Policy (a subtype of the Policy abstract type) to make decisions during execution. The core method is action(policy, belief), which maps a belief to an action.
action.action performs minimal computation.A Solver (a subtype of the Solver abstract type) performs the heavy lifting of finding a policy. The core method is solve(solver, problem), which carries out the offline optimization or search.
POMDPTools provides interface extensions that act as shortcuts for common tasks. While these have default implementations based on the core POMDPs.jl interface, you should use them whenever possible because they allow for optimized implementations if available.
Key extensions include:
weighted_iterator to iterate through value => probability pairs of a distribution. This is more efficient than looking up probability mass for every value when the distribution support is large.obs_weight to get the relative likelihood of an observation. This is useful for algorithms like particle filtering where you need the likelihood without implementing a full custom observation distribution.POMDPs.jl does not guarantee that spaces are ordered consistently with their index function, use ordered_actions, ordered_states, or ordered_observations to get lists that are guaranteed to match the indexing order.In POMDPs.jl, states, actions, and observations can be any Julia object (integers, strings, vectors, etc.).
Int, Float64, or StaticArrays) for states, actions, and observations. They are often used as dictionary keys or in histories. If you must use mutable objects, ensure hash and == are correctly implemented (e.g., using AutoHashEquals.jl).states, actions, or observations keyword arguments with a Vector. However, for continuous or hybrid spaces, you often only need to specify the type using statetype or obstype (e.g., obstype = Float64). Many solvers do not require an explicit enumeration of the space.If the available actions depend on the current state (MDP) or belief (POMDP), pass a function to the actions argument instead of a vector.
For MDPs (state-dependent):
actions = function (s = nothing)
if s == 1
return [1]
else
return [1,2,3]
end
endFor POMDPs (belief-dependent):
actions = function (b)
if pdf(b, 1) > 0.0
return [1,2,3]
else
return [2,3]
end
end