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 domainToOperatorGraphs(domain, obj_types): 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') params = action.parameters + action.decomp.sub_params param_types = [obj_types[next(iter(p.types))] for p in params] p_type_dict = dict(zip(params, param_types)) getDecompGraph(action.decomp.formula, decomp_graph, params, p_type_dict) 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 build_operators(actions, obj_types, cnsts): primitive_operators = [] composite_operators = [] all_operators = [] for action in actions: # create operator token (a step-typed variable) step_typed_var = Operator(name=action.name, typ=action.action_type, stepnumber=-1, num_args=len(action.parameters)) # create operator with step-typed variable as root operator_template = Action(name=action.name, root_element=step_typed_var) # convert args args = convert_params(action.parameters, obj_types) # if action.decomp is not None: # args = convert_params(action.decomp.sub_params, obj_types) + args operator_template.constants = {cnst.name: cnst for cnst in cnsts} schema = build_operator(action, operator_template, args) if action.decomp is None: primitive_operators.append(schema) else: dargs = args + convert_params(action.decomp.sub_params, obj_types) # initially use all parameters to become decomposition schema args dschema = make_decomp(action.name, dargs, action.decomp.formula, all_operators) dschema.constants = operator_template.constants # bipartite has second decomposition method if type(action.decomp) == BipartiteStmt: disc_params = convert_params(action.decomp.disc_params, obj_types) # use same decomp schema, and just add new parameters build_decomp(action.decomp.disc_formula, disc_params, dschema, all_operators) schema.subplan = dschema schema.subplan.nonequals.update(schema.nonequals) composite_operators.append(schema) all_operators.append(schema) return primitive_operators, composite_operators
def decompile(arg, p): if isinstance(arg, Argument): return arg elif isinstance(arg, Operator): return Action.subgraph(p, arg) elif isinstance(arg, Literal): return Condition.subgraph(p, arg)
def decompile(arg, p): arg_copy = copy.deepcopy(arg) if isinstance(arg, Argument): return arg_copy elif isinstance(arg, Operator): arg_copy.arg_name = str(Action.subgraph(p, arg)) elif isinstance(arg, Literal): arg_copy.arg_name = str(Condition.subgraph(p, arg)) return arg_copy
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 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 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 build_problem_init(problem, args): init_op = Operator(name='dummy_init', stepnumber=0, num_args=0) init_graph = Action(name='dummy_init', root_element=init_op) for i, object in enumerate(args): init_graph.elements.add(object) init_graph.edges.add(Edge(init_op, object, i)) effect_edges = [] for condition in problem.init.predicates: effect = build_literal(condition, init_graph) if effect is None: continue eff_edge = Edge(init_op, effect, 'effect-of') init_graph.edges.add(eff_edge) effect_edges.append(eff_edge) return init_graph, effect_edges
def build_problem_goal(problem, args): goal_op = Operator(name='dummy_goal', stepnumber=1, num_args=0) goal_graph = Action(name='dummy_goal', root_element=goal_op) for i, object in enumerate(args): goal_graph.elements.add(object) goal_graph.edges.add(Edge(goal_op, object, i)) if problem.goal.formula.key != "and": build_literal(problem.goal.formula, goal_graph) else: precond_list = [] for child in problem.goal.formula.children: prec = build_literal(child, goal_graph) if prec is None: continue precond_list.append(prec) goal_graph.edges.add(Edge(goal_op, prec, "precond-of")) return goal_graph
def rewriteElms(GDO, sp, objects, obtypes, h): sp_arg_dict = { elm.arg_name: elm for elm in sp.elements if elm.arg_name is not None } needs_substituting = [] print(GDO) for i, arg in enumerate(GDO.Args): print("arg: " + str(arg)) # if this arg isn't part of sub-plan (is that possible?) if arg.arg_name not in sp_arg_dict.keys(): if arg.name is None: needs_substituting.append(i) continue # raise ValueError("just checking if this is possible") sp_elm = sp_arg_dict[arg.arg_name] print("suplan elm: " + str(sp_elm)) if type(sp_elm) == Operator: A = Action.subgraph(sp, sp_elm) GDO.replaceArg(arg, A.root) # GDO.elements.remove(arg) GDO.elements.update(A.elements) GDO.edges.update(A.edges) elif type(sp_elm) == Literal: C = Condition.subgraph(sp, sp_elm) GDO.replaceArg(arg, C.root) # GDO.elements.remove(arg) GDO.elements.update(C.elements) GDO.edges.update(C.edges) else: # this is an object that should be substituted GDO.replaceArg(arg, sp_elm) print('almost out') GDO.updateArgs() # this may not be needed anymore for (u, v) in GDO.nonequals: if GDO.Args[u] == GDO.Args[v]: return False, None if len(needs_substituting) == 0: return GDO, None return GDO, needs_substituting
def distinguished_steps(GL, gdo, height): dummy_init = Action(name='begin:' + str(gdo.name) + "-" + str(gdo.root.stepnumber) + str([decompile(arg, gdo) for arg in gdo.Args])) dummy_init.has_cndt = False dummy_init.root.name = dummy_init.name for condition in gdo.Preconditions: if condition.name not in GL.non_static_preds: continue dummy_init.edges.add(Edge(dummy_init.root, condition.root, 'effect-of')) dummy_init.edges.update(condition.edges) dummy_init.elements.update(condition.elements) dummy_init.instantiable = False """ One does not need to add preconditions to the dummy_init - these are marked as completed during initial insertion In other words. when we insert a decompositional step, its preconditions are passed to its dummy_init. """ dummy_goal = Action(name='finish:' + str(gdo.name) + "-" + str(gdo.root.stepnumber) + str([decompile(arg, gdo) for arg in gdo.Args])) dummy_goal.is_cndt = False dummy_goal.root.name = dummy_goal.name for condition in gdo.Effects: dummy_goal.edges.add(Edge(dummy_goal.root, condition.root, "effect-of")) dummy_goal.edges.update(condition.edges) dummy_goal.elements.update(condition.elements) if not GL.check_has_effect(condition, height + 1): # this is a pattern effect. continue dummy_goal.edges.add( Edge(dummy_goal.root, condition.root, 'precond-of')) dummy_goal.instantiable = False gdo.sub_dummy_init = dummy_init gdo.sub_dummy_goal = dummy_goal
def Linkify(Planets, RQ, GL): """ :param Planets: A list of plan-element-graphs :param RQ: ReQuirements :param GL: Ground Library :return: List of Plan-element-graphs which include causal link and ordering graphs """ # If there's no causal link requirements, end here. links = RQ.CausalLinkGraph.edges if len(links) == 0: return Planets # return False # For each link, test if the planet supports that link for link in links: indices = [] for i in range(len(Planets)): src = getElementByArgName(Planets[i], link.source.arg_name) snk = getElementByArgName(Planets[i], link.sink.arg_name) cond = getElementByArgName(Action.subgraph(Planets[i], snk), link.label.root.arg_name) Dependency = Condition.subgraph(Planets[i], cond) if src.stepnumber not in GL.ante_dict[snk.stepnumber]: continue if src.stepnumber not in GL.id_dict[cond.replaced_ID]: continue # pass token, not Dependency Planets[i].CausalLinkGraph.addEdge(src, snk, Dependency) Planets[i].OrderingGraph.addEdge(src, snk) indices.append(i) # Remove planets which cannot support link Planets[:] = [Planets[i] for i in indices] if len(Planets) == 0: raise ValueError('no Planet could support links in {}'.format(RQ.name)) return Planets
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 groundDecompStepList(doperators, GL, stepnum=0, height=0): gsteps = [] print('...Creating Ground Decomp Steps') for op in doperators: #Subplans = Plannify(op.subplan, GL) print('processing operator: {}'.format(op)) try: sub_plans = Plannify(op.subplan, GL, height) except: continue for sp in sub_plans: GDO = copy.deepcopy(op) GDO.is_decomp = True if not rewriteElms(GDO, sp, op): continue GDO.root.is_decomp = True # swap constructor IDs and replaced_IDs GDO._replaceInternals() GDO.replaceInternals() # Now create dummy init step and goal step dummy_init = Action(name='begin:' + str(GDO.name)) dummy_init.has_cndt = False dummy_init.root.stepnumber = stepnum for condition in GDO.Preconditions: dummy_init.edges.add( Edge(dummy_init.root, condition.root, 'effect-of')) dummy_init.edges.update(condition.edges) dummy_init.elements.update(condition.elements) gsteps.append(dummy_init) stepnum += 1 dummy_goal = Action(name='finish:' + str(GDO.name)) dummy_goal.is_cndt = False dummy_goal.root.stepnumber = stepnum for condition in GDO.Effects: dummy_goal.edges.add( Edge(dummy_goal.root, condition.root, 'precond-of')) dummy_goal.edges.update(condition.edges) dummy_goal.elements.update(condition.elements) gsteps.append(dummy_goal) stepnum += 1 GDO.sub_dummy_init = dummy_init GDO.sub_dummy_goal = dummy_goal GDO.ground_subplan = sp GDO.root.stepnumber = stepnum sp.root = GDO.root stepnum += 1 GDO.height = height + 1 GDO.root.height = height + 1 # important to add init and goal steps first gsteps.append(GDO) return gsteps
def groundDecompStepList(doperators, GL, stepnum=0, height=0): gsteps = [] print('...Creating Ground Decomp Steps') for op in doperators: #Subplans = Plannify(op.subplan, GL) print('processing operator: {}'.format(op)) try: sub_plans = Plannify(op.subplan, GL, height) except: continue for sp in sub_plans: GDO = copy.deepcopy(op) GDO.is_decomp = True # rewrites operator arguments based on groundings of sub-plan, provides alternatives possible_alternatives = rewriteElms(GDO, sp, op, GL.objects, GL.object_types, height + 1) if not possible_alternatives: continue gdos = [] if type(possible_alternatives) == bool: gdos.append(GDO) else: for gdo in possible_alternatives: gdos.append(gdo) for gdo in gdos: gdo.root.is_decomp = True # swap constructor IDs and replaced_IDs gdo._replaceInternals() gdo.replaceInternals() # Now create dummy init step and goal step dummy_init = Action(name='begin:' + str(gdo.name)) dummy_init.has_cndt = False dummy_init.root.stepnumber = stepnum for condition in gdo.Preconditions: dummy_init.edges.add( Edge(dummy_init.root, condition.root, 'effect-of')) dummy_init.edges.update(condition.edges) dummy_init.elements.update(condition.elements) gsteps.append(dummy_init) stepnum += 1 dummy_goal = Action(name='finish:' + str(gdo.name)) dummy_goal.is_cndt = False dummy_goal.root.stepnumber = stepnum for condition in gdo.Effects: dummy_goal.edges.add( Edge(dummy_goal.root, condition.root, 'precond-of')) dummy_goal.edges.update(condition.edges) dummy_goal.elements.update(condition.elements) gsteps.append(dummy_goal) stepnum += 1 gdo.sub_dummy_init = dummy_init gdo.sub_dummy_goal = dummy_goal gdo.ground_subplan = copy.deepcopy(sp) gdo.root.stepnumber = stepnum gdo.ground_subplan.root = gdo.root stepnum += 1 gdo.height = height + 1 gdo.root.height = height + 1 # important to add init and goal steps first gsteps.append(gdo) # print('Creating ground step w/ height {}, h={}'.format(gdo, height)) return gsteps