def setup(self, plan_name): """ Create step typed element DI, with effect edges to each condition of start_set Create step typed element DG, with precondition edges to each condition of end_set Add ordering from DI to DG """ s_init = copy.deepcopy(self.GL[-2]) s_init.replaceInternals() s_goal = copy.deepcopy(self.GL[-1]) s_goal.replaceInternals() s_init_plan = PlanElementGraph(name=plan_name, Elements=self.objects|s_init.elements|s_goal.elements, Edges=s_init.edges|s_goal.edges) s_init_plan.initial_dummy_step = s_init.root s_init_plan.final_dummy_step = s_goal.root s_init_plan.OrderingGraph.addOrdering(s_init.root, s_goal.root) #Add initial Open precondition flaws for dummy step #init_flaws = (Flaw((s_goal.root, prec), 'opf') for prec in s_goal.Preconditions) #for flaw in init_flaws: for prec in s_goal.Preconditions: s_init_plan.flaws.insert(self.GL, s_init_plan, Flaw((s_goal.root, prec), 'opf')) return s_init_plan
def multiGoalSetup(self, SP): #s_init is in the back for a multi-goal setup init = copy.deepcopy(self.disc_GL[-1]) init.replaceInternals() BPlans = [] for GA in self.disc_GL.Goal_Actions: s_goal = copy.deepcopy(GA) s_init = copy.deepcopy(init) DPlan = PlanElementGraph(name='disc', Elements=s_init.elements | s_goal.elements, Edges=s_init.edges | s_goal.edges) DPlan.initial_dummy_step = s_init.root DPlan.final_dummy_step = s_goal.root DPlan.OrderingGraph.addOrdering(s_init.root, s_goal.root) init_flaws = (Flaw((s_goal.root, prec), 'opf') for prec in s_goal.preconditions) for flaw in init_flaws: DPlan.flaws.insert(self.disc_GL, DPlan, flaw) Story = SP.deepcopy() New_Stories = Unify(Story, s_goal.ground_subplan, self.story_GL) for NS in New_Stories: BPlans.append(BiPlan(NS, DPlan)) return BPlans
def addStep(self, plan, s_add, s_need, condition, new=None): """ when a step is added/reused, add causal link and ordering edges (including to dummy steps) If step is new, add open precondition flaws for each precondition """ if new is None: new = False if s_add.stepnumber != plan.initial_dummy_step.stepnumber: plan.OrderingGraph.addEdge(plan.initial_dummy_step, s_add.root) plan.OrderingGraph.addEdge(plan.initial_dummy_step, s_need) if s_need.stepnumber != plan.final_dummy_step.stepnumber: plan.OrderingGraph.addEdge(s_add.root, plan.final_dummy_step) plan.OrderingGraph.addEdge(s_need, plan.final_dummy_step) #Always add this ordering plan.OrderingGraph.addEdge(s_add.root, s_need) new_link = plan.CausalLinkGraph.addEdge(s_add.root, s_need, condition) new_tclfs = plan.detectTCLFperCL(self.GL, new_link) if new: for Prec in s_add.Preconditions: plan.flaws.insert(self.GL, plan, Flaw((s_add.root, Prec), 'opf')) #only detect for new steps if adding this step threatens causal link new_tclfs.update(plan.detectTCLFperStep(self.GL, s_add.root)) for tclf in new_tclfs: plan.flaws.insert(self.GL, plan, tclf) return plan
def addStep(self, plan, s_add, s_need, condition, GL, new=None): """ when a step is added/reused, add causal link and ordering edges (including to dummy steps) If step is new, add open precondition flaws for each precondition """ if new is None: new = False if s_add != plan.initial_dummy_step: plan.OrderingGraph.addEdge(plan.initial_dummy_step, s_add) plan.OrderingGraph.addEdge(plan.initial_dummy_step, s_need) if s_need != plan.final_dummy_step: plan.OrderingGraph.addEdge(s_add, plan.final_dummy_step) plan.OrderingGraph.addEdge(s_need, plan.final_dummy_step) #Always add this ordering plan.OrderingGraph.addEdge(s_add, s_need) plan.CausalLinkGraph.addEdge(s_add, s_need, condition) if new: for prec in plan.getIncidentEdgesByLabel(s_add, 'precond-of'): plan.flaws.insert(GL, plan, Flaw((s_add, prec.sink), 'opf')) # if plan.name == 'disc': # plan.flaws.insert(GL, plan, Flaw(s_add.stepnumber, 'dcf')) return plan
def AddNewFlaws(GL, step, new_plan): Step = Action.subgraph(new_plan, step) # Step = Action.subgraph(new_plan, new_plan.getElmByRID(step.replaced_ID)) for pre in Step.Preconditions: #this is a hack, if the precondition has two operator parents, then its in a causal link cndts = {edge for edge in new_plan.edges if isinstance(edge.source, Operator) and edge.sink == pre.root} if len(cndts) == 0: raise ValueError('wait, no edge for this preconditon? impossible!') if len(cndts) < 2: new_plan.flaws.insert(GL, new_plan, Flaw((step, pre), 'opf')) if step.is_decomp: new_plan.flaws.insert(GL, new_plan, Flaw(GL[step.stepnumber].ground_subplan, 'dcf')) new_plan.flaws.addCndtsAndRisks(GL, step)
def AddLink(link, new_plan, UW, remove_flaw=True): Source = Action.subgraph(new_plan, UW[link.source.position]) new_d = Source.getElmByRID(link.label.replaced_ID) if new_d is None: Sink = Action.subgraph(new_plan, UW[link.sink.position]) new_d = Sink.getElmByRID(link.label.replaced_ID) D = Condition.subgraph(new_plan, new_d) new_plan.CausalLinkGraph.addEdge(UW[link.source.position], UW[link.sink.position],D) if remove_flaw: flaws = new_plan.flaws.flaws f = Flaw((UW[link.sink.position], D), 'opf') if f in flaws: new_plan.flaws.remove(f)
def detectThreatenedCausalLinks(self, GL): """ A threatened causal link flaw is a tuple <causal link edge, threatening step element> where if s --p--> t is a causal link edge and s_threat is the threatening step element, then there is no ordering path from t to s_threat, no ordering path from s_threat to s, there is an effect edge from s_threat to a literal false-p', and p' is consistent with p after flipping the truth attribute """ detectedThreatenedCausalLinks = set() nonThreats = self.CausalLinkGraph.nonThreats for causal_link in self.CausalLinkGraph.edges: for step in self.Steps: #defense 1 if step in nonThreats[causal_link]: continue # defense 2-4 - First, ignore steps which either are the source and sink of causal link, or which cannot # be ordered between them if step == causal_link.source or step == causal_link.sink: nonThreats[causal_link].add(step) continue if self.OrderingGraph.isPath(causal_link.sink, step): nonThreats[causal_link].add(step) continue if self.OrderingGraph.isPath(step, causal_link.source): nonThreats[causal_link].add(step) continue if step.stepnumber not in GL.threat_dict[causal_link.sink.stepnumber]: nonThreats[causal_link].add(step) continue detectedThreatenedCausalLinks.add(Flaw((step, causal_link), 'tclf')) #nonThreats[causal_link].add(step) return detectedThreatenedCausalLinks
def newStep(self, plan, flaw, GL): """ @param plan: @param flaw: @return: """ results = set() s_need, precondition = flaw.flaw antecedents = GL.pre_dict[precondition.replaced_ID] for ante in antecedents: if ante.action.name == 'dummy_init': continue #step 1 - make a copy cndt = copy.deepcopy(ante) #step 2 - replace its internals, to distinguish from other identical antesteps (anteaction, eff_link) = cndt anteaction.replaceInternals() # step 3 - make a copy of the plan new_plan = plan.deepcopy() if plan.name == 'disc': anteaction = GL[anteaction.stepnumber].deepcopy() anteaction.replaceInternals() eff = anteaction.getElmByRID(eff_link.sink.replaced_ID) PArgs = list(Condition.subgraph(new_plan, precondition).Args) EArgs = list(Condition.subgraph(anteaction, eff).Args) #Retarget args in discourse step. retargetArgs(anteaction, EArgs, PArgs) #Retarget elements in args in ground subplan retargetElmsInArgs(anteaction.ground_subplan, EArgs, PArgs) #Then, add a flaw which says, add ground subplan, first looking if elm.ID already exists new_plan.flaws.decomps.add( Flaw(anteaction.ground_subplan, 'dcf')) # for edge in anteaction.edges: # if edge.source == anteaction.root and edge.sink == eff: # eff_link = edge # break eff_link = anteaction.RemoveSubgraph(eff) #step 4 - set sink before replace internals preserve_original_id = eff_link.sink.replaced_ID eff_link.sink = new_plan.getElementById(precondition.ID) eff_link.sink.replaced_ID = preserve_original_id new_plan.edges.add(eff_link) #step 5 - add new stuff to new plan new_plan.elements.update(anteaction.elements) new_plan.edges.update(anteaction.edges) #step 6 - update orderings and causal links, add flaws self.addStep(new_plan, anteaction.root, new_plan.getElementById(s_need.ID), eff_link.sink, GL, new=True) new_plan.flaws.addCndtsAndRisks(GL, anteaction.root) #step 7 - add new_plan to open list results.add(new_plan) return results