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, 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>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pddl8Domain {
pub name: String,
pub predicates: Vec<(String, u8)>,
pub actions: Vec<Pddl8ActionSchema>,
}
#[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>,
}
#[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,
}
}
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![] }
}
}