Commit adb217e9 authored by Arthur Bit-Monnot's avatar Arthur Bit-Monnot

[pddl] Minimal pddl parser.

parent 163ff060
......@@ -203,9 +203,9 @@ package object full {
override def toString: String = s"$template(${params.mkString(", ")})"
}
class ActionTemplate(override val name: String,
val containingModel: Model,
override val store: BlockStore[InActionBlock] = new BlockStore())
final case class ActionTemplate(override val name: String,
containingModel: Model,
override val store: BlockStore[InActionBlock] = new BlockStore())
extends Ctx
with InModuleBlock {
override val parent: Some[Ctx] = Some(containingModel)
......@@ -288,7 +288,7 @@ package object full {
store.declarations.get(id(single))
case subScopeName :: name :: Nil =>
store.declarations
.get(new Id(scope + subScopeName, name))
.get(Id(scope + subScopeName, name))
case Nil =>
sys.error("Invalid name: " + localID)
case _ =>
......
package dahu.planning.pddl
import dahu.planning.model.common.{operators, Arg, LocalVar}
import dahu.planning.model.full._
import dahu.planning.pddl.Utils._
import dahu.utils.errors._
import fr.uga.pddl4j.parser.{Exp, Op}
import scala.collection.JavaConverters._
class ActionFactory(actionName: String, parent: Resolver, model: Model) extends Factory {
implicit def predef = parent.predef
private var template = ActionTemplate(actionName, model)
private val start = LocalVar(resolver.id(predef.StartSym), resolver.predef.Time)
private val end = LocalVar(resolver.id(predef.EndSym), resolver.predef.Time)
rec(LocalVarDeclaration(start))
rec(LocalVarDeclaration(end))
override def context: ActionTemplate = template
override def getTranslator(name: String): FunctionCompat = parent.getTranslator(name)
private def duration: StaticExpr = BinaryExprTree(operators.Sub, end, start)
def rec(block: InActionBlock): Unit = {
template = template + block
}
def loadOp(op: Op): Unit = {
require(op.getName.getImage == actionName)
op.getParameters.asScala.foreach {
case ast.TypedSymbol(name, tpe) =>
rec(ArgDeclaration(Arg(resolver.id(name), resolver.typeOf(tpe))))
}
Option(op.getDuration) match {
case Some(ast.Eq(ast.Duration(_), ast.Cst(cst))) =>
rec(
BooleanAssertion(BinaryExprTree(operators.Eq, duration, cst))
)
case x => unexpected(x.toString)
}
recPrecondition(op.getPreconditions)
recEffect(op.getEffects)
}
private def recPrecondition(pre: Exp): Unit = pre match {
case ast.And(subs) =>
subs.foreach(recPrecondition)
case ast.AtStart(e) =>
e match {
case ast.AssertionOnFunction(funcName) =>
val assertion = resolver.getTranslator(funcName).condition(e, resolver)
rec(
TemporallyQualifiedAssertion(
Equals(Interval(start, start)),
assertion
)
)
}
case ast.AtEnd(e) =>
e match {
case ast.AssertionOnFunction(funcName) =>
val assertion = resolver.getTranslator(funcName).condition(e, resolver)
rec(
TemporallyQualifiedAssertion(
Equals(Interval(end, end)),
assertion
)
)
}
}
private def recEffect(pre: Exp): Unit = pre match {
case ast.And(subs) =>
subs.foreach(recEffect)
case ast.AtStart(e) =>
e match {
case ast.AssertionOnFunction(funcName) =>
val assertion = resolver.getTranslator(funcName).effect(e, resolver)
rec(
TemporallyQualifiedAssertion(
Equals(Interval(start, start)),
assertion
)
)
}
case ast.AtEnd(e) =>
e match {
case ast.AssertionOnFunction(funcName) =>
val assertion = resolver.getTranslator(funcName).effect(e, resolver)
rec(
TemporallyQualifiedAssertion(
Equals(Interval(end, end)),
assertion
)
)
}
}
def result: ActionTemplate = template
}
......@@ -12,23 +12,31 @@ import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.language.implicitConversions
abstract class Factory {
abstract class Factory { self =>
def context: Ctx
def predef: PddlPredef
implicit val resolver: Resolver = new Resolver {
def scope: Scope = context.scope
def ctx: Ctx = context
override def id(name: String): Id = Id(common.RootScope, name)
override def id(name: String): Id = Id(scope, name)
override def typeOf(name: String): Type =
context.findType(name).getOrElse(unexpected(s"unknown type: $name"))
override def variable(name: String): StaticExpr = context.findDeclaration(name) match {
case Some(v: VarDeclaration[_]) => CommonTerm(v.variable)
case _ => unexpected(s"unknown variable: $name")
case err =>
println(context)
println(err)
unexpected(s"unknown variable: $name")
}
override def nextId(): String = dahu.planning.model.reservedPrefix + next().toString
def getTranslator(name: String): FunctionCompat = self.getTranslator(name)
override def predef: PddlPredef = self.predef
}
def getTranslator(name: String): FunctionCompat
......@@ -42,7 +50,7 @@ abstract class Factory {
}
class ModelFactory(predef: PddlPredef.type) extends Factory {
class ModelFactory(val predef: PddlPredef) extends Factory {
private var model = predef.baseModel
override def context: Model = model
......@@ -85,7 +93,7 @@ class ModelFactory(predef: PddlPredef.type) extends Factory {
private def recordInitialState(e: Exp): Unit = {
val assertion = e match {
case ast.AssertionOnFunction(funcName) =>
getTranslator(funcName).effect(e)
getTranslator(funcName).effect(e, resolver)
}
rec(TemporallyQualifiedAssertion(Equals(Interval(predef.Start, predef.Start)), assertion))
}
......@@ -94,7 +102,7 @@ class ModelFactory(predef: PddlPredef.type) extends Factory {
case ast.And(goals) =>
goals.foreach(recordGoal)
case ast.AssertionOnFunction(name) =>
val assertion = getTranslator(name).condition(e)
val assertion = getTranslator(name).condition(e, resolver)
rec(
TemporallyQualifiedAssertion(
Equals(Interval(predef.End, predef.End)),
......@@ -128,6 +136,11 @@ class ModelFactory(predef: PddlPredef.type) extends Factory {
}
dom.getDerivesPredicates.asScala.foreach(_ => ???)
dom.getOperators.asScala.foreach { op =>
val fact = new ActionFactory(op.getName.getImage, resolver, model)
fact.loadOp(op)
rec(fact.result)
}
}
def loadProblem(pb: Problem): Unit = {
......
......@@ -15,84 +15,93 @@ abstract class FunctionCompat() {
def name: String
def model: FluentTemplate
def condition(e: Exp): TimedEqualAssertion // TODO: should probably take a context
def effect(e: Exp): TimedAssignmentAssertion
def condition(e: Exp, res: Resolver): TimedEqualAssertion // TODO: should probably take a context
def effect(e: Exp, res: Resolver): TimedAssignmentAssertion
}
object FunctionCompat {
def apply(pddl: NamedTypedList)(implicit ctx: Resolver): FunctionCompat = {
pddl.getTypes.asScala match {
case Seq() => new DefaultPredicate(pddl)
case Seq(tpe) => new DefaultFunction(pddl)
case Seq() => new DefaultPredicate(pddl, ctx)
case Seq(tpe) => new DefaultFunction(pddl, ctx)
case _ => unexpected
}
}
}
class DefaultPredicate(pddl: NamedTypedList)(implicit ctx: Resolver) extends FunctionCompat {
class DefaultPredicate(pddl: NamedTypedList, top: Resolver) extends FunctionCompat {
implicit private def predef = top.predef
override val name: String = pddl.getName.getImage
private val tpe = pddl.getTypes.asScala match {
case Seq() => PddlPredef.Boolean
case Seq() => top.predef.Boolean
case _ => unexpected
}
override val model =
FluentTemplate(ctx.id(name), tpe, pddl.getArguments.asScala.map {
case ast.TypedSymbol(argName, argType) => common.Arg(ctx.id(argName), ctx.typeOf(argType))
FluentTemplate(top.id(name), tpe, pddl.getArguments.asScala.map {
case ast.TypedSymbol(argName, argType) => common.Arg(top.id(argName), top.typeOf(argType))
})
override def condition(e: Exp): TimedEqualAssertion = e match {
override def condition(e: Exp, local: Resolver): TimedEqualAssertion = e match {
case ast.Fluent(fun, args) if fun == name =>
TimedEqualAssertion(
Fluent(model, args.map(ctx.variable)),
PddlPredef.True,
None, //TODO
ctx.nextId()
Fluent(model, args.map(local.variable)),
local.predef.True,
Some(local.ctx),
local.nextId()
)
case _ => unexpected
}
override def effect(e: Exp): TimedAssignmentAssertion = e match {
override def effect(e: Exp, local: Resolver): TimedAssignmentAssertion = e match {
case ast.Fluent(fun, args) if fun == name =>
TimedAssignmentAssertion(
Fluent(model, args.map(ctx.variable)),
predef.True,
None, //TODO
dahu.planning.model.reservedPrefix + next()
Fluent(model, args.map(local.variable)),
local.predef.True,
Some(local.ctx),
local.nextId()
)
case ast.Not(ast.Fluent(fun, args)) =>
TimedAssignmentAssertion(
Fluent(model, args.map(local.variable)),
predef.False,
Some(local.ctx),
local.nextId()
)
case _ => unexpected
}
}
class DefaultFunction(pddl: NamedTypedList)(implicit ctx: Resolver) extends FunctionCompat {
class DefaultFunction(pddl: NamedTypedList, top: Resolver) extends FunctionCompat {
implicit private def predef = top.predef
override val name: String = pddl.getName.getImage
private val tpe = pddl.getTypes.asScala match {
case Seq(t) => typeOf(t.getImage)
case Seq(t) => top.typeOf(t.getImage)
case _ => unexpected
}
override val model =
FluentTemplate(id(name), tpe, pddl.getArguments.asScala.map {
case ast.TypedSymbol(argName, argType) => common.Arg(id(argName), typeOf(argType))
FluentTemplate(top.id(name), tpe, pddl.getArguments.asScala.map {
case ast.TypedSymbol(argName, argType) => common.Arg(top.id(argName), top.typeOf(argType))
})
override def condition(e: Exp): TimedEqualAssertion = e match {
override def condition(e: Exp, local: Resolver): TimedEqualAssertion = e match {
case ast.Eq(ast.Fluent(funName, args), ast.Cst(rhs)) if funName == name =>
TimedEqualAssertion(
Fluent(model, args.map(ctx.variable)),
Fluent(model, args.map(local.variable)),
rhs,
None, //TODO
dahu.planning.model.reservedPrefix + next()
Some(local.ctx),
local.nextId()
)
case _ => unexpected
}
override def effect(e: Exp): TimedAssignmentAssertion = e match {
override def effect(e: Exp, local: Resolver): TimedAssignmentAssertion = e match {
case ast.Eq(ast.Fluent(funName, args), ast.Cst(rhs)) if funName == name =>
TimedAssignmentAssertion(
Fluent(model, args.map(ctx.variable)),
Fluent(model, args.map(local.variable)),
rhs,
None, //TODO
dahu.planning.model.reservedPrefix + next()
Some(local.ctx),
local.nextId()
)
case _ => unexpected
}
......
package dahu.planning.pddl
import fr.uga.pddl4j.parser._
import java.io.File
import scala.language.implicitConversions
import scala.util.{Failure, Success}
object Main extends App {
val domFile = "/home/arthur/work/fape/planning/domains/blocks_ipc2/pddl/blocks_ipc2.dom.pddl"
val pbFile = "/home/arthur/work/fape/planning/domains/blocks_ipc2/pddl/blocks_ipc2.p04-0.pb.pddl"
val domFile = new File(
"/home/arthur/work/fape/planning/domains/blocks_ipc2/pddl/blocks_ipc2.dom.pddl")
val pbFile = new File(
"/home/arthur/work/fape/planning/domains/blocks_ipc2/pddl/blocks_ipc2.p04-0.pb.pddl")
// val domFile =
// "/home/arthur/work/ext/rcll/temporal_1_robot/rcll_domain_production_durations_nors.pddl"
// val pbFile = "/home/arthur/work/ext/rcll/temporal_1_robot/problem-001-r1-o1-durations.pddl"
val parser = new Parser()
parser.parse(domFile, pbFile)
val dom = parser.getDomain
val pb = parser.getProblem
println(dom)
// println(pb)
val factory = new ModelFactory(PddlPredef)
factory.loadDomain(dom)
factory.loadProblem(pb)
println(factory.result)
new Parser(Options()).parseToFull(domFile, pbFile) match {
case Success(model) => println(model)
case Failure(e) =>
e.printStackTrace()
System.exit(1)
}
}
package dahu.planning.pddl
case class Options(discretization: Int = 1)
package dahu.planning.pddl
import java.io.File
import dahu.planning.model.core.CoreModel
import dahu.planning.model.full.Model
import dahu.planning.model.transforms.FullToCore
import scala.util.Try
class Parser(opt: Options) {
implicit private val predef: PddlPredef = PddlPredef(opt.discretization)
def parseToFull(domain: File, problem: File): Try[Model] = Try {
val parser = new fr.uga.pddl4j.parser.Parser()
parser.parse(domain, problem)
val factory = new ModelFactory(predef)
factory.loadDomain(parser.getDomain)
factory.loadProblem(parser.getProblem)
factory.result
}
def parse(domain: File, problem: File): Try[CoreModel] = {
parseToFull(domain, problem).flatMap { m =>
Try(FullToCore.trans(m))
}
}
}
......@@ -4,21 +4,27 @@ import dahu.planning.model.common._
import dahu.planning.model.common.Type._
import dahu.planning.model.full._
object PddlPredef extends Predef {
private val scope = RootScope + "_predef_"
override val Time: IRealType = IntSubType(scope / "time", Integers)
case class PddlPredef(discretization: Int) extends Predef {
override val Boolean: BooleanType = BooleanType(scope / "boolean")
val StartSym = "⊢"
val EndSym = "⊣"
val TrueSym = "⊤"
val FalseSym = "⊥"
val TimeSym = "𝓣𝓲𝓶𝓮"
val BooleanSym = "𝓑𝓸𝓸𝓵"
override val True: Instance = Instance(scope / "true", Boolean)
override val False: Instance = Instance(scope / "false", Boolean)
override val Time: IRealType = IntSubType(RootScope / TimeSym, Integers)
override val Start = LocalVar(scope / "start", Time)
override val End = LocalVar(scope / "end", Time)
override val Boolean: BooleanType = BooleanType(RootScope / BooleanSym)
override val True: Instance = Instance(RootScope / TrueSym, Boolean)
override val False: Instance = Instance(RootScope / FalseSym, Boolean)
override val Start = LocalVar(RootScope / StartSym, Time)
override val End = LocalVar(RootScope / EndSym, Time)
val Number = IntSubType(RootScope / "number", Integers)
val discretization = 1000
def discretize(d: Double): Int = (d * discretization).toInt
override def baseModel: Model =
......
package dahu.planning.pddl
import dahu.planning.model.common.{Id, Scope, Type}
import dahu.planning.model.full.StaticExpr
import dahu.planning.model.full.{Ctx, StaticExpr}
trait Resolver {
def scope: Scope
def scope: Scope = ctx.scope
def ctx: Ctx
def predef: PddlPredef
def typeOf(name: String): Type
def id(name: String): Id
def variable(name: String): StaticExpr
def getTranslator(name: String): FunctionCompat
def nextId(): String
}
......
......@@ -8,7 +8,6 @@ import scala.language.implicitConversions
object Utils {
private var counter = 0
implicit val predef: Predef = PddlPredef
def next(): Int = { counter += 1; counter }
implicit def term2FullModel(v: Term): CommonTerm = CommonTerm(v)
......
......@@ -9,9 +9,10 @@ import scala.collection.JavaConverters._
object AssertionOnFunction {
def unapply(e: Exp): Option[String] = e match {
case Fluent(name, _) => Some(name)
case Eq(Fluent(name, _), _) => Some(name)
case _ => None
case Fluent(name, _) => Some(name)
case Eq(Fluent(name, _), _) => Some(name)
case Not(AssertionOnFunction(name)) => Some(name)
case _ => None
}
}
......@@ -29,9 +30,9 @@ object Fluent {
}
object Cst {
def unapply(e: Exp): Option[Cst] = {
def unapply(e: Exp)(implicit predef: PddlPredef): Option[Cst] = {
if(e.getConnective == Connective.NUMBER)
Some(IntLiteral(PddlPredef.discretize(e.getValue)))
Some(IntLiteral(predef.discretize(e.getValue)))
else
None
}
......@@ -39,7 +40,7 @@ object Cst {
object Eq {
def unapply(e: Exp): Option[(Exp, Exp)] = {
if(e.getConnective == Connective.FN_ATOM) {
if(e.getConnective == Connective.FN_ATOM || e.getConnective == Connective.EQUAL) {
e.getChildren.asScala.toList match {
case lhs :: rhs :: Nil => Some((lhs, rhs))
case _ => unexpected
......@@ -50,6 +51,19 @@ object Eq {
}
}
object Not {
def unapply(e: Exp): Option[Exp] = {
if(e.getConnective == Connective.NOT) {
e.getChildren.asScala match {
case Seq(neg) => Some(neg)
case _ => unexpected
}
} else {
None
}
}
}
case class Tpe(name: String, parent: Option[String])
object ReadTpe {
......@@ -77,11 +91,11 @@ object And {
object TypedSymbol {
def unapply(e: TypedSymbol): Option[(String, String)] = {
if(e.getKind == Symbol.Kind.VARIABLE || e.getKind == Symbol.Kind.CONSTANT) {
val name =
if(e.getImage.startsWith("?"))
e.getImage.drop(1)
else
e.getImage
val name = e.getImage
// if(e.getImage.startsWith("?"))
// e.getImage.drop(1)
// else
// e.getImage
e.getTypes.asScala.toList match {
case tpe :: Nil => Some((name, tpe.getImage))
case _ => None
......@@ -91,3 +105,38 @@ object TypedSymbol {
}
}
}
object Duration {
def unapply(e: Exp): Option[Unit] = {
if(e.getConnective == Connective.TIME_VAR && e.getVariable.getImage == "?duration")
Some(())
else
None
}
}
object AtStart {
def unapply(e: Exp): Option[Exp] = {
if(e.getConnective == Connective.AT_START) {
e.getChildren.asScala match {
case Seq(sub) => Some(sub)
case _ => unexpected
}
} else {
None
}
}
}
object AtEnd {
def unapply(e: Exp): Option[Exp] = {
if(e.getConnective == Connective.AT_END) {
e.getChildren.asScala match {
case Seq(sub) => Some(sub)
case _ => unexpected
}
} else {
None
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment