Beispiel #1
0
def solve_current(problem, **search_kwargs):
    """
    Solves a PDDLStream problem without applying any streams
    Will fail if the problem requires stream applications
    :param problem: a PDDLStream problem
    :param search_kwargs: keyword args for the search subroutine
    :return: a tuple (plan, cost, evaluations) where plan is a sequence of actions
        (or None), cost is the cost of the plan, and evaluations is init but expanded
        using stream applications
    """
    evaluations, goal_expression, domain, stream_name, externals = parse_problem(
        problem)
    compile_to_exogenous(evaluations, domain, externals)
    plan, cost = solve_finite(evaluations, goal_expression, domain,
                              **search_kwargs)
    return revert_solution(plan, cost, evaluations)
Beispiel #2
0
def solve_exhaustive(problem, max_time=300, verbose=True, **search_kwargs):
    """
    Solves a PDDLStream problem by applying all possible streams and searching once
    Requires a finite max_time when infinitely many stream instances
    :param problem: a PDDLStream problem
    :param max_time: the maximum amount of time to apply streams
    :param verbose: if True, this prints the result of each stream application
    :param search_kwargs: keyword args for the search subroutine
    :return: a tuple (plan, cost, evaluations) where plan is a sequence of actions
        (or None), cost is the cost of the plan, and evaluations is init but expanded
        using stream applications
    """
    start_time = time.time()
    evaluations, goal_expression, domain, stream_name, externals = parse_problem(
        problem)
    compile_to_exogenous(evaluations, domain, externals)
    instantiator = Instantiator(evaluations, externals)
    while instantiator.stream_queue and (elapsed_time(start_time) < max_time):
        process_stream_queue(instantiator, evaluations, verbose=verbose)
    plan, cost = solve_finite(evaluations, goal_expression, domain,
                              **search_kwargs)
    return revert_solution(plan, cost, evaluations)
Beispiel #3
0
def solve_incremental(problem,
                      max_time=INF,
                      max_cost=INF,
                      layers=1,
                      verbose=True,
                      **search_kwargs):
    """
    Solves a PDDLStream problem by alternating between applying all possible streams and searching
    :param problem: a PDDLStream problem
    :param max_time: the maximum amount of time to apply streams
    :param max_cost: a strict upper bound on plan cost
    :param layers: the number of stream application layers per iteration
    :param verbose: if True, this prints the result of each stream application
    :param search_kwargs: keyword args for the search subroutine
    :return: a tuple (plan, cost, evaluations) where plan is a sequence of actions
        (or None), cost is the cost of the plan, and evaluations is init but expanded
        using stream applications
    """
    store = SolutionStore(max_time, max_cost,
                          verbose)  # TODO: include other info here?
    evaluations, goal_expression, domain, _, externals = parse_problem(problem)
    compile_to_exogenous(evaluations, domain, externals)
    instantiator = Instantiator(evaluations, externals)
    num_iterations = 0
    while not store.is_terminated():
        num_iterations += 1
        print(
            'Iteration: {} | Evaluations: {} | Cost: {} | Time: {:.3f}'.format(
                num_iterations, len(evaluations), store.best_cost,
                store.elapsed_time()))
        function_process_stream_queue(instantiator, evaluations, store)
        plan, cost = solve_finite(evaluations, goal_expression, domain,
                                  **search_kwargs)
        store.add_plan(plan, cost)
        if not instantiator.stream_queue:
            break
        layered_process_stream_queue(instantiator, evaluations, store, layers)
    return revert_solution(store.best_plan, store.best_cost, evaluations)
Beispiel #4
0
def solve_focused(problem,
                  stream_info={},
                  action_info={},
                  synthesizers=[],
                  max_time=INF,
                  max_cost=INF,
                  unit_costs=None,
                  sampling_time=0,
                  effort_weight=None,
                  eager_layers=1,
                  visualize=False,
                  verbose=True,
                  postprocess=False,
                  **search_kwargs):
    """
    Solves a PDDLStream problem by first hypothesizing stream outputs and then determining whether they exist
    :param problem: a PDDLStream problem
    :param action_info: a dictionary from stream name to ActionInfo for planning and execution
    :param stream_info: a dictionary from stream name to StreamInfo altering how individual streams are handled
    :param max_time: the maximum amount of time to apply streams
    :param max_cost: a strict upper bound on plan cost
    :param effort_weight: a multiplier for stream effort compared to action costs
    :param eager_layers: the number of eager stream application layers per iteration
    :param visualize: if True, it draws the constraint network and stream plan as a graphviz file
    :param verbose: if True, this prints the result of each stream application
    :param search_kwargs: keyword args for the search subroutine
    :return: a tuple (plan, cost, evaluations) where plan is a sequence of actions
        (or None), cost is the cost of the plan, and evaluations is init but expanded
        using stream applications
    """
    # TODO: return to just using the highest level samplers at the start
    solve_stream_plan_fn = relaxed_stream_plan if effort_weight is None else simultaneous_stream_plan
    # TODO: warning check if using simultaneous_stream_plan or sequential_stream_plan with non-eager functions
    num_iterations = 0
    store = SolutionStore(max_time, max_cost,
                          verbose)  # TODO: include other info here?
    evaluations, goal_expression, domain, stream_name, externals = parse_problem(
        problem, stream_info)
    compile_to_exogenous(evaluations, domain, externals)
    if unit_costs is None:
        unit_costs = not has_costs(domain)
    full_action_info = get_action_info(action_info)
    load_stream_statistics(stream_name, externals + synthesizers)
    if visualize:
        clear_visualizations()
    eager_externals = list(filter(lambda e: e.info.eager, externals))
    streams, functions, negative = partition_externals(externals)
    queue = []
    # TODO: switch to searching if believe chance of search better than sampling
    while not store.is_terminated():
        num_iterations += 1
        # TODO: decide max_sampling_time based on total search_time or likelihood estimates
        print(
            '\nIteration: {} | Queue: {} | Evaluations: {} | Cost: {} | Time: {:.3f}'
            .format(num_iterations, len(queue), len(evaluations),
                    store.best_cost, store.elapsed_time()))
        layered_process_stream_queue(
            Instantiator(evaluations, eager_externals), evaluations, store,
            eager_layers)
        solve_stream_plan = lambda sr: solve_stream_plan_fn(
            evaluations,
            goal_expression,
            domain,
            sr,
            negative,
            max_cost=store.best_cost,
            #max_cost=min(store.best_cost, max_cost),
            unit_costs=unit_costs,
            **search_kwargs)
        #combined_plan, cost = solve_stream_plan(populate_results(evaluations, streams + functions))
        combined_plan, cost = iterative_solve_stream_plan(
            evaluations, streams, functions, solve_stream_plan)
        if action_info:
            combined_plan = reorder_combined_plan(evaluations, combined_plan,
                                                  full_action_info, domain)
            print('Combined plan: {}'.format(combined_plan))
        stream_plan, action_plan = separate_plan(combined_plan,
                                                 full_action_info)
        stream_plan = reorder_stream_plan(
            stream_plan)  # TODO: is this strictly redundant?
        stream_plan = get_synthetic_stream_plan(stream_plan, synthesizers)
        print('Stream plan: {}\n'
              'Action plan: {}'.format(stream_plan, action_plan))

        if stream_plan is None:
            if queue:
                fairly_process_queue(queue, evaluations, store)
            else:
                break
        else:
            if visualize:
                create_visualizations(evaluations, stream_plan, num_iterations)
            heappush(
                queue,
                HeapElement(
                    SkeletonKey(0, len(stream_plan)),
                    Skeleton(instantiate_first({}, stream_plan), 0, {},
                             stream_plan, action_plan, cost)))
            greedily_process_queue(queue, evaluations, store, sampling_time)

    if postprocess and (not unit_costs):
        locally_optimize(evaluations, store, goal_expression, domain,
                         functions, negative, synthesizers)
    write_stream_statistics(stream_name, externals + synthesizers, verbose)
    return revert_solution(store.best_plan, store.best_cost, evaluations)
Beispiel #5
0
def solve_focused(problem,
                  max_time=INF,
                  stream_info={},
                  effort_weight=None,
                  eager_iterations=1,
                  visualize=False,
                  verbose=True,
                  **kwargs):
    # TODO: eager, negative, context, costs, bindings
    start_time = time.time()
    num_iterations = 0
    best_plan = None
    best_cost = INF
    evaluations, goal_expression, domain, externals = parse_problem(problem)
    update_stream_info(externals, stream_info)
    eager_externals = filter(lambda e: e.info.eager, externals)
    constraint_solver = ConstraintSolver(problem[3])
    disabled = []
    if visualize:
        clear_visualizations()
    while elapsed_time(start_time) < max_time:
        num_iterations += 1
        print('\nIteration: {} | Evaluations: {} | Cost: {} | Time: {:.3f}'.
              format(num_iterations, len(evaluations), best_cost,
                     elapsed_time(start_time)))
        eagerly_evaluate(evaluations, eager_externals, eager_iterations,
                         max_time - elapsed_time(start_time), verbose)
        # TODO: version that just calls one of the incremental algorithms
        instantiator = Instantiator(evaluations, externals)
        stream_results = []
        while instantiator.stream_queue and (elapsed_time(start_time) <
                                             max_time):
            stream_results += optimistic_process_stream_queue(instantiator)
        # exhaustive_stream_plan | incremental_stream_plan | simultaneous_stream_plan | sequential_stream_plan | relaxed_stream_plan
        solve_stream_plan = sequential_stream_plan if effort_weight is None else simultaneous_stream_plan
        #solve_stream_plan = simultaneous_stream_plan
        stream_plan, action_plan, cost = solve_stream_plan(
            evaluations, goal_expression, domain, stream_results, **kwargs)
        print('Stream plan: {}\n'
              'Action plan: {}'.format(stream_plan, action_plan))
        if stream_plan is None:
            if not disabled:
                break
            reset_disabled(disabled)
        elif (len(stream_plan) == 0) and (cost < best_cost):
            best_plan = action_plan
            best_cost = cost
            break
        else:
            if visualize:
                create_visualizations(evaluations, stream_plan, num_iterations)
            constraint_facts = constraint_solver.solve(
                get_optimistic_constraints(evaluations, stream_plan),
                verbose=verbose)
            if constraint_facts:
                evaluations.update(map(evaluation_from_fact, constraint_facts))
            else:
                #process_stream_plan(evaluations, stream_plan, disabled, verbose)
                process_immediate_stream_plan(evaluations, stream_plan,
                                              disabled, verbose)

    return revert_solution(best_plan, best_cost, evaluations)
Beispiel #6
0
def solve_committed(problem, max_time=INF, effort_weight=None, visualize=False, verbose=True, **kwargs):
    # TODO: constrain plan skeleton
    # TODO: constrain ususable samples
    # TODO: recursively consider previously exposed binding levels
    # TODO: parameter for how many times to consider a plan skeleton

    # TODO: constrain to use previous plan skeleton
    # TODO: only use stream instances on plan
    # TODO: identify subset of state to include to further constrain (requires inverting axioms)
    # TODO: recurse to previous problems
    start_time = time.time()
    num_iterations = 0
    best_plan = None; best_cost = INF
    evaluations, goal_expression, domain, streams = parse_problem(problem)
    constraint_solver = ConstraintSolver(problem[3])
    disabled = []
    if visualize:
        clear_visualizations()
    committed = False
    instantiator = Instantiator(evaluations, streams)
    #stream_results = []
    #while instantiator.stream_queue and (elapsed_time(start_time) < max_time):
    #    stream_results += optimistic_process_stream_queue(instantiator, prioritized=False)
    # TODO: queue to always consider functions
    # TODO: can always append functions
    # Subproblems are which streams you can use
    while elapsed_time(start_time) < max_time:
        num_iterations += 1
        print('\nIteration: {} | Evaluations: {} | Cost: {} | Time: {:.3f}'.format(
            num_iterations, len(evaluations), best_cost, elapsed_time(start_time)))
        stream_results = []
        while instantiator.stream_queue and (elapsed_time(start_time) < max_time):
            stream_results += optimistic_process_stream_queue(instantiator)
        solve_stream_plan = sequential_stream_plan if effort_weight is None else simultaneous_stream_plan
        #solve_stream_plan = relaxed_stream_plan
        # TODO: constrain to use previous plan to some degree
        stream_plan, action_plan, cost = solve_stream_plan(evaluations, goal_expression,
                                                     domain, stream_results, **kwargs)
        print('Stream plan: {}\n'
              'Action plan: {}'.format(stream_plan, action_plan))
        if stream_plan is None:
            if committed or disabled:
                if not committed:
                    reset_disabled(disabled)
                committed = False
                instantiator = Instantiator(evaluations, streams)
            else:
                break
        elif (len(stream_plan) == 0) and (cost < best_cost):
            best_plan = action_plan; best_cost = cost
            break
        else:
            if visualize:
                create_visualizations(evaluations, stream_plan, num_iterations)
            # TODO: use set of intended stream instances here instead
            #stream_results = []
            committed = True
            constraint_facts = constraint_solver.solve(get_optimistic_constraints(evaluations, stream_plan), verbose=verbose)
            if constraint_facts:
                new_evaluations = map(evaluation_from_fact, constraint_facts)
                evaluations.update(new_evaluations)
            else:
                #new_evaluations = process_stream_plan(evaluations, stream_plan, disabled, verbose)
                new_evaluations = process_immediate_stream_plan(evaluations, stream_plan, disabled, verbose)
                for evaluation in new_evaluations:
                    instantiator.add_atom(evaluation) # TODO: return things to try next
                #while instantiator.stream_queue and (elapsed_time(start_time) < max_time):
                #    stream_results += optimistic_process_stream_queue(instantiator, prioritized=False)
                #stream_results = stream_plan # TODO: would need to prune disabled
                # TODO: don't include streams that aren't performable?
                # TODO: could also only include the previous stream plan
                # TODO: need to be careful if I only instantiate one that I am not unable to find a plan
                # TODO: need to always propagate this a little
    return revert_solution(best_plan, best_cost, evaluations)
Beispiel #7
0
def solve_focused(problem,
                  stream_info={},
                  action_info={},
                  dynamic_streams=[],
                  max_time=INF,
                  max_cost=INF,
                  unit_costs=False,
                  commit=True,
                  effort_weight=None,
                  eager_layers=1,
                  visualize=False,
                  verbose=True,
                  postprocess=False,
                  **search_kwargs):
    """
    Solves a PDDLStream problem by first hypothesizing stream outputs and then determining whether they exist
    :param problem: a PDDLStream problem
    :param action_info: a dictionary from stream name to ActionInfo for planning and execution
    :param stream_info: a dictionary from stream name to StreamInfo altering how individual streams are handled
    :param max_time: the maximum amount of time to apply streams
    :param max_cost: a strict upper bound on plan cost
    :param commit: if True, it commits to instantiating a particular partial plan-skeleton.
    :param effort_weight: a multiplier for stream effort compared to action costs
    :param eager_layers: the number of eager stream application layers per iteration
    :param visualize: if True, it draws the constraint network and stream plan as a graphviz file
    :param verbose: if True, this prints the result of each stream application
    :param search_kwargs: keyword args for the search subroutine
    :return: a tuple (plan, cost, evaluations) where plan is a sequence of actions
        (or None), cost is the cost of the plan, and evaluations is init but expanded
        using stream applications
    """
    # TODO: return to just using the highest level samplers at the start
    start_time = time.time()
    num_iterations = 0
    best_plan = None
    best_cost = INF
    evaluations, goal_expression, domain, stream_name, externals = parse_problem(
        problem)
    action_info = get_action_info(action_info)
    update_stream_info(externals, stream_info)
    load_stream_statistics(stream_name, externals)
    eager_externals = filter(lambda e: e.info.eager, externals)
    disabled = []
    if visualize:
        clear_visualizations()
    #functions = filter(lambda s: isinstance(s, Function), externals)
    functions = filter(lambda s: type(s) is Function, externals)
    negative = filter(lambda s: type(s) is Predicate and s.is_negative(),
                      externals)
    streams = filter(lambda s: s not in (functions + negative), externals)
    stream_results = []
    depth = 1
    sampling_queue = []
    while elapsed_time(start_time) < max_time:
        search_time = time.time(
        )  # TODO: allocate more sampling effort to maintain the balance
        # TODO: total search time vs most recent search time?
        if stream_results is None:
            stream_plan, action_plan, cost = None, None, INF
        else:
            num_iterations += 1
            print(
                '\nIteration: {} | Depth: {} | Evaluations: {} | Cost: {} | Time: {:.3f}'
                .format(num_iterations, depth, len(evaluations), best_cost,
                        elapsed_time(start_time)))
            # TODO: constrain to use previous plan to some degree
            eagerly_evaluate(evaluations, eager_externals, eager_layers,
                             max_time - elapsed_time(start_time), verbose)
            stream_results += optimistic_process_streams(
                evaluations_from_stream_plan(evaluations, stream_results),
                functions)
            # TODO: warning check if using simultaneous_stream_plan or relaxed_stream_plan with non-eager functions
            solve_stream_plan = relaxed_stream_plan if effort_weight is None else simultaneous_stream_plan
            #solve_stream_plan = sequential_stream_plan if effort_weight is None else simultaneous_stream_plan
            combined_plan, cost = solve_stream_plan(evaluations,
                                                    goal_expression,
                                                    domain,
                                                    stream_results,
                                                    negative,
                                                    max_cost=best_cost,
                                                    unit_costs=unit_costs,
                                                    **search_kwargs)
            combined_plan = reorder_combined_plan(evaluations, combined_plan,
                                                  action_info, domain)
            print('Combined plan: {}'.format(combined_plan))
            stream_plan, action_plan = separate_plan(combined_plan,
                                                     action_info)
            stream_plan = reorder_stream_plan(
                stream_plan)  # TODO: is this strictly redundant?
            stream_plan = get_synthetic_stream_plan(stream_plan,
                                                    dynamic_streams)
            print('Stream plan: {}\n'
                  'Action plan: {}'.format(stream_plan, action_plan))

        if stream_plan is None:
            if disabled or (depth != 0):
                if depth == 0:
                    reset_disabled(disabled)
                stream_results = optimistic_process_streams(
                    evaluations, streams)
                depth = 0  # Recurse on problems
            else:
                break
        elif len(stream_plan) == 0:
            if cost < best_cost:
                best_plan = action_plan
                best_cost = cost
                if best_cost < max_cost:
                    break
            stream_results = None
        else:
            """
            sampling_key = SkeletonKey(0, len(stream_plan))
            sampling_problem = Skeleton({}, stream_plan, action_plan, cost)
            heappush(sampling_queue, (sampling_key, sampling_problem))
            greedily_process_queue(sampling_queue, evaluations, disabled, max_cost, True, 0, verbose)
            depth += 1
            stream_results = None
            """

            if visualize:
                create_visualizations(evaluations, stream_plan, num_iterations)
            option = True
            if option:
                # TODO: can instantiate all but subtract stream_results
                # TODO: can even pass a subset of the fluent state
                # TODO: can just compute the stream plan preimage
                # TODO: replan constraining the initial state and plan skeleton
                # TODO: reuse subproblems
                # TODO: always start from the initial state (i.e. don't update)
                old_evaluations = set(evaluations)
                stream_results, _ = process_stream_plan(
                    evaluations, stream_plan, disabled, verbose)
                new_evaluations = set(evaluations) - old_evaluations
                if stream_results is not None:
                    new_instances = [r.instance for r in stream_results]
                    stream_results = optimistic_process_streams(
                        new_evaluations, streams, new_instances)
            if not commit:
                stream_results = None
            depth += 1

    reset_disabled(disabled)
    if postprocess and (not unit_costs) and (best_plan is not None):
        best_plan = locally_optimize(evaluations, best_plan, goal_expression,
                                     domain, functions, negative,
                                     dynamic_streams, verbose)
    write_stream_statistics(stream_name, externals)
    return revert_solution(best_plan, best_cost, evaluations)