| name | add-active-algorithm |
| description | Add a new active learning algorithm to AMLGym. Use when the user wants to integrate an algorithm that interacts with a simulator to collect its own experience. |
Add an Active Algorithm
Create a new active algorithm adapter in amlgym/algorithms/.
Steps
-
Create amlgym/algorithms/$ARGUMENTS.py (class name must match filename, PascalCase, case-insensitive)
-
Inherit from ActiveAlgorithmAdapter and implement learn():
from dataclasses import dataclass
from typing import Tuple
from unified_planning.shortcuts import SequentialSimulator
from amlgym.algorithms.ActiveAlgorithmAdapter import ActiveAlgorithmAdapter
from amlgym.modeling.trajectory import Trajectory
@dataclass
class $ARGUMENTS(ActiveAlgorithmAdapter):
"""Docstring with paper reference and usage example."""
def learn(self,
simulator: SequentialSimulator,
input_domain_path: str,
max_steps: int = 100,
seed: int = 123) -> Tuple[str, Trajectory]:
...
-
Add external dependencies to requirements.txt if needed
-
No registration needed — amlgym/algorithms/__init__.py auto-discovers all algorithm files
Reference implementation
Study amlgym/algorithms/RandomAgent.py for the canonical active adapter pattern:
- Grounding actions via
tarski.LPGroundingStrategy (requires clingo)
- Interacting with the simulator to collect trajectories
- Filtering failed actions (
simulator.apply() returns None for inapplicable actions, but may also raise UPInvalidActionError — always wrap in try/except)
- Building a
Trajectory from collected states and actions
- Optionally delegating to an offline learner (e.g.,
SAM) for model extraction
Key utilities
amlgym/modeling/trajectory.py — Trajectory(states, actions) dataclass with .write() method
amlgym/util/util.py — empty_domain() strips preconditions/effects, fix_domain_format() normalizes hyphens
- Action grounding: use
tarski.LPGroundingStrategy + convert_problem_to_tarski() (see RandomAgent._ground_actions())
Testing
from unified_planning.io import PDDLReader
from unified_planning.shortcuts import SequentialSimulator
from amlgym.algorithms import get_algorithm
from amlgym.benchmarks import get_domain_path, get_problems_path
from amlgym.util.util import empty_domain
from amlgym.metrics import syntactic_precision, syntactic_recall
domain = 'blocksworld'
domain_path = get_domain_path(domain)
input_domain = empty_domain(domain_path)
problem_path = get_problems_path(domain, kind='learning')[0]
problem = PDDLReader().parse_problem(domain_path, problem_path)
simulator = SequentialSimulator(problem=problem)
agent = get_algorithm('$ARGUMENTS')
model, trajectory = agent.learn(simulator, input_domain)
with open('learned.pddl', 'w') as f:
f.write(model)
print("Precision:", syntactic_precision('learned.pddl', domain_path))
print("Recall:", syntactic_recall('learned.pddl', domain_path))