def reinstantiate_action_instances(task, old_instances): import pddl import instantiate # Recomputes the instances with without any pruned preconditions fluents = get_fluents(task) function_assignments = { fact.fluent: fact.expression for fact in task.init if isinstance(fact, pddl.f_expression.FunctionAssignment) } type_to_objects = instantiate.get_objects_by_type(task.objects, task.types) init_facts = set() fluent_facts = MockSet() new_instances = [] state = set(task.init) for old_instance in old_instances: # TODO: better way of instantiating conditional effects (when not fluent) #new_instance = reinstantiate_action(old_instance) predicate_to_atoms = instantiate.get_atoms_by_predicate({ a for a in state if isinstance(a, pddl.Atom) and (a.predicate in fluents) }) action = old_instance.action var_mapping = old_instance.var_mapping new_instance = action.instantiate(var_mapping, init_facts, fluent_facts, type_to_objects, task.use_min_cost_metric, function_assignments, predicate_to_atoms) assert (new_instance is not None) new_instances.append(new_instance) apply_action(state, new_instance) new_instances.append(get_goal_instance(task.goal)) # TODO: move this? return new_instances
def compile_to_exogenous_actions(evaluations, domain, streams): # TODO: version of this that operates on fluents of length one? # TODO: better instantiation when have full parameters fluent_predicates = get_fluents(domain) 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) future_fn = lambda a: rename_atom(a, future_map) new_streams = [] 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 new_streams.append(create_static_stream(stream, evaluations, fluent_predicates, future_fn)) stream_atom = new_streams[-1].certified[0] add_predicate(domain, make_predicate(get_prefix(stream_atom), get_args(stream_atom))) preconditions = [stream_atom] + list(stream.domain) effort = 1 # TODO: use stream info #effort = 1 if unit_cost else result.instance.get_effort() #if effort == INF: # continue domain.actions.append(make_action( name='call-{}'.format(stream.name), parameters=get_args(stream_atom), preconditions=preconditions, effects=stream.certified, cost=effort)) stream.certified = tuple(set(stream.certified) | set(map(future_fn, stream.certified))) if REPLACE_STREAM: streams.extend(new_streams) else: streams[:] = new_streams
def reuse_facts(problem, certificate, skeleton): # TODO: repackage streams # TODO: recover the full axiom + action plan # TODO: recover the plan preimage annotated with use time # Some supporting args are quantified out and thus lack some facts new_facts = [] if skeleton is None: return new_facts reuse_objs = set() for action, args in skeleton: for arg in args: if (arg != WILD) and not is_parameter(arg): reuse_objs.add(hash_or_id(arg)) # The reuse relpose omission is due to the fact that the initial pose was selected # (which is populated in the initial state) order_predicate = ORDER_PREDICATE.format('') domain = parse_domain(problem.domain_pddl) fluents = get_fluents(domain) for fact in certificate.preimage_facts: predicate = get_prefix(fact) if (predicate in {order_predicate, EQ}) or (predicate in fluents): # Could technically evaluate functions as well continue if all( isinstance(arg, str) or (hash_or_id(arg) in reuse_objs) for arg in get_args(fact)): new_facts.append(fact) return new_facts
def compile_to_exogenous_axioms(evaluations, domain, streams): # TODO: no attribute certified # TODO: recover the streams that are required import pddl fluent_predicates = get_fluents(domain) 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) future_fn = lambda a: rename_atom(a, future_map) derived_map = {p: 'd-{}'.format(p) for p in certified_predicates} derived_fn = lambda a: rename_atom(a, derived_map) # TODO: could prune streams that don't need this treatment for action in domain.actions: action.precondition = replace_predicates(derived_map, action.precondition) for effect in action.effects: assert (isinstance(effect, pddl.Effect)) effect.condition = replace_predicates(derived_map, effect.condition) for axiom in domain.axioms: axiom.condition = replace_predicates(derived_map, axiom.condition) #fluent_predicates.update(certified_predicates) new_streams = [] for stream in list(streams): if not isinstance(stream, Stream): raise NotImplementedError(stream) new_streams.append( create_static_stream(stream, evaluations, fluent_predicates, future_fn)) stream_atom = new_streams[-1].certified[0] add_predicate( domain, make_predicate(get_prefix(stream_atom), get_args(stream_atom))) preconditions = [stream_atom] + list(map(derived_fn, stream.domain)) for certified_fact in stream.certified: derived_fact = derived_fn(certified_fact) external_params = get_args(derived_fact) internal_params = tuple(p for p in (stream.inputs + stream.outputs) if p not in get_args(derived_fact)) domain.axioms.extend([ make_axiom(parameters=external_params, preconditions=[certified_fact], derived=derived_fact), make_axiom(parameters=external_params + internal_params, preconditions=preconditions, derived=derived_fact), ]) stream.certified = tuple( set(stream.certified) | set(map(future_fn, stream.certified))) if REPLACE_STREAM: streams.extend(new_streams) else: streams[:] = new_streams
def partition_facts(domain, facts): fluents = get_fluents(domain) static_facts = [] fluent_facts = [] for fact in facts: if get_prefix(get_function(fact)).lower() in fluents: fluent_facts.append(fact) else: static_facts.append(fact) return static_facts, fluent_facts
def instantiate_domain(task, prune_static=True): fluent_predicates = get_fluents(task) is_static = lambda a: isinstance(a, pddl.Atom) and (a.predicate not in fluent_predicates) fluent_facts = MockSet(lambda a: not prune_static or not is_static(a)) init_facts = set(task.init) function_assignments = get_function_assignments(task) type_to_objects = instantiate.get_objects_by_type(task.objects, task.types) constants_from_predicate = defaultdict(set) for action in task.actions + task.axioms: for atom in filter(is_static, get_literals(get_precondition(action))): constants = tuple((i, a) for i, a in enumerate(atom.args) if not is_parameter(a)) constants_from_predicate[atom.predicate].add(constants) predicate_to_atoms = defaultdict(set) args_from_predicate = defaultdict(set) for atom in filter(is_static, task.init): # TODO: compute which predicates might involve constants predicate_to_atoms[atom.predicate].add(atom) args_from_predicate[atom.predicate].add(atom.args) for constants in constants_from_predicate[atom.predicate]: if all(atom.args[i] == o for i, o in constants): args_from_predicate[atom.predicate, constants].add(atom.args) instantiated_actions = [] for action in task.actions: for variable_mapping in instantiate_condition(action, is_static, args_from_predicate): inst_action = action.instantiate(variable_mapping, init_facts, fluent_facts, type_to_objects, task.use_min_cost_metric, function_assignments, predicate_to_atoms) if inst_action: instantiated_actions.append(inst_action) instantiated_axioms = [] for axiom in task.axioms: for variable_mapping in instantiate_condition(axiom, is_static, args_from_predicate): inst_axiom = axiom.instantiate(variable_mapping, init_facts, fluent_facts) if inst_axiom: instantiated_axioms.append(inst_axiom) reachable_facts, reachable_operators = get_achieving_axioms(init_facts, instantiated_actions + instantiated_axioms) atoms = {atom for atom in (init_facts | set(reachable_facts)) if isinstance(atom, pddl.Atom)} relaxed_reachable = all(literal_holds(init_facts, goal) or goal in reachable_facts for goal in instantiate_goal(task.goal)) reachable_actions = [action for action in reachable_operators if isinstance(action, pddl.PropositionalAction)] reachable_axioms = [axiom for axiom in reachable_operators if isinstance(axiom, pddl.PropositionalAxiom)] return relaxed_reachable, atoms, reachable_actions, reachable_axioms
def apply_actions(domain, state, plan, unit_costs=False): # Goal serialization just assumes the tail of the plan includes an abstract action to achieve each condition static_state, _ = partition_facts(domain, state) print('Static:', static_state) # TODO: might need properties that involve an object that aren't useful yet evaluations = evaluations_from_init(state) #goal_exp = obj_from_value_expression(goal) goal_exp = None problem = get_problem(evaluations, goal_exp, domain, unit_costs) task = task_from_domain_problem(domain, problem) task.init = set(task.init) for instance in get_action_instances( task, transform_plan_args(plan, Object.from_value)): apply_action(task.init, instance) fluents = get_fluents(domain) fluent_state = [ value_from_evaluation(evaluation_from_fd(atom)) for atom in task.init if isinstance(atom, pddl.Atom) and atom.predicate in fluents ] print('Fluent:', fluent_state) state = static_state + fluent_state return state
def get_exogenous_predicates(domain, streams): fluent_predicates = get_fluents(domain) domain_predicates = {get_prefix(a) for s in streams for a in s.domain} return list(domain_predicates & fluent_predicates)
def get_exogenous_predicates(domain, streams): return list(get_fluents(domain) & get_domain_predicates(streams))