Skip to content

Architecture

Yoav Grimland edited this page May 4, 2025 · 7 revisions

Note

This page is highly inspired by matklad's excellent blog post ARCHITECTURE.md

This page summarizes the general architecture of PDDLSIM. If you are looking for information on the actual protocol PDDLSIM uses for remote simulation and client-server communication, see RSP Latest Specification.

Bird's eye view

At a very high level, PDDLSIM allows for simulating the actions of an agent in a PDDL problem, such that there is strong separation between the agent and the simulator.

To be more specific, PDDLSIM implements RSP-protocol-compliant server and client communication, provides an abstraction over these, and supporting code for creating such clients and servers, in the form of a PDDL parser and AST, PDDL simulation code, etc.

There are three primary use cases for PDDLSIM:

  1. Constructing a simulation server agents can interact with remotely (pddlsim.remote.server)
  2. Constructing an agent that can interact with simulations remotely (pddlsim.remote.client)
  3. Locally simulating an agent, combining use cases 1 and 2 (pddlsim.remote.local)

For a server, PDDLSIM needs to know how to host it (what host and port), and what problem to simulate (PDDL domain-problem pair). For an agent, PDDLSIM needs to know what the agent needs to do when it first connects to a simulation (setup), and after that, have a way to invoke the agent and ask it to perform an action in the simulation's current state, progressing it forward.

Naturally, local simulation requires both of these (excluding hosting information).

Entry points

  • For the server, it is pddlsim.remote.server._server_constructor. This setups a callable that is invoked on connection to the server.
  • For the client, it is pddlsim.remote.client.act_in_simulation. Most of the logic is in SimulationClient though.
  • For parsing, the entry points are pddlsim.parser.parse_domain and pddlsim.parser.parse_problem. These then invoke the Lark-based parser.

Code Map

This section talks about important directories, modules, and data structures, as well as where certain important parts of PDDLSIM are. Keep an eye out for "Architectural invariants", especially because these are generally expressed as the absence of something.

src/pddlsim/

Root of PDDLSIM's actual code.

tests/

Contains all of PDDLSIM's tests, divided into unit tests, integration tests, and benchmarks. Tests not in this folder aren't run.

src/pddlsim/remote/

All of the code directly related to implementing the RSP protocol, as well as (de)serialization for RSP messages. Serialization for PDDL domains and problems is not implemented here.

Note

Architectural invariant: All public APIs in remote must not expose the fact that PDDLSIM implements the RSP protocol. This is an implementation detail.

src/pddlsim/remote/_message.py

Definitions for every single kind of message payload in RSP, as well as some special constructors for some needs (e.g., type mismatch constructor for Error).

src/pddlsim/remote/client.py

Implementation of an RSP client via SimulationClient.

src/pddlsim/remote/server.py

Implementation of an RSP server.

Note

Architectural invariant: The RSP server has no direct state, and instead takes its state via parameters for different request handlers.

src/pddlsim/_serde.py

(De)serialization primitives, mainly used for RSP implementation.

Note

Architectural invariant: Each implementation of Serdeable's validation is only responsible for validation of data that doesn't implement Serdeable. Types that do should be stored as Any, and on create, deserialized, activating their internal validation.

src/pddlsim/ast.py and src/pddlsim/parser.py

ast.py is responsible for defining a PDDL (with some extensions) AST, as well as code for validating a PDDL AST is well formed. parser.py is a parser for constructing such ASTs.

Note

Architectural invariant: Before validation occurs, some AST constructors will additionally make sure their inputs contain no duplicates, and error otherwise. The actual AST objects, by construction, should not have duplicates (e.g., using set instead of list).

Note

Architectural invariant: Only AST types that directly appear in validation errors should subclass Locationed.

src/pddlsim/asp.py

Code for constructing an ASP program to find groundings of a PDDL action definition, to be run by Clingo.

src/pddlsim/state.py and src/pddlsim/simulation.py

Implementation of a PDDL simulator.

Error handling

The main thing to know in regards to error handling, is that the RSP client and RSP server respectively, must never error out due to an issue with the communicated values, or behavior, of the other side. Simulation may/should terminate, but not with an exception being raised. On the other hand, if the client/server are responsible for the error, they mustn't suppress it.

Clone this wiki locally