A PDDL 2.1 Level 1 (classical + numeric fluents) planning engine and independent plan validator for MoonBit.
$ moon run --target native cmd/moonpddl -- solve \
examples/blocksworld/domain.pddl examples/blocksworld/problem.pddl \
-s astar -H hmax
; moonpddl: solved
; cost = 4
; expanded = 6, generated = 11
; heuristic = hmax, search = astar
(pick-up b)
(stack b c)
(pick-up a)
(stack a b)| 类别 | 支持内容 |
|---|---|
| 需求标记 | :strips、:typing、:negative-preconditions、:disjunctive-preconditions、:equality、:existential-preconditions、:universal-preconditions、:quantified-preconditions、:conditional-effects、:fluents、:adl(域与问题皆可声明),以及 :action-costs |
| 类型 | 多继承类型层次(:types t - (either a b));对象/常量/参数/量词变量均接受 (either t1 t2 ...) 并集语义 |
| 命题公式 | and、or、not、imply、exists、forall、对象相等 =,可任意嵌套 |
| 数值表达式 | 整数与实数字面量、一元负号、+/*(多元)、-(二元/一元)、/、任意参数的函数项,可任意嵌套 |
| 数值比较 | <、<=、=、>、>= 出现在前提、效果条件与目标中 |
| 函数声明 | (:functions ...) 任意 0 元/多元函数,参数带类型,返回类型 number |
| 数值效果 | increase、decrease、assign、scale-up、scale-down 作用于任意函数,右端为完整数值表达式,可与 when/forall 组合(total-cost 除外,见语义约定) |
| 初始状态 | 命题事实 + 任意函数的 (= (f args) value) 赋值,负数与小数均可 |
| 优化目标 | :metric minimize/maximize 作用于完整数值表达式(含 total-cost 的裸写法) |
| 动作代价 | total-cost 累计;代价表达式支持规范允许的静态函数输入,例如 (increase (total-cost) (* (fuel-price) (distance ?a ?b))) |
| 计划文本 | 每行一个动作,括号可省略,大小写不敏感,; 后为注释,; cost = N 支持小数 |
moon add sa2360/pddl# 静态检查与测试(默认 wasm 目标)
moon check
moon test
# 同时验证 native 后端
moon test --target native
# 构建原生 CLI
moon build --target native cmd/moonpddlmoon run --target native cmd/moonpddl -- version
moon run --target native cmd/moonpddl -- check \
examples/blocksworld/domain.pddl examples/blocksworld/problem.pddlmoonpddl solve <domain.pddl> <problem.pddl> [options]
moonpddl validate <domain.pddl> <problem.pddl> <plan.txt> [--json]
moonpddl check <domain.pddl> <problem.pddl> [--json]
moonpddl ground <domain.pddl> <problem.pddl> [--json]
moonpddl version| 选项 | 说明 |
|---|---|
| -s, --search <gbfs\|astar\|wastar> | 搜索策略,默认 gbfs |
| -H, --heuristic <name> | blind、goal-count、hmax、hadd、hff,默认 hff |
| --weight <n> | WA* 权重,默认 5;仅能与 --search wastar 共用 |
| --max-expanded <n> | 扩展状态上限,默认 1,000,000 |
| --json | 输出单行 JSON |
| --out <path> | 将计划写入文件,首行为 ; cost = N |
| -q, --quiet | 不输出求解统计 |
| -h, --help | 显示帮助 |
moon run --target native cmd/moonpddl -- solve \
examples/delivery-numeric/domain.pddl examples/delivery-numeric/problem.pddl \
-s astar -H hmax; moonpddl: solved
; cost = 34
; expanded = 6, generated = 12
; heuristic = hmax, search = astar
(drive t1 a b)
(refuel t1 b)
(drive t1 b c){"status":"solved","cost":34,"steps":3,"expanded":6,"generated":12,
"heuristic":"hmax","search":"astar",
"plan":["(drive t1 a b)","(refuel t1 b)","(drive t1 b c)"]}moon run --target native cmd/moonpddl -- validate \
examples/logistics/domain.pddl examples/logistics/problem.pddl \
examples/logistics/plan.pddl
# plan valid: 9 step(s), cost 9{"valid":true,"steps":9,"executed":9,"cost":9,"declared_cost":9,"issues":[]}moon run --target native cmd/moonpddl -- check \
examples/delivery-numeric/domain.pddl examples/delivery-numeric/problem.pddlmodel ok
domain: delivery-numeric
problem: delivery-1
objects: 4
atoms: 6
fluents: 11
actions: 12
goal disjuncts: 1
initial cost: 0
cost mode: total-costlet domain = @pddl.parse_domain(domain_source)
let problem_ast = @pddl.parse_problem(problem_source)
let problem = @pddl.ground(domain, problem_ast)
let result = @pddl.solve(problem, @pddl.HFF, @pddl.AStar)
let plan_text = result.render_plan(problem)
let report = @pddl.validate_plan(problem, plan_text)
inspect(report.valid, content="true")| API | 说明 |
|---|---|
| parse_domain / parse_problem | 解析 PDDL,失败时抛出带位置的 PddlError |
| ground | 将领域与问题编译为 GroundProblem |
| solve | 按给定启发式与策略搜索,返回 SearchResult |
| heuristic_value | 计算某个状态在指定启发式下的估计值 |
| validate | 一次性完成解析 + 接地 + 验证 |
| validate_plan | 在已有 GroundProblem 上验证计划 |
| ValidationReport::to_json | 将验证结果序列化为 JSON |
| State / apply_action | 位集 + 数值 fluent 状态与动作前向执行,可用于自定义搜索 |
| eval_num_value / num_compare / format_number | 数值表达式求值、带容差比较与规范化输出 |
PDDL 文本
│ lexer.mbt + sexp.mbt
▼
S 表达式(带行列位置)
│ parser.mbt → ast.mbt
▼
Domain / Problem
│ ground.mbt(类型、对象、量词、DNF、条件效果、数值编译、静态代价、剪枝)
▼
GroundProblem(原子表 + fluent 表 + 位集/数组 State + 接地动作)
├── heuristics.mbt(删除松弛:hmax / hadd / hff)
│ └── search.mbt(GBFS / A* / WA*)→ SearchResult → 计划文本
└── validate.mbt(独立重放)→ ValidationReport(文本 / JSON)| 文件 | 职责 |
|---|---|
| lexer.mbt、sexp.mbt | 词法与 S 表达式读取,记录源码位置 |
| parser.mbt、ast.mbt | PDDL 领域/问题解析与 AST(含数值表达式) |
| error.mbt | PddlError、错误分类与位置格式化 |
| ground.mbt | 类型层次、接地、DNF 编译、数值状态与效果、静态代价、可达性剪枝 |
| heuristics.mbt | 删除松弛任务、hmax、hadd、hff、目标计数 |
| search.mbt | 开放表、GBFS/A*/WA*、节点预算、计划重建 |
| validate.mbt | 计划文本解析、独立执行、诊断与 JSON 报告 |
| cmd/moonpddl/ | 原生 CLI |
| 领域 | 规模 | 展示能力 | 计划代价 |
|---|---|---|---|
| blocksworld | 3 个积木 | STRIPS、类型、最优搜索 | 4 |
| gripper | 2 个球、2 个夹爪 | 多类型对象与移动 | 5 |
| logistics | 2 城市、卡车 + 飞机 | 多交通工具、9 步计划 | 9 |
| matchcellar | 2 根火柴、2 个保险丝 | 动作代价与 :metric | 4 |
| delivery-numeric | 3 地点、1 卡车 | 数值 fluent、静态函数代价输入、数值前提与效果 | 34 |
moon run --target native cmd/moonpddl -- validate \
examples/delivery-numeric/domain.pddl examples/delivery-numeric/problem.pddl \
examples/delivery-numeric/plan.pddl
# plan valid: 3 step(s), cost 34moon test # 91 个测试,wasm
moon test --target native # 同一套测试,native
moon test --include-skipped -f "benchmarks:*" # 可选性能基准| 阶段 | 中位耗时 |
|---|---|
| 解析领域 + 问题 | ≈ 108 µs |
| 接地(24 个动作,含剪枝) | ≈ 246 µs |
| GBFS + hff 求解 | ≈ 262 µs |
| 验证 4 步计划 | ≈ 33 µs |
pub(all) struct GroundProblem {
domain_name : String
problem_name : String
objects : Array[TypedName]
atoms : Array[GroundAtom]
funcs : Array[GroundFunc]
actions : Array[GroundAction]
initial : State
initial_cost : Double
goal : Array[Array[CondLit]]
uses_action_costs : Bool
has_metric : Bool
metric_minimize : Bool
} derive(Debug)pub(all) struct SearchResult {
status : SearchStatus
plan : Array[Int]
cost : Double
expanded : Int
generated : Int
} derive(Debug)pub(all) struct ValidationIssue {
kind : ValidationIssueKind
line : Int
step : Int
message : String
} derive(Debug)pub(all) struct ValidationReport {
valid : Bool
steps : Int
executed : Int
cost : Double
declared_cost : Double?
issues : Array[ValidationIssue]
} derive(Debug)fn format_number(value : Double) -> Stringfn solve(problem : GroundProblem, heuristic : HeuristicKind, algorithm : SearchAlgorithm, max_expanded? : Int, max_generated? : Int) -> SearchResultfn validate(domain : Domain, problem : Problem, source : String) -> ValidationReport raise PddlErrorInstall
Download zipA PDDL 2.1 Level 1 (classical + numeric fluents) planning engine and independent plan validator for MoonBit.