Ejemplo n.º 1
0
def transform_action_args(action, fn):
    if isinstance(action, Action):
        name, args = action
        return Action(name, tuple(map(fn, args)))
    elif isinstance(action, DurativeAction):
        name, args, start, duration = action
        return DurativeAction(name, tuple(map(fn, args)), start, duration)
    elif isinstance(action, StreamAction):
        name, inputs, outputs = action
        return StreamAction(name, tuple(map(fn, inputs)),
                            tuple(map(fn, outputs)))
    elif isinstance(action, Assignment):
        args, = action
        return Assignment(tuple(map(fn, args)))
    raise NotImplementedError(action)
Ejemplo n.º 2
0
def transform_action_args(action, fn):
    if isinstance(action, Action):
        name, args = action
        return Action(name, tuple(map(fn, args)))
    elif isinstance(action, DurativeAction):
        action = temporal_from_sequential(action)
        if action is None:
            return None
        name, args, start, duration = action
        return DurativeAction(name, tuple(map(fn, args)), start, duration)
    elif isinstance(action, StreamAction):
        name, inputs, outputs = action
        return StreamAction(name, tuple(map(fn, inputs)),
                            tuple(map(fn, outputs)))
    elif isinstance(action, FunctionAction):
        name, inputs = action
        return FunctionAction(name, tuple(map(fn, inputs)))
    elif isinstance(action, Assignment):
        args, = action
        return Assignment(tuple(map(fn, args)))
    raise NotImplementedError(action)
Ejemplo n.º 3
0
def transform_action_args(action, fn):
    if isinstance(action, Action):
        name, args = action
        return Action(name, tuple(map(fn, args)))
    elif isinstance(action, DurativeAction):
        name, args, start, duration = action
        #name, index = name[:-2], int(name[-1])
        #if index != 0: # TODO: what was this for?
        #    return None
        return DurativeAction(name, tuple(map(fn, args)), start, duration)
    elif isinstance(action, StreamAction):
        name, inputs, outputs = action
        return StreamAction(name, tuple(map(fn, inputs)),
                            tuple(map(fn, outputs)))
    elif isinstance(action, FunctionAction):
        name, inputs = action
        return FunctionAction(name, tuple(map(fn, inputs)))
    elif isinstance(action, Assignment):
        args, = action
        return Assignment(tuple(map(fn, args)))
    raise NotImplementedError(action)
Ejemplo n.º 4
0
def constraint_satisfaction(stream_pddl, stream_map, init, terms, stream_info={},
                            costs=True, max_cost=INF, success_cost=INF, max_time=INF,
                            unit_efforts=False, max_effort=INF,
                            max_skeletons=INF, search_sample_ratio=1, verbose=True, **search_args):
    # Approaches
    # 1) Existential quantification of bindings in goal conditions
    # 2) Backtrack useful streams and then schedule. Create arbitrary outputs for not mentioned.
    # 3) Construct all useful streams and then associate outputs with bindings
    #    Useful stream must satisfy at least one fact. How should these assignments be propagated though?
    #    Make an action that maps each stream result to unbound values?
    # TODO: include functions again for cost-sensitive satisfaction
    # TODO: convert init into streams to bind certain facts
    # TODO: investigate constraint satisfaction techniques for binding instead
    # TODO: could also instantiate all possible free parameters even if not useful
    # TODO: effort that is a function of the number of output parameters (degrees of freedom)
    # TODO: use a CSP solver instead of a planner internally
    # TODO: max_iterations?
    if not terms:
        return {}, 0, init
    constraints, negated, functions = partition_facts(set(map(obj_from_existential_expression, terms)))
    if not costs:
        functions = []
    evaluations = evaluations_from_init(init)
    goal_facts = set(filter(lambda f: evaluation_from_fact(f) not in evaluations, constraints))
    free_parameters = sorted(get_parameters(goal_facts))
    print('Parameters:', free_parameters)

    externals = parse_stream_pddl(stream_pddl, stream_map, stream_info, unit_efforts=unit_efforts)
    stream_results = extract_streams(evaluations, externals, goal_facts)
    function_plan = plan_functions(negated + functions, externals)
    plan_skeleton = [Assignment(free_parameters)]
    cost = get_optimistic_cost(function_plan)
    if max_cost < cost:
        return None, INF, init
    # TODO: detect connected components
    # TODO: eagerly evaluate fully bound constraints

    # TODO: consider other results if this fails
    domain = create_domain(goal_facts)
    init_evaluations = evaluations.copy()
    store = SolutionStore(evaluations, max_time=max_time, success_cost=success_cost, verbose=verbose)
    queue = SkeletonQueue(store, domain, disable=False)
    num_iterations = search_time = sample_time = 0
    planner = 'ff-astar'  # TODO: toggle within reschedule_stream_plan
    #last_clusters = set()
    #last_success = True
    while not store.is_terminated():
        num_iterations += 1
        start_time = time.time()
        print('\nIteration: {} | Skeletons: {} | Skeleton Queue: {} | Evaluations: {} | '
              'Cost: {:.3f} | Search Time: {:.3f} | Sample Time: {:.3f} | Total Time: {:.3f}'.format(
            num_iterations, len(queue.skeletons), len(queue),
            len(evaluations), store.best_cost, search_time, sample_time, store.elapsed_time()))
        external_plan = None
        if len(queue.skeletons) < max_skeletons:
            domain.axioms[:] = create_disabled_axioms(queue, use_parameters=False)
            #dominated = are_domainated(last_clusters, clusters)
            #last_clusters = clusters
            #if last_success or not dominated: # Could also keep a history of results
            stream_plan = reschedule_stream_plan(init_evaluations, goal_facts, domain, stream_results,
                                                 unique_binding=True, unsatisfiable=True,
                                                 max_effort=max_effort, planner=planner, **search_args)
            if stream_plan is not None:
                external_plan = reorder_stream_plan(combine_optimizers(
                    init_evaluations, stream_plan + list(function_plan)))
        print('Stream plan ({}, {:.3f}): {}'.format(
            get_length(external_plan), compute_plan_effort(external_plan), external_plan))
        last_success = (external_plan is not None)
        search_time += elapsed_time(start_time)

        # Once a constraint added for a skeleton, it should only be relaxed
        start_time = time.time()
        if last_success: # Only works if create_disable_axioms never changes
            allocated_sample_time = (search_sample_ratio * search_time) - sample_time
        else:
            allocated_sample_time = INF
        queue.process(external_plan, plan_skeleton, cost=cost,
                      complexity_limit=INF,  max_time=allocated_sample_time)
        sample_time += elapsed_time(start_time)
        if not last_success and not queue:
            break
        # TODO: exhaustively compute all plan skeletons and add to queue within the focused algorithm

    write_stream_statistics(externals, verbose)
    action_plan, cost, facts = revert_solution(store.best_plan, store.best_cost, evaluations)
    bindings = bindings_from_plan(plan_skeleton, action_plan)
    return bindings, cost, facts