Skip to content

Commit e901bb7

Browse files
Merge pull request #295 from Learning-and-Intelligent-Systems/master
[merge upstream] Merge in latest VLM-related changes
2 parents d71d26b + 374c4e8 commit e901bb7

30 files changed

Lines changed: 1170 additions & 530 deletions

.predicators_pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ confidence=
5252
# --enable=similarities". If you want to run only the classes checker, but have
5353
# no Warning level messages displayed, use"--disable=all --enable=classes
5454
# --disable=W"
55-
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,not-callable,logging-format-interpolation,consider-using-enumerate,invalid-name,eval-used,len-as-condition,raise-missing-from,consider-using-with,logging-fstring-interpolation,cache-max-size-none,unnecessary-lambda-assignment
55+
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,not-callable,logging-format-interpolation,consider-using-enumerate,invalid-name,eval-used,len-as-condition,raise-missing-from,consider-using-with,logging-fstring-interpolation,cache-max-size-none,unnecessary-lambda-assignment,cyclic-import
5656

5757
# Enable the message, report, category or checker with the given id(s). You can
5858
# either give multiple identifier separated by comma (,) or put this option

predicators/approaches/grammar_search_invention_approach.py

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ def enumerate(self) -> Iterator[Tuple[Predicate, float]]:
468468
"((0:robot).fingers<=[idx 0]0.5)"
469469
],
470470
"burger_no_move": [
471-
"((0:robot).fingers<=[idx 0]0.5)"
471+
"((0:robot).fingers<=[idx 0]0.5)",
472472
],
473473
"unittest": [
474474
"((0:robot).hand<=[idx 0]0.65)", "((0:block).grasp<=[idx 0]0.0)",
@@ -885,6 +885,7 @@ class _ForallPredicateGrammarWrapper(_PredicateGrammar):
885885
base_grammar: _PredicateGrammar
886886

887887
def enumerate(self) -> Iterator[Tuple[Predicate, float]]:
888+
forall_penalty = CFG.grammar_search_forall_penalty
888889
for (predicate, cost) in self.base_grammar.enumerate():
889890
yield (predicate, cost)
890891
if predicate.arity == 0:
@@ -894,14 +895,15 @@ def enumerate(self) -> Iterator[Tuple[Predicate, float]]:
894895
forall_predicate = Predicate(str(forall_classifier), [],
895896
forall_classifier)
896897
assert forall_predicate.arity == 0
897-
yield (forall_predicate, cost + 1) # add arity + 1 to cost
898+
yield (forall_predicate, cost + forall_penalty)
898899
# Generate NOT-Forall(x)
899900
notforall_classifier = _NegationClassifier(forall_predicate)
900901
notforall_predicate = Predicate(str(notforall_classifier),
901902
forall_predicate.types,
902903
notforall_classifier)
903904
assert notforall_predicate.arity == 0
904-
yield (notforall_predicate, cost + 1) # add arity + 1 to cost
905+
yield (notforall_predicate, cost + forall_penalty)
906+
905907
# Generate UFFs
906908
if predicate.arity >= 2:
907909
for idx in range(predicate.arity):
@@ -911,14 +913,14 @@ def enumerate(self) -> Iterator[Tuple[Predicate, float]]:
911913
[predicate.types[idx]],
912914
uff_classifier)
913915
assert uff_predicate.arity == 1
914-
yield (uff_predicate, cost + 2) # add arity + 1 to cost
916+
yield (uff_predicate, cost + forall_penalty + 1)
915917
# Negated UFF
916918
notuff_classifier = _NegationClassifier(uff_predicate)
917919
notuff_predicate = Predicate(str(notuff_classifier),
918920
uff_predicate.types,
919921
notuff_classifier)
920922
assert notuff_predicate.arity == 1
921-
yield (notuff_predicate, cost + 2) # add arity + 1 to cost
923+
yield (notuff_predicate, cost + forall_penalty + 1)
922924

923925

924926
################################################################################
@@ -942,6 +944,12 @@ def __init__(self, initial_predicates: Set[Predicate],
942944
def get_name(cls) -> str:
943945
return "grammar_search_invention"
944946

947+
def load(self, online_learning_cycle: Optional[int]) -> None:
948+
super().load(online_learning_cycle)
949+
preds, _ = utils.extract_preds_and_types(self._nsrts)
950+
self._learned_predicates = set(
951+
preds.values()) - self._initial_predicates
952+
945953
def _get_current_predicates(self) -> Set[Predicate]:
946954
return self._initial_predicates | self._learned_predicates
947955

@@ -959,6 +967,9 @@ def _generate_atom_dataset_via_grammar(
959967
self._metrics["grammar_size"] = len(candidates)
960968
for predicate, cost in candidates.items():
961969
logging.info(f"{predicate} {cost}")
970+
# Now, rename these predicates to be compatible with PDDL planners!
971+
renamed_candidates = self.\
972+
_rename_predicates_to_remove_incompatible_chars(candidates)
962973
# Apply the candidate predicates to the data.
963974
logging.info("Applying predicates to data...")
964975

@@ -983,13 +994,13 @@ def _generate_atom_dataset_via_grammar(
983994
else:
984995
atom_dataset = utils.create_ground_atom_dataset(
985996
dataset.trajectories,
986-
set(candidates) | self._initial_predicates)
997+
set(renamed_candidates) | self._initial_predicates)
987998
# Save this atoms dataset if the save_atoms flag is set.
988999
if CFG.save_atoms:
9891000
utils.save_ground_atom_dataset(atom_dataset, dataset_fname)
9901001
logging.info("Done.")
9911002
assert atom_dataset is not None
992-
return (atom_dataset, candidates)
1003+
return (atom_dataset, renamed_candidates)
9931004

9941005
def _parse_atom_dataset_from_annotated_dataset(
9951006
self, dataset: Dataset
@@ -1016,6 +1027,22 @@ def _parse_atom_dataset_from_annotated_dataset(
10161027
logging.debug(f"All candidate predicates: {candidates.keys()}")
10171028
return (atom_dataset, candidates)
10181029

1030+
def _rename_predicates_to_remove_incompatible_chars(
1031+
self, predicates_and_costs: Dict[Predicate,
1032+
float]) -> Dict[Predicate, float]:
1033+
"""Renames predicates to get rid of characters in the name that are
1034+
incompatible with PDDL planners like FD."""
1035+
renamed_predicates: Dict[Predicate, float] = {}
1036+
for p in predicates_and_costs:
1037+
if isinstance(p, VLMPredicate): # pragma: no cover.
1038+
renamed_predicates[p] = predicates_and_costs[p]
1039+
continue
1040+
new_name = p.name.replace("(", "[").replace(")",
1041+
"]").replace(" ", "_")
1042+
renamed_pred = Predicate(new_name, p.types, p._classifier) # pylint:disable=protected-access
1043+
renamed_predicates[renamed_pred] = predicates_and_costs[p]
1044+
return renamed_predicates
1045+
10191046
def learn_from_offline_dataset(self, dataset: Dataset) -> None:
10201047
if CFG.offline_data_method in [
10211048
"geo_and_demo_with_vlm_imgs", "geo_and_demo+labelled_atoms",
@@ -1027,7 +1054,15 @@ def learn_from_offline_dataset(self, dataset: Dataset) -> None:
10271054
self._parse_atom_dataset_from_annotated_dataset(dataset)
10281055
atom_dataset = utils.merge_ground_atom_datasets(
10291056
atom_dataset_from_grammar, atom_dataset_from_vlm)
1030-
candidates = candidates_from_grammar | candidates_from_vlm
1057+
# If grammar_search_invent_geo_predicates_only is False, then we
1058+
# want to invent both VLM and geo predicates
1059+
if not CFG.grammar_search_invent_geo_predicates_only:
1060+
candidates = candidates_from_grammar | candidates_from_vlm
1061+
# Otherwise, we only want to invent geo predicates, and directly
1062+
# select all the VLM predicates.
1063+
else:
1064+
candidates = candidates_from_grammar
1065+
self._initial_predicates |= set(candidates_from_vlm.keys())
10311066
elif not CFG.offline_data_method in [
10321067
"demo+labelled_atoms", "saved_vlm_img_demos_folder",
10331068
"demo_with_vlm_imgs"
@@ -1045,8 +1080,22 @@ def learn_from_offline_dataset(self, dataset: Dataset) -> None:
10451080
CFG.grammar_search_use_handcoded_debug_grammar:
10461081
# Skip hill-climbing and select all the predicates from the
10471082
# debug grammar.
1083+
# Same functionality as
1084+
# _rename_predicates_to_remove_incompatible_chars.
1085+
# We have to do it again here because the predicates in
1086+
# _DEBUG_GEOMETRIC_PREDICATES haven't been renamed to make them
1087+
# compatible with fast-downward. If we do rename them, grammar
1088+
# generation gets messed up (for a
1089+
# not-yet-investigated reason).
1090+
def rename(p: str) -> str: # pragma: no cover
1091+
return p.replace("(", "[").replace(")",
1092+
"]").replace(" ", "_")
1093+
1094+
renamed_debug_geometric_predicates = [
1095+
rename(p) for p in _DEBUG_GEOMETRIC_PREDICATES[CFG.env]
1096+
]
10481097
debug_predicate_names = _DEBUG_VLM_PREDICATES[
1049-
CFG.env] + _DEBUG_GEOMETRIC_PREDICATES[CFG.env]
1098+
CFG.env] + renamed_debug_geometric_predicates
10501099
self._learned_predicates = set(
10511100
p for p in candidates.keys()
10521101
if p.name in debug_predicate_names)
@@ -1066,21 +1115,21 @@ def learn_from_offline_dataset(self, dataset: Dataset) -> None:
10661115
elif CFG.grammar_search_pred_selection_approach == "no_select":
10671116
self._learned_predicates = set(candidates.keys())
10681117
logging.info("Done.")
1069-
# Now, rename these predicates to be compatible with PDDL planners!
1070-
renamed_predicates: Set[Predicate] = set()
1071-
for p in self._learned_predicates:
1072-
if isinstance(p, VLMPredicate): # pragma: no cover.
1073-
renamed_predicates.add(p)
1074-
continue
1075-
new_name = p.name.replace("(", "[").replace(")",
1076-
"]").replace(" ", "_")
1077-
renamed_pred = Predicate(new_name, p.types, p._classifier) # pylint:disable=protected-access
1078-
renamed_predicates.add(renamed_pred)
1079-
self._learned_predicates = renamed_predicates
10801118
# Finally, learn NSRTs via superclass, using all the kept predicates.
10811119
annotations = None
10821120
if dataset.has_annotations:
1083-
annotations = dataset.annotations
1121+
if CFG.offline_data_method in [
1122+
"geo_and_demo_with_vlm_imgs",
1123+
"geo_and_demo+labelled_atoms",
1124+
"geo_and_saved_vlm_img_demos_folder"
1125+
]:
1126+
# IMPORTANT: in this case, we need to make sure the dataset
1127+
# annotations include the geo predicates as well as the VLM
1128+
# predicates, so we need to set the annotations to the generated
1129+
# atom_dataset and not just the dataset.annotations.
1130+
annotations = [atoms_data[1] for atoms_data in atom_dataset]
1131+
else:
1132+
annotations = dataset.annotations
10841133
self._learn_nsrts(dataset.trajectories,
10851134
online_learning_cycle=None,
10861135
annotations=annotations)
@@ -1119,10 +1168,12 @@ def _get_successors(
11191168
_check_goal,
11201169
_get_successors,
11211170
score_function.evaluate,
1171+
early_termination_heuristic_thresh=CFG.
1172+
grammar_search_early_termination_heuristic_thresh,
11221173
enforced_depth=CFG.grammar_search_hill_climbing_depth,
11231174
parallelize=CFG.grammar_search_parallelize_hill_climbing)
11241175
logging.info("\nHill climbing summary:")
1125-
for i in range(1, len(path)):
1176+
for i in range(1, len(path)): # pragma: no cover
11261177
new_additions = path[i] - path[i - 1]
11271178
assert len(new_additions) == 1
11281179
new_addition = next(iter(new_additions))
@@ -1178,7 +1229,7 @@ def _get_successors(
11781229

11791230
logging.info(f"\nSelected {len(kept_predicates)} predicates out of "
11801231
f"{len(candidates)} candidates:")
1181-
for pred in kept_predicates:
1232+
for pred in kept_predicates: # pragma: no cover
11821233
logging.info(f"\t{pred}")
11831234
score_function.evaluate(kept_predicates) # log useful numbers
11841235

predicators/approaches/nsrt_learning_approach.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def load(self, online_learning_cycle: Optional[int]) -> None:
119119
save_path = utils.get_approach_load_path_str()
120120
with open(f"{save_path}_{online_learning_cycle}.NSRTs", "rb") as f:
121121
self._nsrts = pkl.load(f)
122-
if CFG.pretty_print_when_loading:
122+
if CFG.pretty_print_when_loading: # pragma: no cover
123123
preds, _ = utils.extract_preds_and_types(self._nsrts)
124124
name_map = {}
125125
logging.info("Invented predicates:")

0 commit comments

Comments
 (0)