def retrace_instantiation(fact, streams, evaluations, free_parameters, visited_facts, planned_results): # Makes two assumptions: # 1) Each stream achieves a "primary" fact that uses all of its inputs + outputs # 2) Outputs are only free parameters (no constants) if (evaluation_from_fact(fact) in evaluations) or (fact in visited_facts): return visited_facts.add(fact) for stream in streams: for cert in stream.certified: if get_prefix(fact) == get_prefix(cert): mapping = get_mapping(get_args(cert), get_args(fact)) # Should be same anyways if not all(p in mapping for p in (stream.inputs + stream.outputs)): # TODO: assumes another effect is sufficient for binding # Create arbitrary objects for inputs/outputs that aren't mentioned # Can lead to incorrect ordering continue input_objects = safe_apply_mapping(stream.inputs, mapping) output_objects = safe_apply_mapping(stream.outputs, mapping) if not all(out in free_parameters for out in output_objects): # Can only bind if free continue instance = stream.get_instance(input_objects) for new_fact in instance.get_domain(): retrace_instantiation(new_fact, streams, evaluations, free_parameters, visited_facts, planned_results) planned_results.append(instance.get_result(output_objects))
def fn(literal, action): if literal.predicate not in predicate_map: return literal # TODO: other checks on only inputs stream = predicate_map[literal.predicate] mapping = remap_certified(literal, stream) if mapping is None: # TODO: this excludes typing. This is not entirely safe return literal output_args = set(mapping[arg] for arg in stream.outputs) if isinstance(action, pddl.Action): # TODO: unified Action/Axiom effects for effect in action.effects: if isinstance(effect, pddl.Effect) and (output_args & set(effect.literal.args)): raise RuntimeError('Fluent stream outputs cannot be in action effects: {}'.format( effect.literal.predicate)) elif not stream.is_negated: axiom = action raise RuntimeError('Fluent stream outputs cannot be in an axiom: {}'.format(axiom.name)) blocked_args = safe_apply_mapping(stream.inputs, mapping) blocked_literal = literal.__class__(stream.blocked_predicate, blocked_args).negate() if stream.is_negated: conditions = [blocked_literal] conditions.extend(pddl.Atom(get_prefix(fact), safe_apply_mapping(get_args(fact), mapping)) # fd_from_fact for fact in stream.domain) # TODO: be careful when using imply return pddl.Conjunction(conditions) # TODO: prune redundant conditions return pddl.Conjunction([literal, blocked_literal])
def _add_combinations(self, stream, atoms): if not all(atoms): return domain = list(map(head_from_fact, stream.domain)) # Most constrained variable/atom to least constrained for combo in product(*atoms): mapping = test_mapping(domain, combo) if mapping is not None: input_objects = safe_apply_mapping(stream.inputs, mapping) self.push_instance(stream.get_instance(input_objects))
def opt_from_graph(names, orders, infos={}): param_from_order = {order: PARAM_TEMPLATE.format(*order) for order in orders} fact_from_order = {order: (PREDICATE, param_from_order[order]) for order in orders} object_from_param = {param: parse_value(param) for param in param_from_order.values()} incoming_from_edges, outgoing_from_edges = neighbors_from_orders(orders) stream_plan = [] for i, n in enumerate(names): #info = infos.get(n, StreamInfo(p_success=1, overhead=0, verbose=True)) inputs = [param_from_order[n2, n] for n2 in incoming_from_edges[n]] outputs = [param_from_order[n, n2] for n2 in outgoing_from_edges[n]] #gen = get_gen(outputs=outputs, p_success=info.p_success) #gen = get_gen(infos[i], outputs=outputs) stream = Stream( name=n, #gen_fn=DEBUG, #gen_fn=from_gen(gen), gen_fn=from_gen_fn(get_gen_fn(outputs=outputs, **infos[i])), inputs=inputs, domain=[fact_from_order[n2, n] for n2 in incoming_from_edges[n]], fluents=[], outputs=outputs, certified=[fact_from_order[n, n2] for n2 in outgoing_from_edges[n]], #info=info, info=StreamInfo(), ) # TODO: dump names print() print(stream) input_objects = safe_apply_mapping(stream.inputs, object_from_param) instance = stream.get_instance(input_objects) print(instance) output_objects = safe_apply_mapping(stream.outputs, object_from_param) result = instance.get_result(output_objects) print(result) stream_plan.append(result) opt_plan = OptPlan(action_plan=[], preimage_facts=[]) opt_solution = OptSolution(stream_plan, opt_plan, cost=1) return opt_solution
def _add_combinations_relation(self, stream, atoms): if not all(atoms): return # TODO: might be a bug here? domain = list(map(head_from_fact, stream.domain)) # TODO: compute this first? relations = [ Relation(filter(is_parameter, domain[index].args), [ tuple(a for a, b in safe_zip(atom.args, domain[index].args) if is_parameter(b)) for atom in atoms[index] ]) for index in compute_order(domain, atoms) ] solution = solve_satisfaction(relations) for element in solution.body: mapping = solution.get_mapping(element) input_objects = safe_apply_mapping(stream.inputs, mapping) self.push_instance(stream.get_instance(input_objects))
def select_inputs(instance, inputs): external = instance.external assert set(inputs) <= set(external.inputs) mapping = get_mapping(external.inputs, instance.input_objects) return safe_apply_mapping(inputs, mapping)