-
Notifications
You must be signed in to change notification settings - Fork 1
Add forall tag to preconditions #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
d72e1be
b668073
38f5295
0b60cc3
03b838b
6f7e2ab
d5490df
cbf3145
20fe195
690160d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,3 +17,6 @@ dist/ | |
|
|
||
| # Mypy specific | ||
| .mypy_cache/ | ||
|
|
||
| # Vim | ||
| *.swp | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Callable, Generator, MutableMapping, Sequence | ||
| from collections.abc import Callable, Generator, MutableMapping, Sequence, Mapping | ||
| from dataclasses import dataclass, field | ||
| from enum import StrEnum | ||
| from itertools import chain | ||
|
|
@@ -15,6 +15,7 @@ | |
| Condition, | ||
| Domain, | ||
| EqualityCondition, | ||
| ForallCondition, | ||
| Identifier, | ||
| NotCondition, | ||
| Object, | ||
|
|
@@ -454,6 +455,7 @@ def argument_to_asp(argument: Argument) -> ArgumentAST: | |
|
|
||
|
|
||
| def action_definition_asp_part( | ||
| problem: Problem, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd really rather you not add the problem to the action definition, as this basically destroys caching, which we currently make use of. You don't need to do this! You can encode universal quantification just fine without explicitly mentioning objects from the problem, and making a bunch of
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I agree that this is disgusting -- to be perfectly transparent this is the first time I'm dealing with ASP so I think I didn't solve the problem in a good way :) I'll fix it to match your implementation
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed as of latest commit but ended up doing a rewrite |
||
| action_definition: ActionDefinition, | ||
| variable_id_allocator: IDAllocator[Variable], | ||
| object_id_allocator: IDAllocator[Object], | ||
|
|
@@ -478,9 +480,52 @@ def action_definition_asp_part( | |
| ], | ||
| ) | ||
|
|
||
| # Specify the precondition over the parameters | ||
| # Preprocess precondition to replace Foralls with series of Ands | ||
| def _expand_substitute( | ||
| condition: Condition[Argument], substitutions: Mapping[Variable, Object] | ||
| ) -> Condition[Object]: | ||
| """Fold in to use global information for Forall...""" | ||
| match condition: | ||
| case AndCondition(subconditions): | ||
| return AndCondition( | ||
| [ | ||
| _expand_substitute(subcondition, substitutions) | ||
| for subcondition in subconditions | ||
| ] | ||
| ) | ||
| case OrCondition(subconditions): | ||
| return OrCondition( | ||
| [ | ||
| _expand_substitute(subcondition, substitutions) | ||
| for subcondition in subconditions | ||
| ] | ||
| ) | ||
| case NotCondition(base_condition): | ||
| return NotCondition(_expand_substitute(base_condition, substitutions)) | ||
| case EqualityCondition(left_side, right_side): | ||
| return EqualityCondition( | ||
| substitutions.get(left_side, left_side), | ||
| substitutions.get(right_side, right_side), | ||
| ) | ||
| case ForallCondition(loop_var, condition): | ||
| new_subs = dict(substitutions) | ||
| conditions = [] | ||
| for param in problem.objects_section: | ||
| if param.type == loop_var.type: | ||
| new_subs[loop_var.value] = param.value | ||
| conditions.append(_expand_substitute(condition, new_subs)) | ||
| return AndCondition(conditions) | ||
| case Predicate(name, assignment): | ||
| return Predicate( | ||
| name, | ||
| tuple( | ||
| substitutions.get(argument, argument) | ||
| for argument in assignment | ||
| ), | ||
| ) | ||
|
|
||
| precondition_id = _add_condition_to_asp_part( | ||
| action_definition.precondition, | ||
| _expand_substitute(action_definition.precondition, {}), | ||
| part, | ||
| IDAllocator.from_id_constructor(RuleID), | ||
| variable_id_allocator, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -638,6 +638,32 @@ def _as_str_without_location(self) -> str: | |
| def __repr__(self) -> str: | ||
| return f"(= {self.left_side!r} {self.right_side!r})" | ||
|
|
||
| @dataclass(frozen=True) | ||
| class ForallCondition[A: Argument]: | ||
| """Represents an forall predicate (forall (arg) condition) in PDDL.""" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be "a", not "an", and in parnetheses, write |
||
|
|
||
| loop_var: Typed | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this called
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed renamed to (variable). Type list[Typed[Variable]] |
||
| condition: "Condition[A]" | ||
|
|
||
| def _validate( | ||
| self, | ||
| parameters: Parameters, | ||
| objects: Mapping[Object, Type], | ||
| domain: "Domain", | ||
| ) -> None: | ||
|
|
||
| scope_dict = dict(parameters._items) | ||
| scope_dict[self.loop_var.value] = self.loop_var.type | ||
| self.condition._validate(scope_dict, objects, domain) | ||
|
|
||
| @override | ||
| def _as_str_without_location(self) -> str: | ||
| return "forall predicate" | ||
|
|
||
| @override | ||
| def __repr__(self) -> str: | ||
| return f"(= {self.left_side!r} {self.right_side!r})" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be a remnant of copying from
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
|
|
||
|
|
||
| class _SerializedPredicate(TypedDict): | ||
| name: Any | ||
|
|
@@ -735,6 +761,7 @@ def __str__(self): | |
| | OrCondition[A] | ||
| | NotCondition[A] | ||
| | EqualityCondition[A] | ||
| | ForallCondition[A] | ||
| | Predicate[A] | ||
| ) | ||
| """Represents a condition in PDDL, over objects, or variables.""" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,8 +64,11 @@ EQUALS_SIGN: "=" | |
| | "(" OR_KEYWORD list_{condition{argument}} ")" -> or_condition | ||
| | "(" NOT_KEYWORD condition{argument} ")" -> not_condition | ||
| | "(" EQUALS_SIGN argument argument ")" -> equality_condition | ||
| | "(" "forall" "(" VARIABLE "-" _type ")" condition{argument} ")" -> forall_condition | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably also allow quantification over all objects (no type specified). You should probably create a parameterized parser (like say |
||
| | predicate{argument} | ||
|
|
||
| //| "(" "forall" "(" VARIABLE "-" _type ")" "when" "(" condition{argument} ")" condition{argument} ")" -> forall_when_condition | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this comment still here? Is this part of the PR, or not? If not, remove it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
|
|
||
| not_predicate{argument}: "(" "not" predicate{argument} ")" | ||
| _atom{argument}: predicate{argument} | ||
| | not_predicate{argument} | ||
|
|
@@ -109,4 +112,4 @@ _goal_section: "(" ":goal" condition{object_} ")" | |
| GOALS_KEYWORD: ":goals" | ||
| goals_section: "(" GOALS_KEYWORD list_{condition{object_}} ")" | ||
|
|
||
| problem: "(" "define" _problem_name _used_domain_name [[requirements_section{problem_requirement}]] [objects_section] [action_fallibilities_section] [revealables_section] [initialization_section] (_goal_section | goals_section) ")" | ||
| problem: "(" "define" _problem_name _used_domain_name [[requirements_section{problem_requirement}]] [objects_section] [action_fallibilities_section] [revealables_section] [initialization_section] (_goal_section | goals_section) ")" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is there a diff here? These lines look the exact same. Weird.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe an ending newline diff? I don't know... |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,7 +50,7 @@ def _make_atom_hold(self, atom: Atom[Object]) -> None: | |
| case Predicate(): | ||
| self._true_predicates.add(atom) | ||
| case NotPredicate(base_predicate): | ||
| self._true_predicates.remove(base_predicate) | ||
| self._true_predicates.discard(base_predicate) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know the idea here is to allow non-existent predicates, but this is not something we plan to support. Non-existent predicates will always remain an error, for the foreseeable future.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I'm pretty sure you'd have to modify the parser for this anyway, since we currently do validation on all PDDL input.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I should've specified the intent; I ran into an error where I was setting a predicate to False as part of an action's effect; but if that predicate is already false, then this causes an error. This change was intended to allow that behavior, not to allow non-existent predicates.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I see, yeah you're totally right, this would be a bug. It's a shame we didn't catch it earlier. Please remove this from the PR. I'll open a separate PR fixing this, and adding a test so the issue doesn't arise again. |
||
|
|
||
| def does_condition_hold(self, condition: Condition[Object]) -> bool: | ||
| """Check if the given grounded condition holds in the state.""" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a crash recovery file on Vim, right? In that case, I really don't think this should be in the
.gitignore. Just don't commit it, and once it serves its purpose ideally remove it from your filesystem.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vim creates
.swpfiles whenever a file is opened; basically if yougit statuswhile vim is still open it'll show a bunch of .swp files. I can remove it from the .gitignoreThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I actually think it is a good idea to include in the ..gitignore. Otherwise, these swp files show up in the status checks and "untracked". Technically this is harmless, but in practice, this is annoying and distracting.
So putting *.swp and *~ in the .gitignore file is good practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, personally, I've never had this issue while using Vim, and am kind of of the belief that a
.gitignoreshould only include what's relevant to the project itself, and is independent of the tooling used by developers, but if you really feel like this is fine, I'm also not too against it.It does feel like just using Git's
core.excludesfilewould be enough though, but I'm not a very frequent Vim user anymore.