def domainToOperatorGraphs(domain): opGraphs = set() dopGraphs = set() for action in domain.actions: op = Operator(name=action.name, num_args=len(action.parameters)) op_graph = Action(name=action.name, root_element=op) evalActionParams(action.parameters, op_graph) if action.precond is not None: getFormulaGraph(action.precond.formula, op_graph, parent=op, relationship='precond-of', elements=op_graph.elements, edges=op_graph.edges) if action.effect is not None: getFormulaGraph(action.effect.formula, op_graph, parent=op, relationship='effect-of', elements=op_graph.elements, edges=op_graph.edges) if action.decomp is not None: # henceforth, action.decomp is tuple (sub-params, decomp) decomp_graph = PlanElementGraph(name=action.name, type_graph='decomp') getDecompGraph(action.decomp.formula, decomp_graph, action.parameters + action.decomp.sub_params) op_graph.subplan = decomp_graph # This searches for params that are listed as params and sub-params, may not be needed # opelms = list(op_graph.elements) # dpelms = list(decomp_graph.elements) # for step_elm in opelms: # for d_elm in dpelms: # if not isinstance(d_elm, Argument): # continue # if d_elm.arg_name == step_elm.arg_name: # op_graph.assign(step_elm, d_elm) dopGraphs.add(op_graph) else: opGraphs.add(op_graph) return opGraphs, dopGraphs
def Groundify(Planets, GL, has_links): for Planet in Planets: for step in Planet.Steps: Step = Action.subgraph(Planet, step) Planet.UnifyActions(Step, GL[step.stepnumber]) if not has_links: #we're done return Planets Discovered_Planets = [] for Plan in Planets: Libs = [LinkLib(i,link,GL) for i, link in enumerate(Plan.CausalLinkGraph.edges)] #LW = [plan1 [link1.condition, link2.condition,..., link-n.condition], # plan2 [link1.condition, link2.condition, ..., link-m.condition], # plan-k [l1,...,lz]] LW = productByPosition(Libs) for lw in LW: NP = Plan.deepcopy() for _link in lw: pre_token = GL.getConsistentPrecondition(Action.subgraph(NP, _link.sink), _link.label) pre_link = NP.RemoveSubgraph(pre_token) pre_link.sink = _link.label Discovered_Planets.append(NP) return Discovered_Planets
def Groundify(Planets, GL, has_links): for Planet in Planets: for step in Planet.Steps: Step = Action.subgraph(Planet, step) Planet.UnifyActions(Step, GL[step.stepnumber]) if not has_links: #we're done return Planets Discovered_Planets = [] for Plan in Planets: Libs = [LinkLib(i,link,GL) for i, link in enumerate(Plan.CausalLinkGraph.edges)] #LW = [plan1 [link1.condition, link2.condition,..., link-n.condition], # plan2 [link1.condition, link2.condition, ..., link-m.condition], # plan-k [l1,...,lz]] LW = productByPosition(Libs) for lw in LW: NP = Plan.deepcopy() for _link in lw: pre_token = GL.getConsistentPrecondition(Action.subgraph(NP, _link.sink), _link.label) if _link.label == pre_token: continue pre_link = NP.RemoveSubgraph(pre_token) pre_link.sink = _link.label NP.edges.add(pre_link) Discovered_Planets.append(NP) return Discovered_Planets
def problemToGraphs(problem): """ Returns a dictionary: Keys: 'arg', 'init', 'goal' Values: arg dictionary, (elements, edges), (elements, edges) """ Args = {object.name: Argument(name=object.name, typ=object.typeName) for object in problem.objects if not object.typeName.lower() in {'character', 'actor', 'person', 'agent'}} Args.update({object.name: Actor(typ=object.typeName.lower(), name=object.name) for object in problem.objects if object.typeName.lower() in {'character', 'actor', 'person', 'agent'}}) goal_elements, goal_edges = getGoalSet(problem.goal.formula, Args) goal_op = Operator(name='dummy_goal', stepnumber=1, num_args=0) goal_graph = Action(name='dummy_goal', root_element=goal_op) goal_graph.elements.update(goal_elements) goal_graph.edges.update(goal_edges) goal_graph.edges.update({Edge(goal_op, goal_lit, 'precond-of') for goal_lit in goal_elements if type(goal_lit) is Literal}) init_op = Operator(name='dummy_init', stepnumber=0, num_args=0) init_graph = Action(name='dummy_init', root_element=init_op) for condition in problem.init.predicates: lit = Literal(name=condition.name, num_args=len(condition.parameters), truth=True) init_graph.elements.add(lit) init_graph.edges.add(Edge(init_op, lit, 'effect-of')) for i, p in enumerate(condition.parameters): init_graph.edges.add(Edge(lit, Args[p], i)) return Args, init_graph, goal_graph
def problemToGraphs(problem): """ Returns a dictionary: Keys: 'arg', 'init', 'goal' Values: arg dictionary, (elements, edges), (elements, edges) """ if problem.goalAction is not None: action = problem.goalAction gop = Operator(name=action.name, num_args=len(action.parameters)) GoalAction = Action(name=action.name, root_element=gop) evalActionParams(action.parameters, GoalAction) getFormulaGraph(action.precond.formula, GoalAction, parent=gop, relationship='precond-of', elements=GoalAction.elements, edges=GoalAction.edges) decomp_graph = PlanElementGraph(name=action.name, type_graph='decomp') getDecompGraph(action.decomp.formula, decomp_graph, action.parameters) GoalAction.subgraphs.add(decomp_graph) goal_graph = GoalAction init_op = Operator(name='dummy_init', stepnumber=0, num_args=0) init_graph = Action(name='dummy_init', root_element=init_op) Args = dict() else: Args = { object.name: Argument(name=object.name, typ=object.typeName) for object in problem.objects if not object.typeName.lower() in {'character', 'actor'} } Args.update({ object.name: Actor(name=object.name) for object in problem.objects if object.typeName.lower() in {'character', 'actor'} }) goal_elements, goal_edges = getGoalSet(problem.goal.formula, Args) goal_op = Operator(name='dummy_goal', stepnumber=1, num_args=0) goal_graph = Action(name='dummy_goal', root_element=goal_op) goal_graph.elements.update(goal_elements) goal_graph.edges.update(goal_edges) goal_graph.edges.update({ Edge(goal_op, goal_lit, 'precond-of') for goal_lit in goal_elements if type(goal_lit) is Literal }) init_op = Operator(name='dummy_init', stepnumber=0, num_args=0) init_graph = Action(name='dummy_init', root_element=init_op) for condition in problem.init.predicates: lit = Literal(name=condition.name, num_args=len(condition.parameters), truth=True) init_graph.elements.add(lit) init_graph.edges.add(Edge(init_op, lit, 'effect-of')) for i, p in enumerate(condition.parameters): init_graph.edges.add(Edge(lit, Args[p], ARGLABELS[i])) return (Args, init_graph, goal_graph)
def testDecomp(self): from GlobalContainer import GC story_domain = 'domains/ark-domain.pddl' story_problem = 'domains/ark-problem.pddl' print('Reading {} and {}'.format(story_domain, story_problem)) story = parseDomAndProb(story_domain, story_problem) # (op_graphs, objects, GC.object_types, init, goal) try: SGL = reload('SGL') GC.SGL = SGL except: SGL = GLib(*story) GC.SGL = SGL disc_domain = 'domains/ark-discourse-tests.pddl' disc_problem = 'domains/ark-discourse-tests-problem.pddl' print('Reading {} and {}'.format(disc_domain, disc_problem)) disc = parseDomAndProb(disc_domain, disc_problem) # (op_graphs, objects, GC.object_types, init, goal) try: DGL = reload('DGL') GC.DGL = DGL except: DGL = GLib(*disc, storyGL=SGL) GC.DGL = DGL bi = PlanSpacePlanner(story[1], SGL, disc[1], DGL) results = bi.POCL(5) for R in results: S = R.S print(type(S)) print('\n') print('Story') for step in topoSort(S): print(Action.subgraph(S, step)) for elm in S.elements: print(elm) for edge in S.edges: print(edge) D = R.D print('\nDiscourse') for step in topoSort(D): print(Action.subgraph(D, step)) for elm in D.elements: print(elm) for edge in D.edges: print(edge) print('\n\n')
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 Plannify(RQ, GL): #An ActionLib for steps in RQ - ActionLib is a container w/ all of its possible instances as ground steps print('... Processing {}'.format(RQ.name)) print('...ActionLibs') Libs = [ ActionLib(i, RS, GL) for i, RS in enumerate( [Action.subgraph(RQ, step) for step in RQ.Steps]) ] #A World is a combination of one ground-instance from each step Worlds = productByPosition(Libs) print('...Planets') #A Planet is a plan s.t. all steps are "arg_name consistent", but a step may not be equiv to some ground step Planets = [ PlanElementGraph.Actions_2_Plan(W) for W in Worlds if isArgNameConsistent(W) ] print('...Linkify') #Linkify installs orderings and causal links from RQ/decomp to Planets, rmvs Planets which cannot support links has_links = Linkify(Planets, RQ, GL) print('...Groundify') #Groundify is the process of replacing partial steps with its ground step, and removing inconsistent planets Plans = Groundify(Planets, GL, has_links) print('...returning consistent plans') return [Plan for Plan in Plans if Plan.isInternallyConsistent()]
def testPlanner(self): from GlobalContainer import GC # domain = 'domains/ark-domain.pddl' # problem = 'domains/ark-problem.pddl' #domain = 'domains/ark-domain-decomp.pddl' #problem = 'domains/ark-problem-decomp.pddl' # domain = 'domains/ark-domain-decomp-two.pddl' #problem = 'domains/ark-problem-decomp-two.pddl' #domain = 'domains/ark-domain-decomp-three.pddl' # problem = 'domains/ark-problem-outcomes.pddl' # domain = 'domains/ark-domain-outcomes.pddl' domain = 'domains/h1.pddl' problem = 'domains/h1p1.pddl' print('Reading {} and {}'.format(domain, problem)) try: SGL = reload(domain + problem) GC.SGL = SGL except: SGL = GLib(domain, problem) GC.SGL = SGL pypocl = PlanSpacePlanner(SGL) results = pypocl.POCL(1) for R in results: print(R) for step in topoSort(R): print(Action.subgraph(R, step)) print('\n\n')
def AddNewSteps(UW, other, SSteps, new_plan): for step in UW: if step not in SSteps: S_new = Action.subgraph(other, step).deepcopy() S_new.root.arg_name = step.stepnumber # move pieces new_plan.elements.update(S_new.elements) new_plan.edges.update(S_new.edges) # place in order new_plan.OrderingGraph.addEdge(new_plan.initial_dummy_step, S_new.root) new_plan.OrderingGraph.addEdge(S_new.root, new_plan.final_dummy_step)
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} 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')) new_plan.flaws.addCndtsAndRisks(GL, step)
def POCL(self, num_plans=5): Completed = [] visited = 0 while len(self.Open) > 0: #Select child plan = self.Open.pop() visited += 1 if not plan.isInternallyConsistent(): continue if plan.num_flaws() == 0: print( 'bipartite solution found at {} nodes expanded and {} nodes visited' .format(visited, len(self.Open) + visited)) Completed.append(plan) if len(Completed) == num_plans: return Completed continue elif len(plan.S.flaws) == 0 and not plan.S.solved: plan.S.solved = True print( 'story solution found at {} nodes expanded and {} nodes visited' .format(visited, len(self.Open) + visited)) elif len(plan.D.flaws) == 0 and not plan.D.solved: plan.D.solved = True print( 'disc solution found at {} nodes expanded and {} nodes visited' .format(visited, len(self.Open) + visited)) for step in topoSort(plan.D): print(Action.subgraph(plan.D, step)) print('\n') #Select Flaw k, flaw = plan.next_flaw() #k = 0:story, 1:disc #if k == 1: print('{} selected : {}\n'.format(flaw.name, flaw)) #Add children to Open List children = self.generateChildren(plan, k, flaw) #print('generated children: {}'.format(len(children))) for child in children: self.Open.insert(child)
def domainToOperatorGraphs(domain): opGraphs = set() for action in domain.actions: op = Operator(name=action.name, num_args=len(action.parameters)) op_graph = Action(name=action.name, root_element=op) evalActionParams(action.parameters, op_graph) if action.precond is not None: getFormulaGraph(action.precond.formula, op_graph, parent=op, relationship='precond-of', elements=op_graph.elements, edges=op_graph.edges) if action.effect is not None: getFormulaGraph(action.effect.formula, op_graph, parent=op, relationship='effect-of', elements=op_graph.elements, edges=op_graph.edges) if hasattr(action, 'decomp') and action.decomp is not None: decomp_graph = PlanElementGraph(name=action.name, type_graph='decomp') getDecompGraph(action.decomp.formula, decomp_graph, action.parameters) op_graph.subgraphs.add(decomp_graph) for step_elm in op_graph.elements: for d_elm in decomp_graph.elements: if not isinstance(d_elm, Argument): continue if d_elm.arg_name == step_elm.arg_name: op_graph.assign(step_elm, d_elm) opGraphs.add(op_graph) return opGraphs
def POCL(self, num_plans=5): completed = [] visited = 0 while len(self) > 0: print(visited, len(self)+visited) #Select child #print(self._frontier) plan = self.pop() print(plan.flaws) #print('\n selecting plan: {}'.format(plan)) #print(plan.flaws) visited += 1 if not plan.isInternallyConsistent(): print('pruned') print(plan) print(plan.flaws) continue if len(plan.flaws) == 0: print('\nsolution found at {} nodes expanded and {} nodes visited'.format(visited, len(self)+visited)) completed.append(plan) if len(completed) == num_plans: print('\n') return completed for step in topoSort(plan): print(Action.subgraph(plan, step)) continue #Select Flaw flaw = plan.flaws.next() print('{} selected : {}\n'.format(flaw.name, flaw)) # if flaw.name == 'tclf': # print('{} selected : {}\n'.format(flaw.name, flaw)) # print(plan.flaws) #Add children to Open List children = self.generateChildren(plan, flaw) #print('generated children: {}'.format(len(children))) for child in children: self.insert(child) raise ValueError('Frontier is empty... no plan found')
def reuse(self, plan, flaw, GL): results = set() s_need, precondition = flaw.flaw #antecedents - a set of stepnumbers antecedents = GL.id_dict[precondition.replaced_ID] if len(antecedents) == 0: return set() for s_old in plan.Steps: if s_old.stepnumber not in antecedents: continue if s_old == s_need: continue #step 1 - make a copy of the plan, also replaces the plan number new_plan = plan.deepcopy() #step 2 - Actionize the steps from new_plan S_Old = Action.subgraph(new_plan, s_old) s_need_new = new_plan.getElementById(s_need.ID) #S_Need = Action.subgraph(new_plan, s_need) #step 3-4 retarget precondition to be s_old effect pre_link_sink = self.RetargetPrecondition(GL, new_plan, S_Old, precondition) if pre_link_sink is False: #Can't reuse in discourse case because story elms in disc args refer to different event instances continue #step 5 - add orderings, causal links, and create flaws self.addStep(new_plan, S_Old.root, s_need_new, pre_link_sink, GL, new=False) #step 6 - add new plan to open list results.add(new_plan) return results
def Plannify(RQ, GL): #An ActionLib for steps in RQ - ActionLib is a container w/ all of its possible instances as ground steps print('...ActionLibs') Libs = [ActionLib(i, RS, GL) for i, RS in enumerate([Action.subgraph(RQ, step) for step in RQ.Steps])] #A World is a combination of one ground-instance from each step Worlds = productByPosition(Libs) print('...Planets') #A Planet is a plan s.t. all steps are "arg_name consistent", but a step may not be equiv to some ground step Planets = [PlanElementGraph.Actions_2_Plan(W) for W in Worlds if isArgNameConsistent(W)] print('...Linkify') #Linkify installs orderings and causal links from RQ/decomp to Planets, rmvs Planets which cannot support links has_links = Linkify(Planets, RQ, GL) print('...Groundify') #Groundify is the process of replacing partial steps with its ground step, and removing inconsistent planets Plans = Groundify(Planets, GL, has_links) print('...returning consistent plans') return [Plan for Plan in Plans if Plan.isInternallyConsistent()]
def Groundify(Planets, GL, has_links): print('...Groundify - Unifying Actions with GL') for i, Planet in enumerate(Planets): print("... Planet {}".format(i)) for Step in Planet.Step_Graphs: print('... Unifying {} with {}'.format(Step, GL[Step.stepnumber])) # Unify Actions (1) swaps step graphs with ground step Planet.UnifyActions(Step, GL[Step.stepnumber]) if not has_links: return Planets print('...Groundify - Creating Causal Links') Discovered_Planets = [] for Plan in Planets: #print(Plan) Libs = [LinkLib(i, link, GL) for i, link in enumerate(Plan.CausalLinkGraph.edges)] #LW = [plan1 [link1.condition, link2.condition,..., link-n.condition], # plan2 [link1.condition, link2.condition, ..., link-m.condition], # plan-k [l1,...,lz]] LW = productByPosition(Libs) for lw in LW: # create new Planet ("discovered planet") for each linkworld. NP = Plan.deepcopy() for _link in list(lw): pre_token = GL.getConsistentPrecondition(Action.subgraph(NP, _link.sink), _link.label) #label = NP.getElementByID(_link.label.ID) if pre_token != _link.label: NP.ReplaceSubgraphs(pre_token, _link.label) NP.CausalLinkGraph.edges.remove(_link) NP.CausalLinkGraph.edges.add(Edge(_link.source, _link.sink, Condition.subgraph(NP, _link.label))) Discovered_Planets.append(NP) return Discovered_Planets
def reuse(self, plan, flaw): results = set() s_need, precondition = flaw.flaw #antecedents - a set of stepnumbers antecedents = self.GL.id_dict[precondition.replaced_ID] if len(antecedents) == 0: return set() for s_old in plan.Steps: if s_old.stepnumber not in antecedents: continue if s_old == s_need: continue new_plan = plan.deepcopy() Old = Action.subgraph(new_plan, s_old) effect_token = self.GL.getConsistentEffect(Old, precondition) #joint_literal = self.RetargetPrecondition(self.GL, new_plan, Old, precondition) if Old.is_decomp or s_need.is_decomp: if not isIdenticalElmsInArgs(precondition.Args, Condition.subgraph(Old, effect_token).Args): continue else: print("not identical") effect_edge = new_plan.ReplaceSubgraphs(precondition.root, effect_token) #add step, orderings, causal links, and create flaws self.addStep(new_plan, Old, s_need=new_plan.getElementById(s_need.ID), condition=Condition.subgraph(new_plan, effect_edge.sink), new=False) results.add(new_plan) return results
if __name__ == '__main__': num_args = len(sys.argv) if num_args > 1: domain_file = sys.argv[1] if num_args > 2: problem_file = sys.argv[2] else: #domain_file = 'domains/mini-indy-domain.pddl' #problem_file = 'domains/mini-indy-problem.pddl' domain_file = 'domains/ark-domain.pddl' problem_file = 'domains/ark-problem.pddl' #f = open('workfile', 'w') operators, objects, object_types, initAction, goalAction = parseDomAndProb( domain_file, problem_file) #non_static_preds = preprocessDomain(operators) FlawLib.non_static_preds = preprocessDomain(operators) obtypes = obTypesDict(object_types) Argument.object_types = obtypes planner = PlanSpacePlanner(operators, objects, initAction, goalAction) #planner.story_GL = GLib(operators, story_objs, obtypes, initAction, goalAction) results = planner.POCL(1) for result in results: totOrdering = topoSort(result) print('\n\n\n') for step in topoSort(result): print(Action.subgraph(result, step)) #print(result)
if __name__ == '__main__': num_args = len(sys.argv) if num_args >1: domain_file = sys.argv[1] if num_args > 2: problem_file = sys.argv[2] else: #domain_file = 'domains/mini-indy-domain.pddl' #problem_file = 'domains/mini-indy-problem.pddl' domain_file = 'domains/ark-domain.pddl' problem_file = 'domains/ark-problem.pddl' #f = open('workfile', 'w') operators, objects, object_types, initAction, goalAction = parseDomAndProb(domain_file, problem_file) #non_static_preds = preprocessDomain(operators) FlawLib.non_static_preds = preprocessDomain(operators) obtypes = obTypesDict(object_types) Argument.object_types = obtypes planner = PlanSpacePlanner(operators, objects, initAction, goalAction) #planner.story_GL = GLib(operators, story_objs, obtypes, initAction, goalAction) results = planner.POCL(1) for result in results: totOrdering = topoSort(result) print('\n\n\n') for step in topoSort(result): print(Action.subgraph(result, step)) #print(result)