def get_stream_action(result, name, unit_cost, effect_scale=1): #from pddl_parser.parsing_functions import parse_action import pddl parameters = [] preconditions = [ fd_from_fact(fact) for fact in result.instance.get_domain() ] precondition = pddl.Conjunction(preconditions) effects = [ pddl.Effect(parameters=[], condition=pddl.Truth(), literal=fd_from_fact(fact)) for fact in result.get_certified() ] effort = 1 if unit_cost else result.instance.get_effort() if effort == INF: return None fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]) expression = pddl.NumericConstant(int_ceil(effect_scale * effort)) # Integer cost = pddl.Increase(fluent=fluent, expression=expression) # Can also be None return pddl.Action(name=name, parameters=parameters, num_external_parameters=len(parameters), precondition=precondition, effects=effects, cost=cost)
def make_cost(cost): if cost is None: return cost fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]) try: expression = pddl.NumericConstant(cost) except TypeError: expression = pddl.PrimitiveNumericExpression( symbol=get_prefix(cost), args=list(map(pddl_from_object, get_args(cost)))) return pddl.Increase(fluent=fluent, expression=expression)
def parse_assignment(alist): assert len(alist) == 3 op = alist[0] head = parse_expression(alist[1]) exp = parse_expression(alist[2]) if op == "=": return pddl.Assign(head, exp) elif op == "increase": return pddl.Increase(head, exp) else: assert False, "Assignment operator not supported."
def parse_assignment(alist): assert len(alist) == 3 op = alist[0] head = parse_expression(alist[1]) exp = parse_expression(alist[2]) if op == "assign" or op == "=": return pddl.Assign(head, exp) elif op == "scale-up": return pddl.ScaleUp(head, exp) elif op == "scale-down": return pddl.ScaleDown(head, exp) elif op == "increase": return pddl.Increase(head, exp) elif op == "decrease": return pddl.Decrease(head, exp) else: assert False, "Assignment operator not supported."
def compile_to_exogenous_actions(evaluations, domain, streams): import pddl # TODO: automatically derive fluents # TODO: version of this that operates on fluents of length one? # TODO: better instantiation when have full parameters # TODO: conversion from stream cost to real cost units? # TODO: any predicates derived would need to be replaced as well fluent_predicates = get_fluents(domain) domain_predicates = {get_prefix(a) for s in streams for a in s.domain} if not (domain_predicates & fluent_predicates): return certified_predicates = {get_prefix(a) for s in streams for a in s.certified} future_map = {p: 'f-{}'.format(p) for p in certified_predicates} augment_evaluations(evaluations, future_map) rename_future = lambda a: rename_atom(a, future_map) for stream in list(streams): if not isinstance(stream, Stream): raise NotImplementedError(stream) # TODO: could also just have conditions asserting that one of the fluent conditions fails streams.append(create_static_stream(stream, evaluations, fluent_predicates, rename_future)) stream_atom = streams[-1].certified[0] parameters = [pddl.TypedObject(p, 'object') for p in get_args(stream_atom)] # TODO: add to predicates as well? domain.predicate_dict[get_prefix(stream_atom)] = pddl.Predicate(get_prefix(stream_atom), parameters) precondition = pddl.Conjunction(tuple(map(fd_from_fact, (stream_atom,) + tuple(stream.domain)))) effects = [pddl.Effect(parameters=[], condition=pddl.Truth(), literal=fd_from_fact(fact)) for fact in stream.certified] effort = 1 # TODO: use stream info #effort = 1 if unit_cost else result.instance.get_effort() #if effort == INF: # continue fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]) expression = pddl.NumericConstant(int_ceil(effort)) # Integer cost = pddl.Increase(fluent=fluent, expression=expression) # Can also be None domain.actions.append(pddl.Action(name='call-{}'.format(stream.name), parameters=parameters, num_external_parameters=len(parameters), precondition=precondition, effects=effects, cost=cost)) stream.certified = tuple(set(stream.certified) | set(map(rename_future, stream.certified)))
def simplify_actions(opt_evaluations, action_plan, task, actions, unit_costs): # TODO: add ordering constraints to simplify the optimization import pddl import instantiate fluent_facts = MockSet() init_facts = set() type_to_objects = instantiate.get_objects_by_type(task.objects, task.types) results_from_head = get_results_from_head(opt_evaluations) action_from_name = {} function_plan = set() for i, (name, args) in enumerate(action_plan): action = find_unique(lambda a: a.name == name, actions) assert (len(action.parameters) == len(args)) # parameters = action.parameters[:action.num_external_parameters] var_mapping = {p.name: a for p, a in zip(action.parameters, args)} new_name = '{}-{}'.format(name, i) new_parameters = action.parameters[len(args):] new_preconditions = [] action.precondition.instantiate(var_mapping, init_facts, fluent_facts, new_preconditions) new_effects = [] for eff in action.effects: eff.instantiate(var_mapping, init_facts, fluent_facts, type_to_objects, new_effects) new_effects = [pddl.Effect([], pddl.Conjunction(conditions), effect) for conditions, effect in new_effects] cost = pddl.Increase(fluent=pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]), expression=pddl.NumericConstant(1)) # cost = None task.actions.append(pddl.Action(new_name, new_parameters, len(new_parameters), pddl.Conjunction(new_preconditions), new_effects, cost)) action_from_name[new_name] = (name, map(obj_from_pddl, args)) if not unit_costs: function_result = extract_function_results(results_from_head, action, args) if function_result is not None: function_plan.add(function_result) return action_from_name, list(function_plan)
def sequential_stream_plan(evaluations, goal_expression, domain, stream_results, negated, unit_costs=True, **kwargs): if negated: raise NotImplementedError() # TODO: compute preimage and make that the goal instead opt_evaluations = evaluations_from_stream_plan(evaluations, stream_results) opt_task = task_from_domain_problem(domain, get_problem(opt_evaluations, goal_expression, domain, unit_costs)) action_plan, action_cost = solve_from_task(opt_task, **kwargs) if action_plan is None: return None, action_cost import instantiate fluent_facts = MockSet() init_facts = set() task = task_from_domain_problem(domain, get_problem(evaluations, goal_expression, domain, unit_costs)) type_to_objects = instantiate.get_objects_by_type(task.objects, task.types) task.actions, stream_result_from_name = get_stream_actions(stream_results) results_from_head = get_results_from_head(opt_evaluations) # TODO: add ordering constraints to simplify the optimization import pddl action_from_name = {} function_plan = set() for i, (name, args) in enumerate(action_plan): action = find_unique(lambda a: a.name == name, domain.actions) assert(len(action.parameters) == len(args)) #parameters = action.parameters[:action.num_external_parameters] var_mapping = {p.name: a for p, a in zip(action.parameters, args)} new_name = '{}-{}'.format(name, i) new_parameters = action.parameters[len(args):] new_preconditions = [] action.precondition.instantiate(var_mapping, init_facts, fluent_facts, new_preconditions) new_effects = [] for eff in action.effects: eff.instantiate(var_mapping, init_facts, fluent_facts, type_to_objects, new_effects) new_effects = [pddl.Effect([], pddl.Conjunction(conditions), effect) for conditions, effect in new_effects] cost = pddl.Increase(fluent=pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]), expression=pddl.NumericConstant(1)) #cost = None task.actions.append(pddl.Action(new_name, new_parameters, 0, pddl.Conjunction(new_preconditions), new_effects, cost)) action_from_name[new_name] = (name, map(obj_from_pddl, args)) if not unit_costs: function_plan.update(extract_function_results(results_from_head, action, args)) planner = kwargs.get('planner', 'ff-astar') combined_plan, _ = solve_from_task(task, planner=planner, **kwargs) if combined_plan is None: return None, obj_from_pddl_plan(action_plan), INF stream_plan = [] action_plan = [] for name, args in combined_plan: if name in stream_result_from_name: stream_plan.append(stream_result_from_name[name]) else: action_plan.append(action_from_name[name]) stream_plan += list(function_plan) combined_plan = stream_plan + action_plan return combined_plan, action_cost
def make_cost(cost): fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]) expression = pddl.NumericConstant(cost) return pddl.Increase(fluent=fluent, expression=expression)