From efa696f1aa82f8585afc7fbf5b982bf1a6b1ed1c Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Mon, 19 Jun 2023 11:13:15 -0400 Subject: [PATCH 01/18] More in depth debugging. --- macq/extract/locm.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 9042fa5f..25781540 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -216,7 +216,12 @@ def __new__( sorts = LOCM._get_sorts(obs_trace, debug=debug["get_sorts"]) if debug["sorts"]: - print(f"Sorts:\n{sorts}", end="\n\n") + sortid2objs = {v: [] for v in set(sorts.values())} + for k,v in sorts.items(): + sortid2objs[v].append(k) + print("\nSorts:\n") + pprint(sortid2objs) + print("\n") TS, ap_state_pointers, OS = LOCM._step1(obs_trace, sorts, debug["step1"]) HS = LOCM._step3(TS, ap_state_pointers, OS, sorts, debug["step3"]) @@ -422,9 +427,10 @@ def _step1( ap_state_pointers = defaultdict(dict) # iterate over each object and its action sequence for obj, seq in obj_traces.items(): - state_n = 1 # count current (new) state id sort = sorts[obj.name] if obj != zero_obj else 0 TS[sort][obj] = seq # add the sequence to the transition set + # max of the states already in OS[sort], plus 1 + state_n = max([max(s) for s in OS[sort]] + [0]) + 1 # count current (new) state id prev_states: StatePointers = None # type: ignore # iterate over each transition A.P in the sequence for ap in seq: @@ -453,6 +459,7 @@ def _step1( OS[sort][prev_end_state] ) OS[sort].pop(prev_end_state) + assert len(set.union(*OS[sort])) == sum([len(s) for s in OS[sort]]) prev_states = ap_states @@ -711,6 +718,26 @@ def _step7( del ap_state_pointers[0] if debug: + import networkx as nx + import os + + for sort in OS: + # multigraph + G = nx.DiGraph() + N = len(OS[sort]) + for ap, apstate in ap_state_pointers[sort].items(): + start_idx, end_idx = LOCM._pointer_to_set(OS[sort], apstate.start, apstate.end) + # check if edge is already in graph + if G.has_edge(start_idx, end_idx): + # append to the edge label + G.edges[start_idx, end_idx]["label"] += f"\n{ap.action.name}.{ap.pos}" + else: + G.add_edge(start_idx, end_idx, label=f"{ap.action.name}.{ap.pos}") + # write to dot file + nx.drawing.nx_pydot.write_dot(G, f"LOCM-step7-sort{sort}.dot") + os.system(f"dot -Tpng LOCM-step7-sort{sort}.dot -o LOCM-step7-sort{sort}.png") + os.system(f"rm LOCM-step7-sort{sort}.dot") + print("ap state pointers") pprint(ap_state_pointers) print() @@ -719,9 +746,9 @@ def _step7( pprint(OS) print() - print("bindings:") - pprint(bindings) - print() + # print("bindings:") + # pprint(bindings) + # print() bound_param_sorts = { sort: { From 3b9f0ef51b35d62044dc3e15f9fb078af6123f06 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Mon, 19 Jun 2023 16:20:02 -0400 Subject: [PATCH 02/18] Work in progress, with a couple of bugs fixed. --- macq/extract/locm.py | 68 +++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 25781540..29e6ab5a 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -25,7 +25,7 @@ class AP: sort: int def __repr__(self) -> str: - return f"{self.action.name}.{self.pos}" + return f"{self.action.name}.{self.pos} [sort{self.sort}]" def __hash__(self): return hash(self.action.name + str(self.pos)) @@ -131,10 +131,10 @@ def __hash__(self) -> int: ) def __repr__(self) -> str: - out = "<\n" - for k, v in asdict(self).items(): - out += f" {k}={v}\n" - return out.strip() + "\n>" + out = f"\n [->B->S->C->] = ({str(self.B)}) -> {str(self.S)} -> ({str(self.C)})" + out += "\n\tG\tG'\tS\tk\tk'\tl\tl'" + out += "\n\t" + str(self.G) + "\t" + str(self.G_) + "\t" + str(self.S) + "\t" + str(self.k) + "\t" + str(self.k_) + "\t" + str(self.l) + "\t" + str(self.l_) + "\n" + return out @staticmethod def from_dict( @@ -555,7 +555,7 @@ def _step3( # Remove any unsupported hypotheses (but yet undisputed) for hind, hs in HS.copy().items(): - for h in hs: + for h in hs.copy(): if not h.supported: hs.remove(h) if len(hs) == 0: @@ -569,7 +569,6 @@ def _step4( HS: Dict[int, Dict[int, Set[Hypothesis]]], debug: bool = False ) -> Bindings: """Step 4: Creation and merging of state parameters""" - # bindings = {sort: {state: [(hypothesis, state param)]}} bindings: Bindings = defaultdict(dict) for sort, hs_sort in HS.items(): @@ -671,7 +670,7 @@ def get_state_machines( state_machines = [] for (sort, trans), states in zip(ap_state_pointers.items(), OS.values()): - graph = Digraph(f"LOCM-step1-sort{sort}") + graph = Digraph(f"LOCM-sort{sort}") for state in range(len(states)): label = f"state{state}" if ( @@ -722,9 +721,21 @@ def _step7( import os for sort in OS: - # multigraph G = nx.DiGraph() - N = len(OS[sort]) + for n in range(len(OS[sort])): + lbl = f"state{n}" + if ( + bindings is not None + and sort in bindings + and n in bindings[sort] + ): + lbl += f"\n[" + params = [] + for binding in bindings[sort][n]: + params.append(f"{binding.hypothesis.G_}") + lbl += f",".join(params) + lbl += f"]" + G.add_node(n, label=lbl, shape="oval") for ap, apstate in ap_state_pointers[sort].items(): start_idx, end_idx = LOCM._pointer_to_set(OS[sort], apstate.start, apstate.end) # check if edge is already in graph @@ -748,7 +759,7 @@ def _step7( # print("bindings:") # pprint(bindings) - # print() + bound_param_sorts = { sort: { @@ -764,15 +775,31 @@ def _step7( actions = {} fluents = defaultdict(dict) - all_aps: Dict[str, List[AP]] = defaultdict(list) + all_aps: Dict[str, Dict[int, AP]] = defaultdict(defaultdict) for aps in ap_state_pointers.values(): for ap in aps: - all_aps[ap.action.name].append(ap) + all_aps[ap.action.name][ap.pos] = ap for action, aps in all_aps.items(): + assert len(aps) == max(aps.keys()) actions[action] = LearnedLiftedAction( - action, [f"sort{ap.sort}" for ap in aps] + action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] ) + + for sort in bindings: + for state in bindings[sort]: + for binding in bindings[sort][state]: + hyp = binding.hypothesis + # assertions on the binding + assert hyp.G_ != hyp.G + assert hyp.k == hyp.B.pos + assert hyp.l == hyp.C.pos + assert hyp.k_ > 0 + assert hyp.l_ > 0 + assert hyp.k > 0 + assert hyp.l > 0 + assert actions[hyp.B.action.name].param_sorts[hyp.B.pos-1] == f"sort{hyp.B.sort}", f"Action:\n{actions[hyp.B.action.name]}\nHypothesis:\n{hyp}" + assert actions[hyp.C.action.name].param_sorts[hyp.C.pos-1] == f"sort{hyp.C.sort}", f"Action:\n{actions[hyp.C.action.name]}\nHypothesis:\n{hyp}" @dataclass class TemplateFluent: @@ -781,14 +808,16 @@ class TemplateFluent: def __hash__(self) -> int: return hash(self.name + "".join(self.param_sorts)) - + for sort, state_bindings in bound_param_sorts.items(): for state, bound_sorts in state_bindings.items(): fluents[sort][state] = TemplateFluent( f"sort{sort}_state{state}", [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], ) + assert sort not in bound_sorts + assert len(ap_state_pointers) == len(OS) for (sort, aps), states in zip(ap_state_pointers.items(), OS.values()): for ap, pointers in aps.items(): start_state, end_state = LOCM._pointer_to_set( @@ -845,6 +874,13 @@ def __hash__(self) -> int: if debug: pprint(fluents) - pprint(actions) + + for a in actions: + print(a) + print(a.precond) + print(a.delete) + print(a.add) + print() + return fluents, actions From 9a4a1cf79f6966dd36ba56a8e8595bbbffe218ef Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 20:39:05 -0400 Subject: [PATCH 03/18] Debug changes [wip] --- macq/extract/learned_fluent.py | 2 +- macq/extract/locm.py | 120 +++++++++++++++++++++++---------- macq/extract/model.py | 37 ++++++++-- 3 files changed, 114 insertions(+), 45 deletions(-) diff --git a/macq/extract/learned_fluent.py b/macq/extract/learned_fluent.py index 59e2c1c6..37305a2c 100644 --- a/macq/extract/learned_fluent.py +++ b/macq/extract/learned_fluent.py @@ -50,7 +50,7 @@ def __hash__(self): return hash(self.details()) def __str__(self): - return self.details() + return self.details() + f" {self.param_act_inds}" def __repr__(self): return self.details() diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 29e6ab5a..a642ae4c 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -106,6 +106,7 @@ class Hypothesis: another argument of the same sort G′ in position k′ and l′ respectively, we hypothesise that there may be a relation between sorts G and G′." """ + S: int B: AP k: int @@ -131,9 +132,25 @@ def __hash__(self) -> int: ) def __repr__(self) -> str: - out = f"\n [->B->S->C->] = ({str(self.B)}) -> {str(self.S)} -> ({str(self.C)})" + out = f"\n [->B->S->C->] = ({str(self.B)}) -> {str(self.S)} -> ({str(self.C)})" out += "\n\tG\tG'\tS\tk\tk'\tl\tl'" - out += "\n\t" + str(self.G) + "\t" + str(self.G_) + "\t" + str(self.S) + "\t" + str(self.k) + "\t" + str(self.k_) + "\t" + str(self.l) + "\t" + str(self.l_) + "\n" + out += ( + "\n\t" + + str(self.G) + + "\t" + + str(self.G_) + + "\t" + + str(self.S) + + "\t" + + str(self.k) + + "\t" + + str(self.k_) + + "\t" + + str(self.l) + + "\t" + + str(self.l_) + + "\n" + ) return out @staticmethod @@ -217,7 +234,7 @@ def __new__( if debug["sorts"]: sortid2objs = {v: [] for v in set(sorts.values())} - for k,v in sorts.items(): + for k, v in sorts.items(): sortid2objs[v].append(k) print("\nSorts:\n") pprint(sortid2objs) @@ -430,7 +447,9 @@ def _step1( sort = sorts[obj.name] if obj != zero_obj else 0 TS[sort][obj] = seq # add the sequence to the transition set # max of the states already in OS[sort], plus 1 - state_n = max([max(s) for s in OS[sort]] + [0]) + 1 # count current (new) state id + state_n = ( + max([max(s) for s in OS[sort]] + [0]) + 1 + ) # count current (new) state id prev_states: StatePointers = None # type: ignore # iterate over each transition A.P in the sequence for ap in seq: @@ -565,9 +584,7 @@ def _step3( return Hypothesis.from_dict(HS) @staticmethod - def _step4( - HS: Dict[int, Dict[int, Set[Hypothesis]]], debug: bool = False - ) -> Bindings: + def _step4(HS: Hypotheses, debug: bool = False) -> Bindings: """Step 4: Creation and merging of state parameters""" # bindings = {sort: {state: [(hypothesis, state param)]}} bindings: Bindings = defaultdict(dict) @@ -615,6 +632,10 @@ def _step4( state_params.pop(P2) state_param_pointers[v2] = P1 + # fix state_param_pointers after v2 + for ind in range(v2 + 1, len(state_param_pointers)): + state_param_pointers[ind] -= 1 + # add state bindings for the sort to the output bindings # replacing hypothesis params with actual state params bindings[sort][state] = [ @@ -626,7 +647,7 @@ def _step4( @staticmethod def _step5( - HS: Dict[int, Dict[int, Set[Hypothesis]]], + HS: Hypotheses, bindings: Bindings, debug: bool = False, ) -> Bindings: @@ -634,12 +655,12 @@ def _step5( # check each bindings[G][S] -> (h, P) for sort, hs_sort in HS.items(): - for state in hs_sort: + for state_id in hs_sort: # track all the h.Bs that occur in bindings[G][S] all_hB = set() # track the set of h.B that set parameter P sets_P = defaultdict(set) - for h, P in bindings[sort][state]: + for h, P in bindings[sort][state_id]: sets_P[P].add(h.B) all_hB.add(h.B) @@ -648,11 +669,11 @@ def _step5( for P, setby in sets_P.items(): if not setby == all_hB: # P is a flawed parameter # remove all bindings referencing P - for h, P_ in bindings[sort][state].copy(): + for h, P_ in bindings[sort][state_id].copy(): if P_ == P: - bindings[sort][state].remove(Binding(h, P_)) - if len(bindings[sort][state]) == 0: - del bindings[sort][state] + bindings[sort][state_id].remove(Binding(h, P_)) + if len(bindings[sort][state_id]) == 0: + del bindings[sort][state_id] for k, v in bindings.copy().items(): if not v: @@ -717,9 +738,10 @@ def _step7( del ap_state_pointers[0] if debug: - import networkx as nx import os + import networkx as nx + for sort in OS: G = nx.DiGraph() for n in range(len(OS[sort])): @@ -737,16 +759,24 @@ def _step7( lbl += f"]" G.add_node(n, label=lbl, shape="oval") for ap, apstate in ap_state_pointers[sort].items(): - start_idx, end_idx = LOCM._pointer_to_set(OS[sort], apstate.start, apstate.end) + start_idx, end_idx = LOCM._pointer_to_set( + OS[sort], apstate.start, apstate.end + ) # check if edge is already in graph if G.has_edge(start_idx, end_idx): # append to the edge label - G.edges[start_idx, end_idx]["label"] += f"\n{ap.action.name}.{ap.pos}" + G.edges[start_idx, end_idx][ + "label" + ] += f"\n{ap.action.name}.{ap.pos}" else: - G.add_edge(start_idx, end_idx, label=f"{ap.action.name}.{ap.pos}") + G.add_edge( + start_idx, end_idx, label=f"{ap.action.name}.{ap.pos}" + ) # write to dot file nx.drawing.nx_pydot.write_dot(G, f"LOCM-step7-sort{sort}.dot") - os.system(f"dot -Tpng LOCM-step7-sort{sort}.dot -o LOCM-step7-sort{sort}.png") + os.system( + f"dot -Tpng LOCM-step7-sort{sort}.dot -o LOCM-step7-sort{sort}.png" + ) os.system(f"rm LOCM-step7-sort{sort}.dot") print("ap state pointers") @@ -757,9 +787,8 @@ def _step7( pprint(OS) print() - # print("bindings:") - # pprint(bindings) - + print("bindings:") + pprint(bindings) bound_param_sorts = { sort: { @@ -785,7 +814,7 @@ def _step7( actions[action] = LearnedLiftedAction( action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] ) - + for sort in bindings: for state in bindings[sort]: for binding in bindings[sort][state]: @@ -798,8 +827,14 @@ def _step7( assert hyp.l_ > 0 assert hyp.k > 0 assert hyp.l > 0 - assert actions[hyp.B.action.name].param_sorts[hyp.B.pos-1] == f"sort{hyp.B.sort}", f"Action:\n{actions[hyp.B.action.name]}\nHypothesis:\n{hyp}" - assert actions[hyp.C.action.name].param_sorts[hyp.C.pos-1] == f"sort{hyp.C.sort}", f"Action:\n{actions[hyp.C.action.name]}\nHypothesis:\n{hyp}" + assert ( + actions[hyp.B.action.name].param_sorts[hyp.B.pos - 1] + == f"sort{hyp.B.sort}" + ), f"Action:\n{actions[hyp.B.action.name]}\nHypothesis:\n{hyp}" + assert ( + actions[hyp.C.action.name].param_sorts[hyp.C.pos - 1] + == f"sort{hyp.C.sort}" + ), f"Action:\n{actions[hyp.C.action.name]}\nHypothesis:\n{hyp}" @dataclass class TemplateFluent: @@ -808,13 +843,16 @@ class TemplateFluent: def __hash__(self) -> int: return hash(self.name + "".join(self.param_sorts)) - + for sort, state_bindings in bound_param_sorts.items(): for state, bound_sorts in state_bindings.items(): - fluents[sort][state] = TemplateFluent( - f"sort{sort}_state{state}", - [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], - ) + fluents[sort][state] = { + "temp": TemplateFluent( + f"sort{sort}_state{state}", + [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], + ), + "learned": [], + } assert sort not in bound_sorts assert len(ap_state_pointers) == len(OS) @@ -825,12 +863,15 @@ def __hash__(self) -> int: ) # preconditions += fluent for origin state - start_fluent_temp = fluents[sort][start_state] + start_fluent_temp = fluents[sort][start_state]["temp"] bound_param_inds = [] # for each bindings on the start state (if there are any) # then add each binding.hypothesis.l_ + + # no check h.C == AP.a // l == AP.pos + # so could be adding l' binds from other actions coming into same state if sort in bindings and start_state in bindings[sort]: bound_param_inds = [ b.hypothesis.l_ - 1 for b in bindings[sort][start_state] @@ -841,7 +882,7 @@ def __hash__(self) -> int: start_fluent_temp.param_sorts, [ap.pos - 1] + bound_param_inds, ) - fluents[sort][start_state] = start_fluent + fluents[sort][start_state]["learned"].append(start_fluent) actions[ap.action.name].update_precond(start_fluent) if start_state != end_state: @@ -849,7 +890,7 @@ def __hash__(self) -> int: actions[ap.action.name].update_delete(start_fluent) # add += fluent for destination state - end_fluent_temp = fluents[sort][end_state] + end_fluent_temp = fluents[sort][end_state]["temp"] bound_param_inds = [] if sort in bindings and end_state in bindings[sort]: bound_param_inds = [ @@ -860,10 +901,15 @@ def __hash__(self) -> int: end_fluent_temp.param_sorts, [ap.pos - 1] + bound_param_inds, ) - fluents[sort][end_state] = end_fluent + fluents[sort][end_state]["learned"].append(end_fluent) actions[ap.action.name].update_add(end_fluent) - fluents = set(fluent for sort in fluents.values() for fluent in sort.values()) + fluents = set( + fluent + for sort in fluents.values() + for fluents in sort.values() + for fluent in fluents["learned"] + ) actions = set(actions.values()) # Step 6: Extraction of static preconditions @@ -874,7 +920,8 @@ def __hash__(self) -> int: if debug: pprint(fluents) - + assert all([type(f) == LearnedLiftedFluent for f in fluents]) + for a in actions: print(a) print(a.precond) @@ -882,5 +929,4 @@ def __hash__(self) -> int: print(a.add) print() - return fluents, actions diff --git a/macq/extract/model.py b/macq/extract/model.py index 6c4d7180..0b74be0b 100644 --- a/macq/extract/model.py +++ b/macq/extract/model.py @@ -189,6 +189,8 @@ def to_pddl_lifted( sorts = set() if self.fluents: + print("self.fluents") + print(self.fluents) for f in self.fluents: for sort in f.param_sorts: if sort not in sorts: @@ -198,19 +200,40 @@ def to_pddl_lifted( lang.predicate(f.name, *f.param_sorts) if self.actions: + # for each action for a in self.actions: + print("a") + print(a) + print("a.param_sorts") + print(a.param_sorts) + print("a.precond") + print(a.precond) vars = [lang.variable(f"x{i}", s) for i, s in enumerate(a.param_sorts)] + print("vars") + print(vars) if len(a.precond) == 1: precond = lang.get(list(a.precond)[0].name)(*[vars[i] for i in a.precond[0].param_act_inds]) # type: ignore else: - precond = CompoundFormula( - Connective.And, - [ - lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) # type: ignore - for f in a.precond - ], - ) + # precond = CompoundFormula( + # Connective.And, + # [ + # lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) # type: ignore + # for f in a.precond + # ], + # ) + print() + + precond = [] + for f in a.precond: + print("f") + print(f) + print("f.name") + print(f.name) + print("f.param_act_inds") + print(f.param_act_inds) + precond.append(lang.get(f.name)(*[vars[i] for i in f.param_act_inds])) # type: ignore + precond = CompoundFormula(Connective.And, precond) adds = [lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) for f in a.add] # type: ignore dels = [lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) for f in a.delete] # type: ignore From b9e4b09905b40574a466dc956bcc9074e9e7ca60 Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 21:15:40 -0400 Subject: [PATCH 04/18] Start working on step 7 from scratch --- macq/extract/locm.py | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index a642ae4c..beae1df5 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -930,3 +930,69 @@ def __hash__(self) -> int: print() return fluents, actions + + @staticmethod + def _step7_wip( + OS: OSType, + ap_state_pointers: APStatePointers, + sorts: Sorts, + bindings: Bindings, + statics: Statics, + debug: bool = False, + ) -> Tuple[Set[LearnedLiftedFluent], Set[LearnedLiftedAction]]: + """Step 7: Formation of PDDL action schema + Implicitly includes Step 6 (statics) by including statics as an argument + and adding to the relevant actions while being constructed. + """ + + # delete zero-object if it's state machine was discarded + if not OS[0]: + del OS[0] + del ap_state_pointers[0] + + # all_aps = {action_name: [AP]} + all_aps: Dict[str, List[AP]] = defaultdict(list) + for aps in ap_state_pointers.values(): + for ap in aps: + all_aps[ap.action.name].append(ap) + + # for action, aps in all_aps.items(): + # assert len(aps) == max(aps.keys()) + # actions[action] = LearnedLiftedAction( + # action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] + # ) + + actions = {} + for sort in ap_state_pointers: + sort_str = f"sort{sort}" + for ap in ap_state_pointers[sort]: + if ap.action.name not in actions: + actions[ap.action.name] = LearnedLiftedAction( + ap.action.name, + [None for _ in range(len(all_aps[ap.action.name]))], # type: ignore + ) + a = actions[ap.action.name] + a.param_sorts[ap.pos - 1] = sort_str + + start_pointer, end_pointer = ap_state_pointers[sort][ap] + start_state, end_state = LOCM._pointer_to_set( + OS[sort], start_pointer, end_pointer + ) + + """ + fluents[sort][state] = { + "temp": TemplateFluent( + f"sort{sort}_state{state}", + [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], + ), + "learned": [], + """ + + start_fluent = LearnedLiftedFluent( + f"sort{sort}_state{start_state}", + [sort_str], + [ap.pos - 1], + ) + for binding in bindings[sort][start_state]: + if binding.hypothesis.C == ap: + pass From 207c008cad71073d0159ea009c83502a75082f2d Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 21:17:21 -0400 Subject: [PATCH 05/18] no syntax error --- macq/extract/locm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index beae1df5..0f9858c1 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -995,4 +995,4 @@ def _step7_wip( ) for binding in bindings[sort][start_state]: if binding.hypothesis.C == ap: - pass + pass From 511beb9e0daa4cfd36cb242e0c50a33f122e4d7d Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 22:01:27 -0400 Subject: [PATCH 06/18] Rewrite step 7 --- macq/extract/locm.py | 77 +++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 0f9858c1..30f751d9 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -719,7 +719,7 @@ def get_state_machines( return state_machines @staticmethod - def _step7( + def _step7_old( OS: OSType, ap_state_pointers: APStatePointers, sorts: Sorts, @@ -932,7 +932,7 @@ def __hash__(self) -> int: return fluents, actions @staticmethod - def _step7_wip( + def _step7( OS: OSType, ap_state_pointers: APStatePointers, sorts: Sorts, @@ -962,6 +962,7 @@ def _step7_wip( # action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] # ) + fluents = defaultdict(dict) actions = {} for sort in ap_state_pointers: sort_str = f"sort{sort}" @@ -979,20 +980,60 @@ def _step7_wip( OS[sort], start_pointer, end_pointer ) - """ - fluents[sort][state] = { - "temp": TemplateFluent( - f"sort{sort}_state{state}", - [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], - ), - "learned": [], - """ + start_fluent_name = f"sort{sort}_state{start_state}_{ap.action.name}" + if start_fluent_name not in fluents[ap.action.name]: + start_fluent = LearnedLiftedFluent( + start_fluent_name, + param_sorts=[sort_str], + param_act_inds=[ap.pos - 1], + ) + fluents[ap.action.name][start_fluent_name] = start_fluent - start_fluent = LearnedLiftedFluent( - f"sort{sort}_state{start_state}", - [sort_str], - [ap.pos - 1], - ) - for binding in bindings[sort][start_state]: - if binding.hypothesis.C == ap: - pass + start_fluent = fluents[ap.action.name][start_fluent_name] + if sort in bindings and start_state in bindings[sort]: + for binding in bindings[sort][start_state]: + if binding.hypothesis.C == ap: + start_fluent.param_sorts.append( + f"sort{binding.hypothesis.G_}" + ) + start_fluent.param_act_inds.append( + binding.hypothesis.l_ - 1 + ) + + a.update_precond(start_fluent) + + if end_state != start_state: + end_fluent_name = f"sort{sort}_state{end_state}_{ap.action.name}" + if end_fluent_name not in fluents[ap.action.name]: + end_fluent = LearnedLiftedFluent( + end_fluent_name, + param_sorts=[sort_str], + param_act_inds=[ap.pos - 1], + ) + fluents[ap.action.name][end_fluent_name] = end_fluent + + end_fluent = fluents[ap.action.name][end_fluent_name] + if sort in bindings and end_state in bindings[sort]: + for binding in bindings[sort][end_state]: + if binding.hypothesis.B == ap: + end_fluent.param_sorts.append( + f"sort{binding.hypothesis.G_}" + ) + end_fluent.param_act_inds.append( + binding.hypothesis.k_ - 1 + ) + + a.update_delete(start_fluent) + a.update_add(end_fluent) + + # Step 6: Extraction of static preconditions + for action in actions.values(): + if action.name in statics: + for static in statics[action.name]: + action.update_precond(static) + + return set( + fluent + for action_fluents in fluents.values() + for fluent in action_fluents.values() + ), set(actions.values()) From 96230fd3f3b4328e4b5e603cd9bf19c26a27786b Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 22:16:42 -0400 Subject: [PATCH 07/18] Clean up tarski translation prints --- macq/extract/model.py | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/macq/extract/model.py b/macq/extract/model.py index 0b74be0b..0ec9cf80 100644 --- a/macq/extract/model.py +++ b/macq/extract/model.py @@ -200,40 +200,19 @@ def to_pddl_lifted( lang.predicate(f.name, *f.param_sorts) if self.actions: - # for each action for a in self.actions: - print("a") - print(a) - print("a.param_sorts") - print(a.param_sorts) - print("a.precond") - print(a.precond) vars = [lang.variable(f"x{i}", s) for i, s in enumerate(a.param_sorts)] - print("vars") - print(vars) if len(a.precond) == 1: precond = lang.get(list(a.precond)[0].name)(*[vars[i] for i in a.precond[0].param_act_inds]) # type: ignore else: - # precond = CompoundFormula( - # Connective.And, - # [ - # lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) # type: ignore - # for f in a.precond - # ], - # ) - print() - - precond = [] - for f in a.precond: - print("f") - print(f) - print("f.name") - print(f.name) - print("f.param_act_inds") - print(f.param_act_inds) - precond.append(lang.get(f.name)(*[vars[i] for i in f.param_act_inds])) # type: ignore - precond = CompoundFormula(Connective.And, precond) + precond = CompoundFormula( + Connective.And, + [ + lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) # type: ignore + for f in a.precond + ], + ) adds = [lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) for f in a.add] # type: ignore dels = [lang.get(f.name)(*[vars[i] for i in f.param_act_inds]) for f in a.delete] # type: ignore From d1058d199d945eee17f600fbaac41a7f0f7bcf98 Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 22:29:34 -0400 Subject: [PATCH 08/18] Remove old step 7 --- macq/extract/locm.py | 81 +++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 30f751d9..e3c2b07e 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -718,6 +718,43 @@ def get_state_machines( return state_machines + @staticmethod + def _debug_state_machines(OS, ap_state_pointers, bindings): + import os + + import networkx as nx + + for sort in OS: + G = nx.DiGraph() + for n in range(len(OS[sort])): + lbl = f"state{n}" + if bindings is not None and sort in bindings and n in bindings[sort]: + lbl += f"\n[" + params = [] + for binding in bindings[sort][n]: + params.append(f"{binding.hypothesis.G_}") + lbl += f",".join(params) + lbl += f"]" + G.add_node(n, label=lbl, shape="oval") + for ap, apstate in ap_state_pointers[sort].items(): + start_idx, end_idx = LOCM._pointer_to_set( + OS[sort], apstate.start, apstate.end + ) + # check if edge is already in graph + if G.has_edge(start_idx, end_idx): + # append to the edge label + G.edges[start_idx, end_idx][ + "label" + ] += f"\n{ap.action.name}.{ap.pos}" + else: + G.add_edge(start_idx, end_idx, label=f"{ap.action.name}.{ap.pos}") + # write to dot file + nx.drawing.nx_pydot.write_dot(G, f"LOCM-step7-sort{sort}.dot") + os.system( + f"dot -Tpng LOCM-step7-sort{sort}.dot -o LOCM-step7-sort{sort}.png" + ) + os.system(f"rm LOCM-step7-sort{sort}.dot") + @staticmethod def _step7_old( OS: OSType, @@ -731,54 +768,14 @@ def _step7_old( Implicitly includes Step 6 (statics) by including statics as an argument and adding to the relevant actions while being constructed. """ + if debug: + LOCM._debug_state_machines(OS, ap_state_pointers, bindings) # delete zero-object if it's state machine was discarded if not OS[0]: del OS[0] del ap_state_pointers[0] - if debug: - import os - - import networkx as nx - - for sort in OS: - G = nx.DiGraph() - for n in range(len(OS[sort])): - lbl = f"state{n}" - if ( - bindings is not None - and sort in bindings - and n in bindings[sort] - ): - lbl += f"\n[" - params = [] - for binding in bindings[sort][n]: - params.append(f"{binding.hypothesis.G_}") - lbl += f",".join(params) - lbl += f"]" - G.add_node(n, label=lbl, shape="oval") - for ap, apstate in ap_state_pointers[sort].items(): - start_idx, end_idx = LOCM._pointer_to_set( - OS[sort], apstate.start, apstate.end - ) - # check if edge is already in graph - if G.has_edge(start_idx, end_idx): - # append to the edge label - G.edges[start_idx, end_idx][ - "label" - ] += f"\n{ap.action.name}.{ap.pos}" - else: - G.add_edge( - start_idx, end_idx, label=f"{ap.action.name}.{ap.pos}" - ) - # write to dot file - nx.drawing.nx_pydot.write_dot(G, f"LOCM-step7-sort{sort}.dot") - os.system( - f"dot -Tpng LOCM-step7-sort{sort}.dot -o LOCM-step7-sort{sort}.png" - ) - os.system(f"rm LOCM-step7-sort{sort}.dot") - print("ap state pointers") pprint(ap_state_pointers) print() From 657b5c309e727ca0391fb4bd00682101dd843d31 Mon Sep 17 00:00:00 2001 From: ecal Date: Tue, 20 Jun 2023 22:31:58 -0400 Subject: [PATCH 09/18] Remove old step 7 --- macq/extract/locm.py | 173 +------------------------------------------ 1 file changed, 1 insertion(+), 172 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index e3c2b07e..8092987a 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -756,7 +756,7 @@ def _debug_state_machines(OS, ap_state_pointers, bindings): os.system(f"rm LOCM-step7-sort{sort}.dot") @staticmethod - def _step7_old( + def _step7( OS: OSType, ap_state_pointers: APStatePointers, sorts: Sorts, @@ -771,177 +771,6 @@ def _step7_old( if debug: LOCM._debug_state_machines(OS, ap_state_pointers, bindings) - # delete zero-object if it's state machine was discarded - if not OS[0]: - del OS[0] - del ap_state_pointers[0] - - print("ap state pointers") - pprint(ap_state_pointers) - print() - - print("OS:") - pprint(OS) - print() - - print("bindings:") - pprint(bindings) - - bound_param_sorts = { - sort: { - state: [ - binding.hypothesis.G_ - for binding in bindings.get(sort, {}).get(state, []) - ] - for state in range(len(states)) - } - for sort, states in OS.items() - } - - actions = {} - fluents = defaultdict(dict) - - all_aps: Dict[str, Dict[int, AP]] = defaultdict(defaultdict) - for aps in ap_state_pointers.values(): - for ap in aps: - all_aps[ap.action.name][ap.pos] = ap - - for action, aps in all_aps.items(): - assert len(aps) == max(aps.keys()) - actions[action] = LearnedLiftedAction( - action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] - ) - - for sort in bindings: - for state in bindings[sort]: - for binding in bindings[sort][state]: - hyp = binding.hypothesis - # assertions on the binding - assert hyp.G_ != hyp.G - assert hyp.k == hyp.B.pos - assert hyp.l == hyp.C.pos - assert hyp.k_ > 0 - assert hyp.l_ > 0 - assert hyp.k > 0 - assert hyp.l > 0 - assert ( - actions[hyp.B.action.name].param_sorts[hyp.B.pos - 1] - == f"sort{hyp.B.sort}" - ), f"Action:\n{actions[hyp.B.action.name]}\nHypothesis:\n{hyp}" - assert ( - actions[hyp.C.action.name].param_sorts[hyp.C.pos - 1] - == f"sort{hyp.C.sort}" - ), f"Action:\n{actions[hyp.C.action.name]}\nHypothesis:\n{hyp}" - - @dataclass - class TemplateFluent: - name: str - param_sorts: List[str] - - def __hash__(self) -> int: - return hash(self.name + "".join(self.param_sorts)) - - for sort, state_bindings in bound_param_sorts.items(): - for state, bound_sorts in state_bindings.items(): - fluents[sort][state] = { - "temp": TemplateFluent( - f"sort{sort}_state{state}", - [f"sort{sort}"] + [f"sort{s}" for s in bound_sorts], - ), - "learned": [], - } - assert sort not in bound_sorts - - assert len(ap_state_pointers) == len(OS) - for (sort, aps), states in zip(ap_state_pointers.items(), OS.values()): - for ap, pointers in aps.items(): - start_state, end_state = LOCM._pointer_to_set( - states, pointers.start, pointers.end - ) - - # preconditions += fluent for origin state - start_fluent_temp = fluents[sort][start_state]["temp"] - - bound_param_inds = [] - - # for each bindings on the start state (if there are any) - # then add each binding.hypothesis.l_ - - # no check h.C == AP.a // l == AP.pos - # so could be adding l' binds from other actions coming into same state - if sort in bindings and start_state in bindings[sort]: - bound_param_inds = [ - b.hypothesis.l_ - 1 for b in bindings[sort][start_state] - ] - - start_fluent = LearnedLiftedFluent( - start_fluent_temp.name, - start_fluent_temp.param_sorts, - [ap.pos - 1] + bound_param_inds, - ) - fluents[sort][start_state]["learned"].append(start_fluent) - actions[ap.action.name].update_precond(start_fluent) - - if start_state != end_state: - # del += fluent for origin state - actions[ap.action.name].update_delete(start_fluent) - - # add += fluent for destination state - end_fluent_temp = fluents[sort][end_state]["temp"] - bound_param_inds = [] - if sort in bindings and end_state in bindings[sort]: - bound_param_inds = [ - b.hypothesis.l_ - 1 for b in bindings[sort][end_state] - ] - end_fluent = LearnedLiftedFluent( - end_fluent_temp.name, - end_fluent_temp.param_sorts, - [ap.pos - 1] + bound_param_inds, - ) - fluents[sort][end_state]["learned"].append(end_fluent) - actions[ap.action.name].update_add(end_fluent) - - fluents = set( - fluent - for sort in fluents.values() - for fluents in sort.values() - for fluent in fluents["learned"] - ) - actions = set(actions.values()) - - # Step 6: Extraction of static preconditions - for action in actions: - if action.name in statics: - for static in statics[action.name]: - action.update_precond(static) - - if debug: - pprint(fluents) - assert all([type(f) == LearnedLiftedFluent for f in fluents]) - - for a in actions: - print(a) - print(a.precond) - print(a.delete) - print(a.add) - print() - - return fluents, actions - - @staticmethod - def _step7( - OS: OSType, - ap_state_pointers: APStatePointers, - sorts: Sorts, - bindings: Bindings, - statics: Statics, - debug: bool = False, - ) -> Tuple[Set[LearnedLiftedFluent], Set[LearnedLiftedAction]]: - """Step 7: Formation of PDDL action schema - Implicitly includes Step 6 (statics) by including statics as an argument - and adding to the relevant actions while being constructed. - """ - # delete zero-object if it's state machine was discarded if not OS[0]: del OS[0] From cef26b7c70329f3271e26ef449115da6cb2f640e Mon Sep 17 00:00:00 2001 From: ecal Date: Wed, 21 Jun 2023 09:33:07 -0400 Subject: [PATCH 10/18] Some comments --- macq/extract/locm.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 8092987a..3d8fbef8 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -782,11 +782,16 @@ def _step7( for ap in aps: all_aps[ap.action.name].append(ap) - # for action, aps in all_aps.items(): - # assert len(aps) == max(aps.keys()) - # actions[action] = LearnedLiftedAction( - # action, [f"sort{aps[i+1].sort}" for i in range(len(aps))] - # ) + # Binding = NamedTuple("Binding", [("hypothesis", Hypothesis), ("param", int)]) + # Bindings = {sort: {state: [Binding]}} + # param_hyps = {sort: {state: {param: [Hypothesis]}}} + """ + Might want to... + Invert it so it's a map of v -> Set(H) + Assert that the G_ is the same for every H with a given v (this would be the sort of v, right?) + Ditto to check the l_ is always the same + Move forward with adding the parameter just once, and not several times + """ fluents = defaultdict(dict) actions = {} From a21306b3712d18b7b19140d18d45afd4cda0e922 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 13:16:01 -0400 Subject: [PATCH 11/18] Forced fix. --- macq/extract/locm.py | 171 ++++++++++++++++++++++-------------------- macq/extract/model.py | 2 - 2 files changed, 88 insertions(+), 85 deletions(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index 3d8fbef8..c1b478ec 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -251,13 +251,9 @@ def __new__( bindings, statics if statics is not None else {}, debug["step7"], + viz, ) - if viz: - state_machines = LOCM.get_state_machines(ap_state_pointers, OS, bindings) - for sm in state_machines: - sm.render(view=view) - return Model(fluents, actions) @staticmethod @@ -615,7 +611,7 @@ def _step4(HS: Hypotheses, debug: bool = False) -> Bindings: # check if hypothesis parameters (v1 & v2) need to be unified if ( (h1.B == h2.B and h1.k == h2.k and h1.k_ == h2.k_) - or + and # See https://github.com/AI-Planning/macq/discussions/200 (h1.C == h2.C and h1.l == h2.l and h1.l_ == h2.l_) # fmt: skip ): v1 = state_bindings[h1] @@ -675,6 +671,22 @@ def _step5( if len(bindings[sort][state_id]) == 0: del bindings[sort][state_id] + # do the same for checking h.C reading parameter P + # See https://github.com/AI-Planning/macq/discussions/200 + all_hC = set() + reads_P = defaultdict(set) + if state_id in bindings[sort]: + for h, P in bindings[sort][state_id]: + reads_P[P].add(h.C) + all_hC.add(h.C) + for P, readby in reads_P.items(): + if not readby == all_hC: + for h, P_ in bindings[sort][state_id].copy(): + if P_ == P: + bindings[sort][state_id].remove(Binding(h, P_)) + if len(bindings[sort][state_id]) == 0: + del bindings[sort][state_id] + for k, v in bindings.copy().items(): if not v: del bindings[k] @@ -682,44 +694,7 @@ def _step5( return bindings @staticmethod - def get_state_machines( - ap_state_pointers: APStatePointers, - OS: OSType, - bindings: Optional[Bindings] = None, - ): - from graphviz import Digraph - - state_machines = [] - for (sort, trans), states in zip(ap_state_pointers.items(), OS.values()): - graph = Digraph(f"LOCM-sort{sort}") - for state in range(len(states)): - label = f"state{state}" - if ( - bindings is not None - and sort in bindings - and state in bindings[sort] - ): - label += f"\n[" - params = [] - for binding in bindings[sort][state]: - params.append(f"{binding.hypothesis.G_}") - label += f",".join(params) - label += f"]" - graph.node(str(state), label=label, shape="oval") - for ap, apstate in trans.items(): - start_idx, end_idx = LOCM._pointer_to_set( - states, apstate.start, apstate.end - ) - graph.edge( - str(start_idx), str(end_idx), label=f"{ap.action.name}.{ap.pos}" - ) - - state_machines.append(graph) - - return state_machines - - @staticmethod - def _debug_state_machines(OS, ap_state_pointers, bindings): + def _debug_state_machines(OS, ap_state_pointers, state_params): import os import networkx as nx @@ -728,13 +703,17 @@ def _debug_state_machines(OS, ap_state_pointers, bindings): G = nx.DiGraph() for n in range(len(OS[sort])): lbl = f"state{n}" - if bindings is not None and sort in bindings and n in bindings[sort]: - lbl += f"\n[" - params = [] - for binding in bindings[sort][n]: - params.append(f"{binding.hypothesis.G_}") - lbl += f",".join(params) - lbl += f"]" + if ( + state_params is not None + and sort in state_params + and n in state_params[sort] + ): + lbl += str( + [ + state_params[sort][n][v] + for v in sorted(state_params[sort][n].keys()) + ] + ) G.add_node(n, label=lbl, shape="oval") for ap, apstate in ap_state_pointers[sort].items(): start_idx, end_idx = LOCM._pointer_to_set( @@ -763,13 +742,12 @@ def _step7( bindings: Bindings, statics: Statics, debug: bool = False, + viz: bool = False, ) -> Tuple[Set[LearnedLiftedFluent], Set[LearnedLiftedAction]]: """Step 7: Formation of PDDL action schema Implicitly includes Step 6 (statics) by including statics as an argument and adding to the relevant actions while being constructed. """ - if debug: - LOCM._debug_state_machines(OS, ap_state_pointers, bindings) # delete zero-object if it's state machine was discarded if not OS[0]: @@ -782,16 +760,25 @@ def _step7( for ap in aps: all_aps[ap.action.name].append(ap) - # Binding = NamedTuple("Binding", [("hypothesis", Hypothesis), ("param", int)]) - # Bindings = {sort: {state: [Binding]}} - # param_hyps = {sort: {state: {param: [Hypothesis]}}} - """ - Might want to... - Invert it so it's a map of v -> Set(H) - Assert that the G_ is the same for every H with a given v (this would be the sort of v, right?) - Ditto to check the l_ is always the same - Move forward with adding the parameter just once, and not several times - """ + state_params = defaultdict(dict) + state_params_to_hyps = defaultdict(dict) + for sort in bindings: + state_params[sort] = defaultdict(dict) + state_params_to_hyps[sort] = defaultdict(dict) + for state in bindings[sort]: + keys = {b.param for b in bindings[sort][state]} + typ = None + for key in keys: + hyps = [ + b.hypothesis for b in bindings[sort][state] if b.param == key + ] + # assert that all are the same G_ + assert len(set([h.G_ for h in hyps])) == 1 + state_params[sort][state][key] = hyps[0].G_ + state_params_to_hyps[sort][state][key] = hyps + + if debug or viz: + LOCM._debug_state_machines(OS, ap_state_pointers, state_params) fluents = defaultdict(dict) actions = {} @@ -811,7 +798,7 @@ def _step7( OS[sort], start_pointer, end_pointer ) - start_fluent_name = f"sort{sort}_state{start_state}_{ap.action.name}" + start_fluent_name = f"sort{sort}_state{start_state}" if start_fluent_name not in fluents[ap.action.name]: start_fluent = LearnedLiftedFluent( start_fluent_name, @@ -821,20 +808,29 @@ def _step7( fluents[ap.action.name][start_fluent_name] = start_fluent start_fluent = fluents[ap.action.name][start_fluent_name] - if sort in bindings and start_state in bindings[sort]: - for binding in bindings[sort][start_state]: - if binding.hypothesis.C == ap: - start_fluent.param_sorts.append( - f"sort{binding.hypothesis.G_}" - ) - start_fluent.param_act_inds.append( - binding.hypothesis.l_ - 1 - ) + + if ( + sort in state_params_to_hyps + and start_state in state_params_to_hyps[sort] + ): + for param in state_params_to_hyps[sort][start_state]: + psort = None + pind = None + for hyp in state_params_to_hyps[sort][start_state][param]: + if hyp.C == ap: + assert psort is None or psort == hyp.G_ + assert pind is None or pind == hyp.l_ + psort = hyp.G_ + pind = hyp.l_ + assert psort is not None + assert pind is not None + start_fluent.param_sorts.append(f"sort{psort}") + start_fluent.param_act_inds.append(pind - 1) a.update_precond(start_fluent) if end_state != start_state: - end_fluent_name = f"sort{sort}_state{end_state}_{ap.action.name}" + end_fluent_name = f"sort{sort}_state{end_state}" if end_fluent_name not in fluents[ap.action.name]: end_fluent = LearnedLiftedFluent( end_fluent_name, @@ -844,15 +840,24 @@ def _step7( fluents[ap.action.name][end_fluent_name] = end_fluent end_fluent = fluents[ap.action.name][end_fluent_name] - if sort in bindings and end_state in bindings[sort]: - for binding in bindings[sort][end_state]: - if binding.hypothesis.B == ap: - end_fluent.param_sorts.append( - f"sort{binding.hypothesis.G_}" - ) - end_fluent.param_act_inds.append( - binding.hypothesis.k_ - 1 - ) + + if ( + sort in state_params_to_hyps + and end_state in state_params_to_hyps[sort] + ): + for param in state_params_to_hyps[sort][end_state]: + psort = None + pind = None + for hyp in state_params_to_hyps[sort][end_state][param]: + if hyp.B == ap: + assert psort is None or psort == hyp.G_ + assert pind is None or pind == hyp.k_ + psort = hyp.G_ + pind = hyp.k_ + assert psort is not None + assert pind is not None + end_fluent.param_sorts.append(f"sort{psort}") + end_fluent.param_act_inds.append(pind - 1) a.update_delete(start_fluent) a.update_add(end_fluent) diff --git a/macq/extract/model.py b/macq/extract/model.py index 0ec9cf80..6c4d7180 100644 --- a/macq/extract/model.py +++ b/macq/extract/model.py @@ -189,8 +189,6 @@ def to_pddl_lifted( sorts = set() if self.fluents: - print("self.fluents") - print(self.fluents) for f in self.fluents: for sort in f.param_sorts: if sort not in sorts: From 2a218a2fe4e49edd76bb394f7f09364e3e9d3a14 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 23:26:19 -0400 Subject: [PATCH 12/18] Only show viz if that's requested. --- macq/extract/locm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macq/extract/locm.py b/macq/extract/locm.py index c1b478ec..82d6fe0d 100644 --- a/macq/extract/locm.py +++ b/macq/extract/locm.py @@ -777,7 +777,7 @@ def _step7( state_params[sort][state][key] = hyps[0].G_ state_params_to_hyps[sort][state][key] = hyps - if debug or viz: + if viz: LOCM._debug_state_machines(OS, ap_state_pointers, state_params) fluents = defaultdict(dict) From 0b0aa3897bd6a58122e58ee1116c6046492585c6 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 23:30:10 -0400 Subject: [PATCH 13/18] Adding new dependency. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 549107f5..647a7edb 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,7 @@ "numpy", "clingo", "graphviz", + "networkx" ] DEV_DEPENDENCIES = [ From d9639cd33e4df2db75894eec3fca6c39c170b10f Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 23:33:06 -0400 Subject: [PATCH 14/18] Adding new dependency. --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 647a7edb..023d33ec 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,8 @@ "numpy", "clingo", "graphviz", - "networkx" + "networkx", + "pydot", ] DEV_DEPENDENCIES = [ From 8a30c9266e9f9dd2e5dd7575dfbfcd1335b66622 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 23:42:08 -0400 Subject: [PATCH 15/18] Test change. --- tests/extract/test_locm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/extract/test_locm.py b/tests/extract/test_locm.py index c92b0683..6c5af6ed 100644 --- a/tests/extract/test_locm.py +++ b/tests/extract/test_locm.py @@ -367,7 +367,7 @@ def test_locm_step4(HS=None, is_test=True): print(f"\nG={G}, S={S}") for h, v in bGS: print(f"{h} -> {v}\n") - assert v == 0 + assert v == 1 else: return bindings From 97f0eebb2803c8512928853e289f162257432d90 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Wed, 21 Jun 2023 23:44:37 -0400 Subject: [PATCH 16/18] Reverting previous. --- tests/extract/test_locm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/extract/test_locm.py b/tests/extract/test_locm.py index 6c5af6ed..c92b0683 100644 --- a/tests/extract/test_locm.py +++ b/tests/extract/test_locm.py @@ -367,7 +367,7 @@ def test_locm_step4(HS=None, is_test=True): print(f"\nG={G}, S={S}") for h, v in bGS: print(f"{h} -> {v}\n") - assert v == 1 + assert v == 0 else: return bindings From b16fd0116112f9bb45844f86b2970fba1b495800 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 22 Jun 2023 22:40:42 -0400 Subject: [PATCH 17/18] Shift in testing. --- tests/extract/test_locm.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/extract/test_locm.py b/tests/extract/test_locm.py index c92b0683..884b1fb1 100644 --- a/tests/extract/test_locm.py +++ b/tests/extract/test_locm.py @@ -365,9 +365,7 @@ def test_locm_step4(HS=None, is_test=True): for G, bG in bindings.items(): for S, bGS in bG.items(): print(f"\nG={G}, S={S}") - for h, v in bGS: - print(f"{h} -> {v}\n") - assert v == 0 + assert 1 == len({v for _, v in bGS}) else: return bindings From fe5a207f93dd5f2a7aaaecf4f5203fc678e67547 Mon Sep 17 00:00:00 2001 From: Christian Muise Date: Thu, 22 Jun 2023 22:44:09 -0400 Subject: [PATCH 18/18] Shift in testing 2. --- tests/extract/test_locm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/extract/test_locm.py b/tests/extract/test_locm.py index 884b1fb1..7bdab418 100644 --- a/tests/extract/test_locm.py +++ b/tests/extract/test_locm.py @@ -365,7 +365,7 @@ def test_locm_step4(HS=None, is_test=True): for G, bG in bindings.items(): for S, bGS in bG.items(): print(f"\nG={G}, S={S}") - assert 1 == len({v for _, v in bGS}) + assert 4 == len({v for _, v in bGS}) else: return bindings