Beispiel #1
0
def recursive_solve_stream_plan(evaluations, streams, functions,
                                stream_results, solve_stream_plan, depth):
    # TODO: check empty plan first?
    combined_plan, cost = solve_stream_plan(stream_results)
    stream_plan, action_plan = separate_plan(combined_plan,
                                             action_info=None,
                                             terminate=False,
                                             stream_only=False)
    #dump_plans(stream_plan, action_plan, cost)
    #create_visualizations(evaluations, stream_plan, depth)
    if stream_plan is None:
        return stream_plan, cost, depth
    plan_index = get_stream_plan_index(stream_plan)
    if plan_index == 0:
        return combined_plan, cost, depth
    if not RECURSIVE:  # TODO: not quite right
        return None, cost, depth
    # TODO: should I just plan using all original plus expanded
    # TODO: might need new actions here (such as a move)
    stream_results, bindings = optimistic_process_stream_plan(
        evaluations, stream_plan)

    # TODO: plan up to first action that only has one
    # Only use actions in the states between the two
    # planned_instances = []
    # for name, args in action_plan:
    #     input_objects = [bindings.get(i, [i]) for i in args]
    #     instances = []
    #     for combo in product(*input_objects):
    #         # TODO: prune actions that aren't feasible
    #         instances.append((name, combo))
    #     planned_instances.append(instances)
    # print(action_plan)
    # print(planned_instances)

    if not ONLY_LOCAL:
        # I don't think the double bound thing really makes entire sense here
        double_bindings = {
            v: k
            for k, values in bindings.items() if 2 <= len(values)
            for v in values
        }
        stream_results.extend(
            optimistic_process_streams(evaluations_from_stream_plan(
                evaluations, stream_results),
                                       streams,
                                       double_bindings=double_bindings))
    stream_results += optimistic_process_streams(
        evaluations_from_stream_plan(evaluations, stream_results), functions)
    return recursive_solve_stream_plan(evaluations, streams, functions,
                                       stream_results, solve_stream_plan,
                                       depth + 1)
Beispiel #2
0
def locally_optimize(evaluations, store, goal_expression, domain, functions, negative,
                     dynamic_streams, visualize, sampling_time=0):
    action_plan = store.best_plan
    if action_plan is None:
        return None
    print('\nPostprocessing | Cost: {} | Total Time: {:.3f}'.format(store.best_cost, store.elapsed_time()))
    # TODO: postprocess current skeletons as well

    task = task_from_domain_problem(domain, get_problem(evaluations, goal_expression, domain, unit_costs=False))
    opt_stream_plan, opt_from_obj = recover_opt_stream_plan(evaluations, action_plan, task)
    opt_stream_plan += optimistic_process_streams(evaluations_from_stream_plan(evaluations, opt_stream_plan), functions)
    opt_action_plan = [(name, tuple(opt_from_obj.get(o, o) for o in args)) for name, args in action_plan]
    pddl_plan = [(name, tuple(map(pddl_from_object, args))) for name, args in opt_action_plan]
    stream_plan = recover_stream_plan(evaluations, goal_expression, domain,
                                      opt_stream_plan, pddl_plan, negative, unit_costs=False)
    stream_plan = get_synthetic_stream_plan(reorder_stream_plan(stream_plan), dynamic_streams)


    # TODO: need to make this just streams
    opt_evaluations = apply_streams(evaluations, stream_plan)
    opt_cost = get_plan_cost(opt_evaluations, opt_action_plan, domain, unit_costs=False)
    dump_plans(stream_plan, opt_action_plan, opt_cost)
    if visualize:
        log_plans(stream_plan, action_plan, None)
        create_visualizations(evaluations, stream_plan, None)

    store.start_time = time.time()
    store.max_cost = store.best_cost
    queue = SkeletonQueue(store, evaluations, goal_expression, domain)
    queue.new_skeleton(stream_plan, opt_action_plan, opt_cost)
    queue.greedily_process()
    queue.timed_process(sampling_time)
Beispiel #3
0
def recover_stream_plan(evaluations, current_plan, opt_evaluations,
                        goal_expression, domain, node_from_atom, action_plan,
                        axiom_plans, negative):
    # Universally quantified conditions are converted into negative axioms
    # Existentially quantified conditions are made additional preconditions
    # Universally quantified effects are instantiated by doing the cartesian produce of types (slow)
    # Added effects cancel out removed effects
    # TODO: node_from_atom is a subset of opt_evaluations (only missing functions)
    real_task = task_from_domain_problem(
        domain, get_problem(evaluations, goal_expression, domain))
    opt_task = task_from_domain_problem(
        domain, get_problem(opt_evaluations, goal_expression, domain))
    negative_from_name = get_negative_predicates(negative)

    real_states, combined_plan = recover_negative_axioms(
        real_task, opt_task, axiom_plans, action_plan, negative_from_name)
    function_plan = compute_function_plan(opt_evaluations, action_plan)

    full_preimage = plan_preimage(combined_plan, [])
    stream_preimage = set(full_preimage) - real_states[0]
    negative_preimage = set(
        filter(lambda a: a.predicate in negative_from_name, stream_preimage))
    function_plan.update(
        convert_negative(negative_preimage, negative_from_name, full_preimage,
                         real_states))
    positive_preimage = stream_preimage - negative_preimage

    step_from_fact = {
        fact_from_fd(l): full_preimage[l]
        for l in positive_preimage if not l.negated
    }
    target_facts = {
        fact
        for fact in step_from_fact.keys() if get_prefix(fact) != EQ
    }
    #stream_plan = reschedule_stream_plan(evaluations, target_facts, domain, stream_results)
    # visualize_constraints(map(fact_from_fd, target_facts))

    stream_plan = []
    for result in current_plan:
        if isinstance(result.external, Function) or (result.external
                                                     in negative):
            function_plan.add(
                result)  # Prevents these results from being pruned
        else:
            stream_plan.append(result)
    curr_evaluations = evaluations_from_stream_plan(evaluations,
                                                    stream_plan,
                                                    max_effort=None)
    extraction_facts = target_facts - set(
        map(fact_from_evaluation, curr_evaluations))
    extract_stream_plan(node_from_atom, extraction_facts, stream_plan)
    stream_plan = postprocess_stream_plan(evaluations, domain, stream_plan,
                                          target_facts)
    stream_plan = convert_fluent_streams(stream_plan, real_states, action_plan,
                                         step_from_fact, node_from_atom)

    return stream_plan + list(function_plan)
Beispiel #4
0
def compute_stream_results(evaluations, opt_results, externals, complexity_limit, **effort_args):
    # TODO: start from the original evaluations or use the stream plan preimage
    # TODO: only use streams in the states between the two actions
    # TODO: apply hierarchical planning to restrict the set of streams that considered on each subproblem
    # TODO: plan up to first action that only has one
    # TODO: revisit considering double bound streams
    functions = list(filter(lambda s: type(s) is Function, externals))
    opt_evaluations = evaluations_from_stream_plan(evaluations, opt_results)
    new_results, _ = optimistic_process_streams(opt_evaluations, functions, complexity_limit, **effort_args)
    return opt_results + new_results
Beispiel #5
0
def get_combined_orders(evaluations, stream_plan, action_plan, domain):
    if action_plan is None:
        return None
    # TODO: could just do this within relaxed
    # TODO: do I want to strip the fluents and just do the partial ordering?

    stream_instances = get_stream_instances(stream_plan)
    negative_results = filter(
        lambda r: isinstance(r, PredicateResult) and (r.value == False),
        stream_plan)
    negative_init = set(
        fd_from_evaluation(evaluation_from_fact(f)) for r in negative_results
        for f in r.get_certified())
    #negated_from_name = {r.instance.external.name for r in negative_results}
    opt_evaluations = evaluations_from_stream_plan(evaluations, stream_plan)
    goal_expression = And()
    task = task_from_domain_problem(
        domain,
        get_problem(opt_evaluations, goal_expression, domain, unit_costs=True))

    action_instances = get_action_instances(task, action_plan)
    replace_derived(task, negative_init, action_instances)

    #combined_instances = stream_instances + action_instances
    orders = set()
    for i, a1 in enumerate(action_plan):
        for a2 in action_plan[i + 1:]:
            orders.add((a1, a2))
    # TODO: just store first achiever here
    for i, instance1 in enumerate(stream_instances):
        for j in range(i + 1, len(stream_instances)):
            effects = {e for _, e in instance1.add_effects}
            if effects & set(stream_instances[j].precondition):
                orders.add((stream_plan[i], stream_plan[j]))
    for i, instance1 in enumerate(stream_instances):
        for j, instance2 in enumerate(action_instances):
            effects = {e for _, e in  instance1.add_effects} | \
                      {e.negate() for _, e in  instance1.del_effects}
            if effects & set(instance2.precondition):
                orders.add((stream_plan[i], action_plan[j]))
    return orders
Beispiel #6
0
def sequential_stream_plan(evaluations, goal_expression, domain, stream_results,
                           negated, effort_weight, unit_costs=True, debug=False, **kwargs):
    # Intuitively, actions have infinitely more weight than streams
    if negated:
        raise NotImplementedError(negated)
    for result in stream_results:
        if isinstance(result.external, Stream) and result.external.is_fluent():
            raise NotImplementedError('Fluents are not supported')

    # 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 = abstrips_solve_from_task(sas_from_pddl(opt_task, debug=debug), debug=debug, **kwargs)
    if action_plan is None:
        return None, action_cost

    actions = domain.actions[:]
    domain.actions[:] = []
    stream_domain, stream_result_from_name = add_stream_actions(domain, stream_results) # TODO: effort_weight
    domain.actions.extend(actions)
    stream_task = task_from_domain_problem(stream_domain, get_problem(evaluations, goal_expression, stream_domain, unit_costs))
    action_from_name, function_plan = simplify_actions(opt_evaluations, action_plan, stream_task, actions, unit_costs)

    # TODO: lmcut?
    combined_plan, _ = solve_from_task(sas_from_pddl(opt_task, debug=debug),
                                       planner=kwargs.get('planner', 'ff-astar'),
                                       debug=debug, **kwargs)
    if combined_plan is None:
        return None, 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])
    combined_plan = stream_plan + function_plan + action_plan
    return combined_plan, action_cost