def __init__(self, dummy_init_constructor, dummy_goal_constructor): self.ID = uuid4() self.OrderingGraph = OrderingGraph() self.CausalLinkGraph = CausalLinkGraph() # self.HierarchyGraph = HierarchyGraph() self.flaws = FlawLib() self.solved = False self.dummy = dummyTuple(dummy_init_constructor.instantiate(), dummy_goal_constructor.instantiate()) self.init = self.dummy.init.preconds self.goal = self.dummy.final.preconds self.steps = [self.dummy.init, self.dummy.final] # check if any existing steps are choices (instances of cndts of open conditions) self.dummy.final.update_choices(self) self.cndt_map = None self.threat_map = None # self.gstep_lib = ground_step_list # self.h_step_dict = dict() self.heuristic = float('inf') self.name = '' self.cost = 0 self.depth = 0
def __init__(self, ID=None, type_graph=None, name=None, Elements=None, plan_elm=None, Edges=None, Restrictions=None): if ID is None: ID = uuid4() if type_graph is None: type_graph = 'PlanElementGraph' if Elements is None: Elements = set() if Edges is None: Edges = set() if Restrictions is None: Restrictions = set() self.OrderingGraph = OrderingGraph() self.CausalLinkGraph = CausalLinkGraph() self.flaws = FlawLib() self.solved = False self.initial_dummy_step = None self.final_dummy_step = None if plan_elm is None: plan_elm = Element(ID=ID, typ=type_graph, name=name) super(PlanElementGraph, self).__init__(ID, type_graph, name, Elements, plan_elm, Edges, Restrictions)
def __init__(self, name, Restrictions=None): self.name = name self.ID = uuid4() self.OrderingGraph = OrderingGraph() self.CausalLinkGraph = CausalLinkGraph() self.flaws = FlawLib() self.solved = False self.initial_dummy_step = None self.final_dummy_step = None self.steps = []
class GPlan: def __init__(self, dummy_init_constructor, dummy_goal_constructor): self.ID = uuid4() self.OrderingGraph = OrderingGraph() self.CausalLinkGraph = CausalLinkGraph() # self.HierarchyGraph = HierarchyGraph() self.flaws = FlawLib() self.solved = False self.dummy = dummyTuple(dummy_init_constructor.instantiate(), dummy_goal_constructor.instantiate()) self.init = self.dummy.init.preconds self.goal = self.dummy.final.preconds self.steps = [self.dummy.init, self.dummy.final] # check if any existing steps are choices (instances of cndts of open conditions) self.dummy.final.update_choices(self) self.cndt_map = None self.threat_map = None # self.gstep_lib = ground_step_list # self.h_step_dict = dict() self.heuristic = float('inf') self.name = '' self.cost = 0 self.depth = 0 def __len__(self): return len(self.steps) def __getitem__(self, pos): return self.steps[pos] def __setitem__(self, item, pos): self.steps[pos] = item def index(self, step): for i, s in enumerate(self.steps): if s.ID == step.ID: return i print('{} {} {}'.format(self.name, step, step.ID)) for i, s in enumerate(self.steps): print('{} {} {}'.format(i, s, s.ID)) raise ValueError('{} with ID={} not found in plan {}'.format(step, step.ID, self.name)) def instantiate(self, add_to_name): new_self = copy.deepcopy(self) new_self.ID = uuid4() new_self.name += add_to_name # refresh attributes return new_self # @property # def cost(self): # return len(self.steps) - 2 def isInternallyConsistent(self): return self.OrderingGraph.isInternallyConsistent() and self.CausalLinkGraph.isInternallyConsistent() # Insert Methods # def insert(self, step, dni=None): # baseline condition: self.cost += 1 # self.cost += (2 * 2 + 1) - (step.height * step.height) if step.height > 0: return self.insert_decomp(step, dni) else: return self.insert_primitive(step) def insert_primitive(self, new_step): self.steps.append(new_step) # global orderings self.OrderingGraph.addEdge(self.dummy.init, new_step) self.OrderingGraph.addEdge(new_step, self.dummy.final) # add open conditions for new step for pre in new_step.open_preconds: self.flaws.insert(self, OPF(new_step, pre)) # check for causal link threats for edge in self.CausalLinkGraph.edges: # source, sink, condition = edge if edge.source.ID == new_step.ID: continue if edge.sink.ID == new_step.ID: continue if self.OrderingGraph.isPath(new_step, edge.source): continue if self.OrderingGraph.isPath(edge.sink, new_step): continue if new_step.stepnum in edge.sink.threat_map[edge.label.ID]: self.flaws.insert(self, TCLF(new_step, edge)) return None def insert_decomp(self, new_step, dni=None): # magic happens here swap_dict = dict() # sub dummy init d_i = new_step.dummy.init.instantiate() d_i.depth = new_step.depth swap_dict[new_step.dummy.init.ID] = d_i self.steps.append(d_i) # add flaws for each new_step precondition, but make s_need d_i and update cndt_map/ threat_map d_i.swap_setup(new_step.cndts, new_step.cndt_map, new_step.threats, new_step.threat_map, new_step.cntg_mental) for pre in new_step.open_preconds: self.flaws.insert(self, OPF(d_i, pre, new_step.height)) preconds = list(new_step.open_preconds) d_i.preconds = preconds d_i.open_preconds = preconds self.OrderingGraph.addEdge(self.dummy.init, d_i) self.OrderingGraph.addEdge(d_i, self.dummy.final) # sub dummy final d_f = new_step.dummy.final.instantiate(default_None_is_to_refresh_open_preconds=False) d_f.depth = new_step.depth swap_dict[new_step.dummy.final.ID] = d_f # d_f will be primitive, to allow any heighted applicable steps self.insert(d_f) # added this 2017-08-09 self.OrderingGraph.addEdge(d_i, d_f) self.OrderingGraph.addEdge(d_f, self.dummy.final) self.OrderingGraph.addEdge(self.dummy.init, d_f) # decomposition links # self.HierarchyGraph.addOrdering(new_step, d_i) # self.HierarchyGraph.addOrdering(new_step, d_f) # for sb_step in new_step.sub_steps: # self.HierarchyGraph.addOrdering(new_step, sb_step) # log who your family is new_step.dummy = dummyTuple(d_i, d_f) d_i.sibling = d_f d_f.sibling = d_i # sub steps for substep in new_step.sub_steps: new_substep = substep.instantiate(default_None_is_to_refresh_open_preconds=False) swap_dict[substep.ID] = new_substep # INCREMENT DEPTH new_substep.depth = new_step.depth + 1 if new_substep.depth > self.depth: self.depth = new_substep.depth if dni is not None: if substep in dni: continue poss_swaps = self.insert(new_substep) if poss_swaps is not None: swap_dict.update(poss_swaps) # if your substeps have children, make those children fit between your init and if new_substep.height > 0: self.OrderingGraph.addEdge(new_substep.dummy.final, d_f) self.OrderingGraph.addEdge(d_i, new_substep.dummy.init) else: self.OrderingGraph.addEdge(new_substep, d_f) self.OrderingGraph.addEdge(d_i, new_substep) # sub orderings for edge in new_step.sub_orderings.edges: if dni is not None: if edge.source in dni: continue elif edge.sink in dni: continue # try: source, sink = swap_dict[edge.source.ID], swap_dict[edge.sink.ID] # except: # pass if source.height > 0: source = source.dummy.final if sink.height > 0: sink = sink.dummy.init self.OrderingGraph.addLabeledEdge(source, sink, edge.label) # sub links for edge in new_step.sub_links.edges: # instantiating a GLiteral does not give it new ID (just returns deep copy) source, sink, label = swap_dict[edge.source.ID], swap_dict[edge.sink.ID], edge.label.instantiate() if source.height > 0: source = source.dummy.final if sink.height > 0: sink = sink.dummy.init clink = self.CausalLinkGraph.addEdge(source, sink, label) # check if this link is threatened for substep in new_step.sub_steps: if dni is not None and substep in dni: continue new_substep = swap_dict[substep.ID] if new_substep.ID in {clink.source.ID, clink.sink.ID}: continue if new_substep.stepnum not in clink.sink.threat_map[clink.label.ID]: continue if new_substep.height > 0: # decomp step compared to its dummy init and dummy final steps if self.OrderingGraph.isPath(new_substep.dummy.final, clink.source): continue if self.OrderingGraph.isPath(clink.sink, new_substep.dummy.init): continue self.flaws.insert(self, TCLF(new_substep.dummy.final, clink)) else: # primitive step gets the primitive treatment if self.OrderingGraph.isPath(new_substep, clink.source): continue if self.OrderingGraph.isPath(clink.sink, new_substep): continue self.flaws.insert(self, TCLF(new_substep, clink)) return swap_dict # print('check') # Resolve Methods # def resolve(self, new_step, s_need, p): if new_step.height > 0: self.resolve_with_decomp(new_step, s_need, p) else: self.resolve_with_primitive(new_step, s_need, p) def resolve_with_primitive(self, new_step, mutable_s_need, mutable_p): # operate on cloned plan mutable_s_need.fulfill(mutable_p) # add orderings self.OrderingGraph.addEdge(new_step, mutable_s_need) # add causal link c_link = self.CausalLinkGraph.addEdge(new_step, mutable_s_need, mutable_p) if mutable_p.ID in mutable_s_need.cntg_mental.keys() and new_step.stepnum in mutable_s_need.cntg_mental[mutable_p.ID]: self.OrderingGraph.addCntg(new_step, mutable_s_need) mutable_s_need.update_choices(self) # check if this link is threatened ignore_these = {mutable_s_need.ID, new_step.ID} # ignore_these = {mutable_s_need.stepnum, new_step.stepnum} for step in self.steps: if step.ID in ignore_these: continue if step.stepnum not in mutable_s_need.threat_map[mutable_p.ID]: continue if self.OrderingGraph.isPath(mutable_s_need, step): continue # only for reuse case, otherwise this check is superfluous if self.OrderingGraph.isPath(step, new_step): continue self.flaws.insert(self, TCLF(step, c_link)) # # check if adding this step threatens other causal links # for cl in self.CausalLinkGraph.edges: # if cl == c_link: # continue # if new_step.stepnum not in cl.sink.threat_map[cl.label.ID]: # continue # if self.OrderingGraph.isPath(new_step, cl.source): # continue # if self.OrderingGraph.isPath(cl.sink, new_step): # continue # self.flaws.insert(self, TCLF(new_step, cl)) def resolve_with_decomp(self, new_step, mutable_s_need, mutable_p): d_i, d_f = new_step.dummy # operate on cloned plan # mutable_s_need = self[s_index] # mutable_p = mutable_s_need.preconds[p_index] mutable_s_need.fulfill(mutable_p) # add ordering self.OrderingGraph.addEdge(d_f, mutable_s_need) # add causal link c_link = self.CausalLinkGraph.addEdge(d_f, mutable_s_need, mutable_p) if mutable_p.ID in mutable_s_need.cntg_mental.keys() and d_f.stepnum in mutable_s_need.cntg_mental[mutable_p.ID]: self.OrderingGraph.addCntg(new_step, mutable_s_need) mutable_s_need.update_choices(self) # check if df -> s_need is threatened ignore_these = {mutable_s_need.ID, d_f.ID, d_i.ID} for step in self.steps: # reminder: existing steps are primitive if step.ID in ignore_these: continue ### NOT SUFFICIENT: needs to not be a threat to any sub-step added... ### if step.stepnum not in mutable_s_need.threat_map[mutable_p.ID]: continue # check only for d_f, in case this step occurs between d_i and d_f if self.OrderingGraph.isPath(step, d_f): continue if self.OrderingGraph.isPath(mutable_s_need, step): continue self.flaws.insert(self, TCLF(step, c_link)) # # check if adding this step threatens other causal links # for cl in self.CausalLinkGraph.edges: # # all causal links are between primitive steps # if cl == c_link: # continue # if new_step.stepnum not in cl.sink.threat_map[cl.label.ID]: # continue # if self.OrderingGraph.isPath(d_f, cl.source): # continue # if self.OrderingGraph.isPath(cl.sink, d_f): # LOOK HERE TODO: DECIDE # continue # self.flaws.insert(self, TCLF(d_f, cl)) def __lt__(self, other): if self.cost / (1 + math.log2(self.depth+1)) + self.heuristic != other.cost / (1 + math.log2(other.depth+1)) + other.heuristic: return self.cost / (1 + math.log2(self.depth+1)) + self.heuristic < other.cost / (1 + math.log2(other.depth+1)) + other.heuristic # if self.cost - math.log2(self.depth+1) + self.heuristic != other.cost - math.log2(other.depth+1) + other.heuristic: # return self.cost - math.log2(self.depth+1) + self.heuristic < other.cost - math.log2(other.depth+1) + other.heuristic # if self.cost - self.depth + self.heuristic != other.cost - other.depth + other.heuristic: # return self.cost - self.depth + self.heuristic < other.cost - other.depth + other.heuristic if self.cost + self.heuristic != other.cost + other.heuristic: return (self.cost + self.heuristic) < (other.cost + other.heuristic) elif self.cost != other.cost: return self.cost < other.cost elif self.heuristic != other.heuristic: return self.heuristic < other.heuristic elif len(self.flaws) != len(other.flaws): return len(self.flaws) < len(other.flaws) elif len(self.CausalLinkGraph.edges) != len(other.CausalLinkGraph.edges): return len(self.CausalLinkGraph.edges) > len(other.CausalLinkGraph.edges) elif len(self.OrderingGraph.edges) != len(other.OrderingGraph.edges): return len(self.OrderingGraph.edges) > len(other.OrderingGraph.edges) elif sum([step.stepnum for step in self]) != sum([step.stepnum for step in other]): return sum([step.stepnum for step in self]) < sum([step.stepnum for step in other]) else: return self.OrderingGraph < other.OrderingGraph def __str__(self): return self.name # return 'GPlan{} c={} h={}\t'.format(self.ID[-4:], self.cost, self.heuristic) + \ # str(self.steps) + '\n' + str(self.OrderingGraph) + '\n' + str(self.CausalLinkGraph) def __repr__(self): return self.__str__()
class GPlan: def __init__(self, dummy_init_constructor, dummy_goal_constructor): self.ID = uuid4() self.OrderingGraph = OrderingGraph() self.CausalLinkGraph = CausalLinkGraph() self.flaws = FlawLib() self.solved = False self.dummy = dummyTuple(dummy_init_constructor.instantiate(), dummy_goal_constructor.instantiate()) self.init = self.dummy.init.preconds self.goal = self.dummy.final.preconds self.steps = [self.dummy.init, self.dummy.final] # check if any existing steps are choices (instances of cndts of open conditions) self.dummy.final.update_choices(self) self.cndt_map = None self.threat_map = None # self.gstep_lib = ground_step_list # self.h_step_dict = dict() self.heuristic = float('inf') def __len__(self): return len(self.steps) def __getitem__(self, pos): return self.steps[pos] def __setitem__(self, item, pos): self.steps[pos] = item def index(self, step): return self.steps.index(step) def instantiate(self): new_self = copy.deepcopy(self) new_self.ID = uuid4() # refresh attributes return new_self @property def cost(self): return len(self.steps) - 2 def isInternallyConsistent(self): return self.OrderingGraph.isInternallyConsistent( ) and self.CausalLinkGraph.isInternallyConsistent() # Insert Methods # def insert(self, step, dummy_dict=None): if step.height > 0: dummy_dict, sub_steps = self.insert_decomp(step, dummy_dict) return dummy_dict, sub_steps else: self.insert_primitive(step) return None, None # self.steps.append(step) # def insert_decomp(self, new_step, dummy_dict=None): # # magic happens here # swap_dict = dict() # # # sub dummy init # d_i = new_step.sub_dummy.sub_init.instantiate() # swap_dict[new_step.sub_dummy.sub_init.ID] = d_i # self.steps.append(d_i) # # # sub dummy final # d_f = new_step.sub_dummy.sub_final.instantiate(default_None_is_to_refresh_open_preconds=False) # swap_dict[new_step.sub_dummy.sub_final.ID] = d_f # self.steps.append(d_f) # # if dummy_dict is None: # dummy_dict = dict() # # # sub steps (recursively insert... then reuse later for existing links # for substep in new_step.sub_steps: # new_substep = substep.instantiate(default_None_is_to_refresh_open_preconds=False) # swap_dict[substep.ID] = new_substep # # # substep points to dummies of same subplan # dummy_dict[new_substep] = dummyTuple(d_i, d_f) # sub_dummy_dict = self.insert(new_substep) # if sub_dummy_dict is not None: # dummy_dict.update(sub_dummy_dict) # # # sub orderings # for edge in new_step.sub_orderings.edges: # self.OrderingGraph.addEdge(swap_dict[edge.source.ID], swap_dict[edge.sink.ID]) # # # sub links # for edge in new_step.sub_links.edges: # clink = self.CausalLinkGraph.addEdge(swap_dict[edge.source.ID], swap_dict[edge.sink.ID], # edge.label.instantiate()) # # check if this link is threatened # for substep in new_step.sub_steps: # new_substep = swap_dict[substep.ID] # if new_substep.ID in {clink.source.ID, clink.sink.ID}: # continue # if new_substep.stepnum not in clink.sink.threat_map[clink.label.ID]: # continue # if self.OrderingGraph.isPath(new_substep, clink.source): # continue # if self.OrderingGraph.isPath(clink.sink, new_substep): # continue # self.flaws.insert(self, TCLF(new_substep, clink)) # # # global orderings # self.OrderingGraph.addEdge(self.dummy.init, d_i) # self.OrderingGraph.addEdge(self.dummy.init, d_f) # self.OrderingGraph.addEdge(d_i, self.dummy.final) # self.OrderingGraph.addEdge(d_f, self.dummy.final) # # return dummy_dict def insert_primitive(self, new_step): self.steps.append(new_step) self.OrderingGraph.addEdge(self.dummy.init, new_step) self.OrderingGraph.addEdge(new_step, self.dummy.final) return None, None, None, new_step def resolve(self, new_step, s_index, p_index): if new_step.height > 0: self.resolve_with_decomp(new_step, s_index, p_index) else: self.resolve_with_primitive(new_step, s_index, p_index) def resolve_with_primitive(self, new_step, s_index, p_index): # operate on cloned plan mutable_s_need = self[s_index] mutable_p = mutable_s_need.preconds[p_index] mutable_s_need.fulfill(mutable_p) mutable_s_need.update_choices(self) # add orderings self.OrderingGraph.addEdge(new_step, mutable_s_need) # add causal link c_link = self.CausalLinkGraph.addEdge(new_step, mutable_s_need, mutable_p) # add open conditions for new step for pre in new_step.open_preconds: self.flaws.insert(self, OPF(new_step, pre)) # check if this link is threatened ignore_these = {mutable_s_need.ID, new_step.ID} for step in self.steps: if step.ID in ignore_these: continue if self.OrderingGraph.isPath(mutable_s_need, step): continue if step.stepnum in mutable_s_need.threats: self.flaws.insert(self, TCLF(step, c_link)) # check if adding this step threatens other causal links for cl in self.CausalLinkGraph.edges: if cl == c_link: continue if new_step.stepnum not in cl.sink.threat_map[cl.label]: continue if self.OrderingGraph.isPath(new_step, cl.source): continue if self.OrderingGraph.isPath(cl.sink, new_step): continue self.flaws.insert(self, TCLF(new_step, cl)) def resolve_with_decomp(self, new_step, s_index, p_index): d_i, d_f = new_step.dummy # operate on cloned plan mutable_s_need = self[s_index] mutable_p = mutable_s_need.preconds[p_index] mutable_s_need.fulfill(mutable_p) mutable_s_need.update_choices(self) # add orderings to rest of plan self.OrderingGraph.addEdge(d_f, mutable_s_need) # add causal link c_link = self.CausalLinkGraph.addEdge(d_f, mutable_s_need, mutable_p) # check if df -> s_need is threatened ignore_these = {mutable_s_need.ID, d_f.ID, d_i.ID} for step in self.steps: # existing steps must be primitive if step.ID in ignore_these: continue if self.OrderingGraph.isPath(step, d_f): continue if self.OrderingGraph.isPath(mutable_s_need, step): continue if step.stepnum in mutable_s_need.threats: self.flaws.insert(self, TCLF(step, c_link)) # check if adding this step threatens other causal links for cl in self.CausalLinkGraph.edges: # all causal links are between primitive steps if cl == c_link: continue if new_step.stepnum not in cl.sink.threat_map[cl.label]: continue if self.OrderingGraph.isPath(d_f, cl.source): continue if self.OrderingGraph.isPath(cl.sink, d_i): continue self.flaws.insert(self, DTCLF(d_i, d_f, cl)) def insert_primitive_0ld(self, new_step, s_index, p_index): # append primitive step self.steps.append(new_step) # operate on cloned plan mutable_s_need = self[s_index] mutable_p = mutable_s_need.preconds[p_index] mutable_s_need.fulfill(mutable_p) mutable_s_need.update_choices(self) # add orderings self.OrderingGraph.addEdge(new_step, mutable_s_need) self.OrderingGraph.addEdge(self.dummy.init, new_step) self.OrderingGraph.addEdge(new_step, self.dummy.final) # add causal link c_link = self.CausalLinkGraph.addEdge(new_step, mutable_s_need, mutable_p) # add open conditions for new step for pre in new_step.open_preconds: self.flaws.insert(self, OPF(new_step, pre)) # check if this link is threatened ignore_these = {mutable_s_need.ID, new_step.ID} for step in self.steps: if step.ID in ignore_these: continue if self.OrderingGraph.isPath(mutable_s_need, step): continue if step.stepnum in mutable_s_need.threats: self.flaws.insert(self, TCLF(step, c_link)) # check if adding this step threatens other causal links for cl in self.CausalLinkGraph.edges: if cl == c_link: continue if new_step.stepnum not in cl.sink.threat_map[cl.label]: continue if self.OrderingGraph.isPath(new_step, cl.source): continue if self.OrderingGraph.isPath(cl.sink, new_step): continue self.flaws.insert(self, TCLF(new_step, cl)) def insert_decomp(self, new_step): # magic happens here swap_dict = dict() # sub dummy init d_i = new_step.sub_dummy.sub_init.instantiate() swap_dict[new_step.sub_dummy.sub_init.ID] = d_i self.steps.append(d_i) # add flaws for each new_step precondition, but make s_need d_i and update cndt_map/ threat_map for pre in new_step.open_preconds: self.flaws.insert(self, OPF(d_i, pre)) d_i.swap_setup(new_step.cndts, new_step.cndt_map, new_step.threats, new_step.threat_map) # sub dummy final d_f = new_step.sub_dummy.sub_final.instantiate( default_None_is_to_refresh_open_preconds=False) swap_dict[new_step.sub_dummy.sub_final.ID] = d_f self.steps.append(d_f) # add flaws for each d_f pre for pre in d_f.open_preconds: self.flaws.insert(self, OPF(d_f, pre)) self.OrderingGraph.addEdge(self.dummy.init, d_i) self.OrderingGraph.addEdge(self.dummy.init, d_f) self.OrderingGraph.addEdge(d_i, self.dummy.final) self.OrderingGraph.addEdge(d_f, self.dummy.final) # sub steps for substep in new_step.sub_steps: new_substep = substep.instantiate( default_None_is_to_refresh_open_preconds=False) swap_dict[substep.ID] = new_substep if new_substep.height > 0: # check what links this new_substep is a source of. self.insert(new_substep) for open_condition in new_substep.open_preconds: self.flaws.insert(self, OPF(new_substep, open_condition)) # sub orderings for edge in new_step.sub_orderings.edges: source, sink = swap_dict[edge.source.ID], swap_dict[edge.sink.ID] if source.height > 0: source = source.dummy.final if sink.height > 0: sink = sink.dummy.init self.OrderingGraph.addEdge(source, sink) # sub links for edge in new_step.sub_links.edges: source, sink, label = swap_dict[edge.source.ID], swap_dict[ edge.sink.ID], edge.label.instantiate() if source.height > 0: source = source.dummy.final if sink.height > 0: sink = sink.dummy.init clink = self.CausalLinkGraph.addEdge(source, sink, label) # check if this link is threatened for substep in new_step.sub_steps: new_substep = swap_dict[substep.ID] if new_substep.ID in {clink.source.ID, clink.sink.ID}: continue if new_substep.stepnum not in clink.sink.threat_map[ clink.label.ID]: continue if new_substep.height > 0: # decomp step compared to its dummy init and dummy final steps if self.OrderingGraph.isPath(new_substep.dummy.final, clink.source): continue if self.OrderingGraph.isPath(clink.sink, new_substep.dummy.init): continue self.flaws.insert( self, DTCLF(new_substep.dummy.init, new_substep.dummy.final, clink)) else: # primitive step gets the primitive treatment if self.OrderingGraph.isPath(new_substep, clink.source): continue if self.OrderingGraph.isPath(clink.sink, new_substep): continue self.flaws.insert(self, TCLF(new_substep, clink)) # # operate on cloned plan # mutable_s_need = self[s_index] # mutable_p = mutable_s_need.preconds[p_index] # mutable_s_need.fulfill(mutable_p) # mutable_s_need.update_choices(self) # # # add orderings to rest of plan # self.OrderingGraph.addEdge(d_f, mutable_s_need) # # # add causal link # c_link = self.CausalLinkGraph.addEdge(d_f, mutable_s_need, mutable_p) # # # check if df -> s_need is threatened # ignore_these = {mutable_s_need.ID, d_f.ID, d_i.ID} # for step in self.steps: # # existing steps must be primitive # if step.ID in ignore_these: # continue # if self.OrderingGraph.isPath(step, d_f): # continue # if self.OrderingGraph.isPath(mutable_s_need, step): # continue # if step.stepnum in mutable_s_need.threats: # self.flaws.insert(self, TCLF(step, c_link)) # # # check if adding this step threatens other causal links # for cl in self.CausalLinkGraph.edges: # # all causal links are between primitive steps # if cl == c_link: # continue # if new_step.stepnum not in cl.sink.threat_map[cl.label]: # continue # if self.OrderingGraph.isPath(d_f, cl.source): # continue # if self.OrderingGraph.isPath(cl.sink, d_i): # continue # self.flaws.insert(self, DTCLF(d_i, d_f, cl)) def __lt__(self, other): if self.cost + self.heuristic != other.cost + other.heuristic: return (self.cost + self.heuristic) < (other.cost + other.heuristic) elif self.heuristic != other.heuristic: return self.heuristic < other.heuristic elif self.cost != other.cost: return self.cost < other.cost elif len(self.flaws) != len(other.flaws): return len(self.flaws) < len(other.flaws) elif sum([step.stepnum for step in self]) != sum([step.stepnum for step in other]): return sum([step.stepnum for step in self]) < sum( [step.stepnum for step in other]) else: return self.OrderingGraph < other.OrderingGraph def __str__(self): return 'GPlan{} c={} h={}\t'.format(self.ID[-4:], self.cost, self.heuristic) + \ str(self.steps) + '\n' + str(self.OrderingGraph) + '\n' + str(self.CausalLinkGraph) def __repr__(self): return self.__str__()