diff --git a/unified_planning/io/pddl_writer.py b/unified_planning/io/pddl_writer.py index 5247ac951..b471016d6 100644 --- a/unified_planning/io/pddl_writer.py +++ b/unified_planning/io/pddl_writer.py @@ -1238,6 +1238,8 @@ def _write_derivative( out.write(f" (increase {fluent} (* #t {converter.convert(simplified_value)} ))") elif effect.is_decrease(): out.write(f" (decrease {fluent} (* #t {converter.convert(simplified_value)} ))") + elif effect.is_derivative(): + out.write(f" (increase {fluent} (* #t {converter.convert(simplified_value)} ))") else: raise UPProblemDefinitionError( "Derivative can only be expressed as increase, decrease in processes", diff --git a/unified_planning/model/action.py b/unified_planning/model/action.py index f0ec258b6..ab01f10cf 100644 --- a/unified_planning/model/action.py +++ b/unified_planning/model/action.py @@ -948,7 +948,7 @@ def add_derivative( fluent_exp, value_exp, condition_exp, - kind=up.model.effect.EffectKind.INCREASE, + kind=up.model.effect.EffectKind.DERIVATIVE, forall=tuple(), ) ) diff --git a/unified_planning/model/effect.py b/unified_planning/model/effect.py index 071160e22..2d7fed516 100644 --- a/unified_planning/model/effect.py +++ b/unified_planning/model/effect.py @@ -38,11 +38,13 @@ class EffectKind(Enum): `ASSIGN` => `if C then F <= V` `INCREASE` => `if C then F <= F + V` `DECREASE` => `if C then F <= F - V` + `DERIVATIVE` => `dF/dt <= V` """ ASSIGN = auto() INCREASE = auto() DECREASE = auto() + DERIVATIVE = auto() class Effect: @@ -109,13 +111,16 @@ def __repr__(self) -> str: s.append(f"forall {', '.join(str(v) for v in self._forall)}") if self.is_conditional(): s.append(f"if {str(self._condition)} then") - s.append(f"{str(self._fluent)}") + if not(self.is_derivative()): + s.append(f"{str(self._fluent)}") if self.is_assignment(): s.append(":=") elif self.is_increase(): s.append("+=") elif self.is_decrease(): s.append("-=") + elif self.is_derivative(): + s.append(f"d{str(self._fluent)}/dt =") s.append(f"{str(self._value)}") return " ".join(s) @@ -244,6 +249,9 @@ def is_increase(self) -> bool: def is_decrease(self) -> bool: """Returns `True` if the :func:`kind ` of this `Effect` is a `decrease`, `False` otherwise.""" return self._kind == EffectKind.DECREASE + def is_derivative(self) -> bool: + """Returns `True` if the :func:`kind ` of this `Effect` is a `derivative`, `False` otherwise.""" + return self._kind == EffectKind.DERIVATIVE class SimulatedEffect: diff --git a/unified_planning/test/test_model.py b/unified_planning/test/test_model.py index a5b8582a7..6e9d23a2e 100644 --- a/unified_planning/test/test_model.py +++ b/unified_planning/test/test_model.py @@ -111,6 +111,36 @@ def test_clone_effect(self): self.assertNotEqual(e, e.value) self.assertNotEqual(e.value, e) + def test_process(self): + Vehicle = UserType("Vehicle") + a = Fluent("a",BoolType()) + x = Fluent("x", IntType()) + move = Process("moving",car = Vehicle) + move.add_precondition(a) + move.add_derivative(x,1) + e = Effect( + FluentExp(x), Int(1), TRUE(), unified_planning.model.EffectKind.DERIVATIVE + ) + self.assertEqual(move.effects[0],e) + self.assertEqual(move.name,"moving") + self.assertEqual(isinstance(move,Process),True) + + def test_event(self): + Vehicle = UserType("Vehicle") + a = Fluent("a",BoolType()) + x = Fluent("x", IntType()) + fell = Event("fell",car = Vehicle) + fell.add_precondition(a) + fell.add_effect(x,1) + e = Effect( + FluentExp(x), Int(1), TRUE(), unified_planning.model.EffectKind.ASSIGN + ) + self.assertEqual(fell.effects[0],e) + self.assertEqual(fell.name,"fell") + self.assertEqual(isinstance(fell,Event),True) + self.assertEqual(isinstance(fell,InstantaneousAction),False) + + def test_istantaneous_action(self): Location = UserType("Location") move = InstantaneousAction("move", l_from=Location, l_to=Location)