use serde::{Deserialize, Serialize};
pub const PDDL8_MAX_ARITY: usize = 8;
pub const PDDL8_MAX_CONJUNCTS: usize = 8;
pub const PDDL8_MAX_PARAMS: usize = 8;
pub const PDDL8_MAX_PLAN_DEPTH: usize = 64;
pub const PDDL8_MAX_GROUND: usize = 4096;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Pddl8Atom {
pub pred: String,
pub args: Vec<String>,
}
impl Pddl8Atom {
pub fn is_variable(arg: &str) -> bool {
arg.starts_with('?')
}
pub fn arity(&self) -> usize {
self.args.len()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Precondition {
pub predicate_id: String,
pub params_hash: Option<[u8; 32]>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8ActionSchema {
pub name: String,
pub params: Vec<String>,
pub preconditions: Vec<Pddl8Atom>,
pub add_effects: Vec<Pddl8Atom>,
pub del_effects: Vec<Pddl8Atom>,
#[serde(default)]
pub typed_params: Vec<(String, String)>, #[serde(default)]
pub condition: Option<PddlCondition>, #[serde(default)]
pub effects: Vec<PddlEffect>, #[serde(default)]
pub numeric_effects: Vec<NumericEffect>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8Domain {
pub name: String,
pub predicates: Vec<(String, u8)>,
pub actions: Vec<Pddl8ActionSchema>,
#[serde(default)]
pub types: Vec<PddlType>,
#[serde(default)]
pub functions: Vec<PddlFunction>,
#[serde(default)]
pub durative_actions: Vec<DurativeAction>,
#[serde(default)]
pub derived: Vec<DerivedPredicate>,
#[serde(default)]
pub constraints: Vec<PddlConstraint>,
#[serde(default)]
pub processes: Vec<PddlProcess>,
#[serde(default)]
pub events: Vec<PddlEvent>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8Problem {
pub name: String,
pub domain: String,
pub objects: Vec<String>,
pub init: Vec<Pddl8Atom>,
pub goal: Vec<Pddl8Atom>,
#[serde(default)]
pub object_types: Vec<(String, String)>,
#[serde(default)]
pub fn_values: Vec<(PddlFunction, f64)>,
#[serde(default)]
pub timed_inits: Vec<TimedLiteral>,
#[serde(default)]
pub preferences: Vec<PddlPreference>,
#[serde(default)]
pub metric: Option<Metric>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct Pddl8GroundAtom {
pub pred: String,
pub args: Vec<String>,
}
impl Pddl8GroundAtom {
pub fn label(&self) -> String {
if self.args.is_empty() {
self.pred.clone()
} else {
format!("{}({})", self.pred, self.args.join(","))
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8GroundAction {
pub schema_name: String,
pub label: String,
pub preconditions: Vec<Pddl8GroundAtom>,
pub add_effects: Vec<Pddl8GroundAtom>,
pub del_effects: Vec<Pddl8GroundAtom>,
}
impl Pddl8GroundAction {
pub fn is_applicable<S>(&self, state: &S) -> bool
where
S: Contains<Pddl8GroundAtom>,
{
self.preconditions.iter().all(|p| state.contains_atom(p))
}
}
pub trait Contains<T> {
fn contains_atom(&self, item: &T) -> bool;
}
impl Contains<Pddl8GroundAtom> for std::collections::BTreeSet<Pddl8GroundAtom> {
fn contains_atom(&self, item: &Pddl8GroundAtom) -> bool {
self.contains(item)
}
}
impl Contains<Pddl8GroundAtom> for std::collections::HashSet<Pddl8GroundAtom> {
fn contains_atom(&self, item: &Pddl8GroundAtom) -> bool {
self.contains(item)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8TapeOp {
pub index: u8,
pub label: String,
pub pred_mask: u64,
pub action: Pddl8GroundAction,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8Tape {
pub ops: Vec<Pddl8TapeOp>,
}
impl Pddl8Tape {
pub fn from_plan(plan: Vec<Pddl8GroundAction>) -> Self {
let ops = plan
.into_iter()
.enumerate()
.map(|(i, action)| Pddl8TapeOp {
index: i as u8,
label: action.label.clone(),
pred_mask: if i == 0 { 0 } else { 1u64 << (i - 1) },
action,
})
.collect();
Self { ops }
}
pub fn len(&self) -> usize {
self.ops.len()
}
pub fn is_empty(&self) -> bool {
self.ops.is_empty()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8StepResult {
pub op_index: u8,
pub label: String,
pub admitted: bool,
pub epoch_after: u64,
pub receipt_hash: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8ExecutionLog {
pub steps: Vec<Pddl8StepResult>,
pub goal_reached: bool,
pub chain_hash: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8ExecutionReceipt {
pub plan_root: String,
pub state_root: String,
pub goal_root: String,
pub chain_hash: String,
pub goal_reached: bool,
pub step_count: usize,
}
pub fn schema_from_rule(
rule_id: &str,
premises: &[String],
conclusion: &str,
) -> Pddl8ActionSchema {
let preconditions = premises
.iter()
.map(|p| atom_from_pred_eq(p))
.collect();
let mut add_effects = Vec::new();
let mut del_effects = Vec::new();
for tok in conclusion.split(';').map(str::trim).filter(|s| !s.is_empty()) {
if let Some(rest) = tok.strip_prefix('!') {
del_effects.push(atom_from_pred_eq(rest));
} else {
add_effects.push(atom_from_pred_eq(tok));
}
}
Pddl8ActionSchema {
name: rule_id.to_string(),
params: vec![],
preconditions,
add_effects,
del_effects,
typed_params: vec![],
condition: None,
effects: vec![],
numeric_effects: vec![],
}
}
fn atom_from_pred_eq(s: &str) -> Pddl8Atom {
if let Some((p, v)) = s.split_once('=') {
Pddl8Atom { pred: p.to_string(), args: vec![v.to_string()] }
} else {
Pddl8Atom { pred: s.to_string(), args: vec![] }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct PddlType {
pub name: String,
pub parent: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PddlCondition {
Atom(Pddl8Atom),
Not(Box<PddlCondition>),
And(Vec<PddlCondition>),
Or(Vec<PddlCondition>),
Forall { vars: Vec<(String, String)>, body: Box<PddlCondition> },
Exists { vars: Vec<(String, String)>, body: Box<PddlCondition> },
Imply(Box<PddlCondition>, Box<PddlCondition>),
Timed(TimeSpecifier, Box<PddlCondition>),
Compare(NumericExpr, CompareOp, NumericExpr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompareOp { Ge, Le, Gt, Lt, Eq }
impl Default for PddlCondition {
fn default() -> Self { PddlCondition::And(vec![]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PddlFunction {
pub name: String,
pub params: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum NumericExpr {
Number(f64),
FunctionTerm(String, Vec<String>), BinOp { op: NumericOp, lhs: Box<NumericExpr>, rhs: Box<NumericExpr> },
Neg(Box<NumericExpr>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NumericOp { Add, Sub, Mul, Div }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum NumericEffect {
Assign(PddlFunction, NumericExpr),
Increase(PddlFunction, NumericExpr),
Decrease(PddlFunction, NumericExpr),
ScaleUp(PddlFunction, NumericExpr),
ScaleDown(PddlFunction, NumericExpr),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PddlEffect {
Add(Pddl8Atom),
Del(Pddl8Atom),
Numeric(NumericEffect),
Timed(TimeSpecifier, Box<PddlEffect>),
Forall { vars: Vec<(String, String)>, effects: Vec<PddlEffect> },
When { condition: PddlCondition, effects: Vec<PddlEffect> },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum TimeSpecifier { AtStart, AtEnd, OverAll }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DurationConstraint {
Eq(NumericExpr),
Lte(NumericExpr),
Gte(NumericExpr),
And(Vec<DurationConstraint>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DurativeAction {
pub name: String,
pub params: Vec<(String, String)>,
pub duration: DurationConstraint,
pub conditions: Vec<PddlCondition>,
pub effects: Vec<PddlEffect>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TimedLiteral {
pub time: f64,
pub atom: Pddl8Atom,
pub negated: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MetricExpr {
Number(f64),
FunctionTerm(String, Vec<String>),
TotalTime,
IsViolated(String),
BinOp { op: NumericOp, lhs: Box<MetricExpr>, rhs: Box<MetricExpr> },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MetricDir { Minimize, Maximize }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Metric { pub dir: MetricDir, pub expr: MetricExpr }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TrajectoryConstraint {
Always(Box<PddlCondition>),
Sometime(Box<PddlCondition>),
Within(f64, Box<PddlCondition>),
AtMostOnce(Box<PddlCondition>),
SometimeBefore(Box<PddlCondition>, Box<PddlCondition>),
SometimeAfter(Box<PddlCondition>, Box<PddlCondition>),
AlwaysWithin(f64, Box<PddlCondition>, Box<PddlCondition>),
HoldDuring(f64, f64, Box<PddlCondition>),
HoldAfter(f64, Box<PddlCondition>),
And(Vec<TrajectoryConstraint>),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PddlPreference {
pub name: Option<String>,
pub constraint: TrajectoryConstraint,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PddlConstraint {
pub name: Option<String>,
pub constraint: TrajectoryConstraint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DerivedPredicate {
pub head: Pddl8Atom,
pub body: PddlCondition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PddlProcess {
pub name: String,
pub params: Vec<(String, String)>,
pub precondition: PddlCondition,
pub effects: Vec<NumericEffect>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PddlEvent {
pub name: String,
pub params: Vec<(String, String)>,
pub precondition: PddlCondition,
pub effects: Vec<PddlEffect>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Pddl31Domain {
pub name: String,
pub requirements: Vec<String>,
pub types: Vec<PddlType>,
pub predicates: Vec<(String, Vec<(String, String)>)>,
pub functions: Vec<PddlFunction>,
pub actions: Vec<Pddl31Action>,
pub durative_actions: Vec<DurativeAction>,
pub derived: Vec<DerivedPredicate>,
pub constraints: Vec<PddlConstraint>,
pub processes: Vec<PddlProcess>,
pub events: Vec<PddlEvent>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl31Action {
pub name: String,
pub params: Vec<(String, String)>,
pub precondition: PddlCondition,
pub effect: Vec<PddlEffect>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Pddl31Problem {
pub name: String,
pub domain: String,
pub objects: Vec<(String, String)>,
pub init_atoms: Vec<Pddl8Atom>,
pub init_fn_values: Vec<(PddlFunction, f64)>,
pub timed_inits: Vec<TimedLiteral>,
pub goal: PddlCondition,
pub preferences: Vec<PddlPreference>,
pub metric: Option<Metric>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalPlanStep {
pub start_time: f64,
pub duration: f64,
pub action_name: String,
pub args: Vec<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TemporalPlan {
pub steps: Vec<TemporalPlanStep>,
pub makespan: f64,
pub metric_value: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalExecutionReceipt {
pub plan_root: String,
pub state_root: String,
pub goal_root: String,
pub makespan: f64,
pub step_count: usize,
pub requirements: Vec<String>,
pub goal_reached: bool,
pub chain_hash: String,
}