Beispiel #1
0
 def dump_new_values(self, new_values=[]):
     if (not new_values and VERBOSE_FAILURES) or \
             (new_values and self.info.verbose):
         print('iter={}, outs={}) {}:{}->{}'.format(
             self.get_iteration(), len(new_values), self.external.name,
             str_from_object(self.get_input_values()),
             str_from_object(new_values)))
Beispiel #2
0
 def next_results(self, accelerate=1, verbose=False):
     # TODO: prune repeated values
     all_new_values = []
     all_new_facts = []
     all_results = []
     start_calls = self.num_calls
     for attempt in range(accelerate):
         if all_results or self.enumerated:
             break
         start_time = time.time()
         new_values, new_facts = self._next_outputs()
         self._check_output_values(new_values)
         self._check_wild_facts(new_facts)
         new_results = [self.get_result(map(Object.from_value, output_values), list_index=list_index)
                        for list_index, output_values in enumerate(new_values)]
         all_new_values.extend(new_values)
         all_new_facts.extend(new_facts)
         all_results.extend(new_results)
         self.update_statistics(start_time, new_results)
     if verbose and (VERBOSE_FAILURES or all_new_values):
         print('{}-{}) {}:{}->{}'.format(start_calls, self.num_calls, self.external.name,
                                         str_from_object(self.get_input_values()),
                                         str_from_object(all_new_values)))
     if verbose and all_new_facts:
         # TODO: format all_new_facts
         print('{}-{}) {}:{}->{}'.format(start_calls, self.num_calls, self.external.name,
                                         str_from_object(self.get_input_values()), all_new_facts))
     return all_results, list(map(obj_from_value_expression, all_new_facts))
Beispiel #3
0
 def next_results(self, verbose=False):
     assert not self.enumerated
     start_time = time.time()
     start_calls = self.num_calls
     new_values, new_facts = self._next_outputs()
     self._check_output_values(new_values)
     self._check_wild_facts(new_facts)
     new_objects = [tuple(map(Object.from_value, output_values)) for output_values in new_values]
     new_objects = list(filter(lambda o: o not in self.previous_outputs, new_objects))
     self.previous_outputs.update(new_objects) # Only counting new outputs as successes
     new_results = [self.get_result(output_objects, list_index=list_index, optimistic=False)
                    for list_index, output_objects in enumerate(new_objects)]
     self.update_statistics(start_time, new_results)
     if verbose:
         if VERBOSE_FAILURES or new_values:
             print('{}) {}:{}->{}'.format(start_calls, self.external.name,
                                          str_from_object(self.get_input_values()),
                                          str_from_object(new_values)))
         if VERBOSE_WILD and new_facts:
             # TODO: format all_new_facts
             print('{}) {}:{}->{}'.format(start_calls, self.external.name,
                                          str_from_object(self.get_input_values()), new_facts))
     facts = list(map(obj_from_value_expression, new_facts))
     if not self.external.outputs and self.successes:
         # Set of possible outputs is exhausted
         self.enumerated = True
     return new_results, facts
Beispiel #4
0
    def next_results(self, verbose=False):
        assert not self.enumerated
        start_time = time.time()
        start_history = len(self.history)
        new_values, new_facts = self._next_outputs()
        self._check_output_values(new_values)
        self._check_wild_facts(new_facts)
        if verbose:
            if (not new_values and VERBOSE_FAILURES) or \
                    (new_values and self.info.verbose):
                print('iter={}, outs={}) {}:{}->{}'.format(
                    self.num_calls, len(new_values), self.external.name,
                    str_from_object(self.get_input_values()), str_from_object(new_values)))
            if VERBOSE_WILD and new_facts:
                # TODO: format all_new_facts
                print('iter={}, facts={}) {}:{}->{}'.format(
                    self.num_calls, self.external.name, str_from_object(self.get_input_values()),
                    new_facts, len(new_facts)))

        objects = [objects_from_values(output_values) for output_values in new_values]
        new_objects = list(filter(lambda o: o not in self.previous_outputs, objects))
        self.previous_outputs.update(new_objects) # Only counting new outputs as successes
        new_results = [self.get_result(output_objects, list_index=list_index, optimistic=False)
                       for list_index, output_objects in enumerate(new_objects)]
        if start_history < len(self.history):
            self.update_statistics(start_time, new_results)
        new_facts = list(map(obj_from_value_expression, new_facts))
        self.successful |= any(r.is_successful() for r in new_results)
        self.num_calls += 1 # Must be after get_result
        #if self.external.is_test() and self.successful:
        #    # Set of possible test stream outputs is exhausted (excluding wild)
        #   self.enumerated = True
        return new_results, new_facts
Beispiel #5
0
def dump_instantiated(instantiated):
    print('Instantiated frequencies:\n'
          'Atoms: {}\n'
          'Actions: {}\n'
          'Axioms: {}'.format(
              str_from_object(
                  Counter(atom.predicate for atom in instantiated.atoms)),
              str_from_object(
                  Counter(action.action.name
                          for action in instantiated.actions)),
              str_from_object(
                  Counter(axiom.axiom.name for axiom in instantiated.axioms))))
Beispiel #6
0
def dump_assignment(solution):
    bindings, cost, evaluations = solution
    print()
    print('Solved: {}'.format(bindings is not None))
    print('Cost: {}'.format(cost))
    print('Total facts: {}'.format(len(evaluations)))
    print('Fact counts: {}'.format(str_from_object(Counter(map(get_prefix, evaluations)))))
    if bindings is None:
        return
    print('Assignments:')
    for param in sorted(bindings):
        print('{} = {}'.format(param, str_from_object(bindings[param])))
Beispiel #7
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--problem', default='mirror', help='The name of the problem to solve')
    parser.add_argument('-a', '--algorithm', default='incremental', help='Specifies the algorithm')
    parser.add_argument('-c', '--cfree', action='store_true', help='Disables collisions')
    parser.add_argument('-d', '--deterministic', action='store_true', help='Uses a deterministic sampler')
    parser.add_argument('-g', '--gurobi', action='store_true', help='Uses gurobi')
    parser.add_argument('-n', '--number', default=1, type=int, help='The number of blocks')
    parser.add_argument('-o', '--optimal', action='store_true', help='Runs in an anytime mode')
    parser.add_argument('-s', '--skeleton', action='store_true', help='Enforces skeleton plan constraints')
    parser.add_argument('-t', '--max_time', default=30, type=int, help='The max time')
    parser.add_argument('-u', '--unit', action='store_true', help='Uses unit costs')
    parser.add_argument('-v', '--visualize', action='store_true', help='Visualizes graphs')
    args = parser.parse_args()
    print('Arguments:', args)

    np.set_printoptions(precision=2)
    if args.deterministic:
        random.seed(seed=0)
        np.random.seed(seed=0)
    print('Random seed:', get_random_seed())

    problem_from_name = {fn.__name__: fn for fn in PROBLEMS}
    if args.problem not in problem_from_name:
        raise ValueError(args.problem)
    print('Problem:', args.problem)
    problem_fn = problem_from_name[args.problem]
    tamp_problem = problem_fn(args.number)
    print(tamp_problem)

    pddlstream_problem = pddlstream_from_tamp(tamp_problem, collisions=not args.cfree,
                                              use_stream=not args.gurobi, use_optimizer=args.gurobi)
    print('Constants:', str_from_object(pddlstream_problem.constant_map))
    print('Initial:', sorted_str_from_list(pddlstream_problem.init))
    print('Goal:', str_from_object(pddlstream_problem.goal))

    success_cost = 0 if args.optimal else INF
    planner = 'max-astar'
    #planner = 'ff-wastar1'
    with Profiler(field='cumtime', num=20):
        if args.algorithm == 'incremental':
            solution = solve_incremental(pddlstream_problem,
                                         complexity_step=1, planner=planner,
                                         unit_costs=args.unit, success_cost=success_cost,
                                         max_time=args.max_time, verbose=False)
        else:
            raise ValueError(args.algorithm)

    print_solution(solution)
    plan, cost, evaluations = solution
    if plan is not None:
        display_plan(tamp_problem, plan)
Beispiel #8
0
def main(max_time=20):
    """
    Creates and solves the 2D motion planning problem.
    """
    parser = create_parser()
    args = parser.parse_args()
    print('Arguments:', args)

    obstacles = [create_box((.5, .5), (.2, .2))]
    regions = {
        'env': create_box((.5, .5), (1, 1)),
        'green': create_box((.8, .8), (.4, .4)),
    }

    goal = 'green'
    if goal not in regions:
        goal = ARRAY([1, 1])

    max_distance = 0.25  # 0.2 | 0.25 | 0.5 | 1.0
    problem, samples, roadmap = create_problem(goal,
                                               obstacles,
                                               regions,
                                               max_distance=max_distance)
    print('Initial:', str_from_object(problem.init))
    print('Goal:', str_from_object(problem.goal))
    constraints = PlanConstraints(max_cost=1.25)  # max_cost=INF)

    with Profiler(field='tottime', num=10):
        solution = solve_incremental(problem,
                                     constraints=constraints,
                                     unit_costs=args.unit,
                                     success_cost=0,
                                     max_time=max_time,
                                     verbose=False)

    print_solution(solution)
    plan, cost, evaluations = solution
    #viewer = draw_environment(obstacles, regions)
    #for sample in samples:
    #    viewer.draw_point(sample)
    #user_input('Continue?')

    # TODO: use the same viewer here
    draw_roadmap(roadmap, obstacles, regions)  # TODO: do this in realtime
    user_input('Continue?')

    if plan is None:
        return
    segments = [args for name, args in plan]
    draw_solution(segments, obstacles, regions)
    user_input('Finish?')
Beispiel #9
0
def main(max_time=20):
    """
    Creates and solves the 2D motion planning problem.
    """

    obstacles = [create_box((.5, .5), (.2, .2))]
    regions = {
        'env': create_box((.5, .5), (1, 1)),
        'green': create_box((.8, .8), (.4, .4)),
    }

    goal = 'green'
    if goal not in regions:
        goal = array([1, 1])

    max_distance = 0.25  # 0.2 | 0.25 | 0.5 | 1.0
    problem, samples, roadmap = create_problem(goal,
                                               obstacles,
                                               regions,
                                               max_distance=max_distance)
    print('Initial:', str_from_object(problem.init))
    print('Goal:', str_from_object(problem.goal))

    pr = cProfile.Profile()
    pr.enable()
    solution = solve_incremental(problem,
                                 unit_costs=False,
                                 max_cost=0,
                                 max_time=max_time,
                                 verbose=False)
    pr.disable()
    pstats.Stats(pr).sort_stats('tottime').print_stats(10)

    print_solution(solution)
    plan, cost, evaluations = solution

    #viewer = draw_environment(obstacles, regions)
    #for sample in samples:
    #    viewer.draw_point(sample)
    #user_input('Continue?')

    # TODO: use the same viewer here
    draw_roadmap(roadmap, obstacles, regions)  # TODO: do this in realtime
    user_input('Continue?')

    if plan is None:
        return
    segments = [args for name, args in plan]
    draw_solution(segments, obstacles, regions)
    user_input('Finish?')
Beispiel #10
0
 def next_results(self, accelerate=1, verbose=False):
     start_time = time.time()
     assert not self.enumerated
     self.enumerated = True
     input_values = self.get_input_values()
     #try:
     value = self.external.fn(*input_values)
     #except TypeError as err:
     #    print('Function [{}] expects {} inputs'.format(self.external.name, len(input_values)))
     #    raise err
     self.value = self.external._codomain(value)
     # TODO: cast the inputs and test whether still equal?
     #if not (type(self.value) is self.external._codomain):
     #if not isinstance(self.value, self.external._codomain):
     #if self.value != value:
     #    raise ValueError('Function [{}] produced a nonintegral value [{}]. '
     #                     'FastDownward only supports integral costs. '
     #                     'To "use" real costs, scale each cost by a large factor, '
     #                     'capturing the most significant bits.'.format(self.external.name, self.value))
     if self.value < 0:
         raise ValueError(
             'Function [{}] produced a negative value [{}]'.format(
                 self.external.name, self.value))
     if (self.value is not False) and verbose:
         print('0) {}{}={}'.format(get_prefix(self.external.head),
                                   str_from_object(self.get_input_values()),
                                   self.value))
     results = [self.external._Result(self, self.value)]
     #if isinstance(self, PredicateInstance) and (self.value != self.external.opt_fn(*input_values)):
     #    self.update_statistics(start_time, [])
     self.update_statistics(start_time, results)
     new_facts = []
     return results, new_facts
Beispiel #11
0
def process_stream_queue(instantiator,
                         store,
                         complexity_limit=INF,
                         verbose=False):
    instances = []
    results = []
    num_successes = 0
    while not store.is_terminated() and instantiator and (
            instantiator.min_complexity() <= complexity_limit):
        instance = instantiator.pop_stream()
        if instance.enumerated:
            continue
        instances.append(instance)
        new_results = process_instance(instantiator,
                                       store,
                                       instance,
                                       verbose=verbose)
        results.extend(new_results)
        num_successes += bool(new_results)  # TODO: max_results?
    if verbose:
        print('Eager Calls: {} | Successes: {} | Results: {} | Counts: {}'.
              format(
                  len(instances), num_successes, len(results),
                  str_from_object(
                      Counter(instance.external.name
                              for instance in instances))))
    return len(instances)
Beispiel #12
0
 def __repr__(self):
     return '{}(holding={}, placed={})'.format(
         self.__class__.__name__, self.holding,
         str_from_object({
             name: self.pose_dists[name].surface_dist
             for name in self.placed
         }))
Beispiel #13
0
 def dump_new_facts(self, new_facts=[]):
     if VERBOSE_WILD and new_facts:
         # TODO: format all_new_facts
         print('iter={}, facts={}) {}:{}->{}'.format(
             self.get_iteration(), self.external.name,
             str_from_object(self.get_input_values()), new_facts,
             len(new_facts)))
Beispiel #14
0
def instantiate_condition(action, is_static, args_from_predicate):
    parameters = {p.name for p in action.parameters}
    #if not parameters:
    #    yield {}
    #    return
    static_conditions = list(
        filter(is_static, get_literals(get_precondition(action))))
    static_parameters = set(
        filter(is_parameter, flatten(atom.args for atom in static_conditions)))
    if not (parameters <= static_parameters):
        raise NotImplementedError(
            'Could not instantiate action {} due to parameters: {}'.format(
                action.name, str_from_object(parameters - static_parameters)))
    atoms_from_cond = {
        condition: args_from_predicate[condition.predicate,
                                       get_constants(condition)]
        for condition in static_conditions
    }
    conditions, atoms = zip(*atoms_from_cond.items())
    relations = [
        Relation(conditions[index].args, atoms[index])
        for index in compute_order(conditions, atoms)
    ]
    solution = solve_satisfaction(relations)
    for element in solution.body:
        yield solution.get_mapping(element)
Beispiel #15
0
def create_visualizations(evaluations, stream_plan, iteration):
    # TODO: place it in the temp_dir?
    # TODO: decompose any joint streams
    for result in stream_plan:
        create_synthesizer_visualizations(result, iteration)
    filename = ITERATION_TEMPLATE.format(iteration)
    # visualize_stream_plan(stream_plan, path)

    constraints = set()  # TODO: approximates needed facts using produced ones
    for stream in stream_plan:
        constraints.update(
            filter(lambda f: evaluation_from_fact(f) not in evaluations,
                   stream.get_certified()))
    print('Constraints:', str_from_object(constraints))
    visualize_constraints(constraints,
                          os.path.join(CONSTRAINT_NETWORK_DIR, filename))

    from pddlstream.retired.synthesizer import decompose_stream_plan
    decomposed_plan = decompose_stream_plan(stream_plan)
    if len(decomposed_plan) != len(stream_plan):
        visualize_stream_plan(decompose_stream_plan(stream_plan),
                              os.path.join(STREAM_PLAN_DIR, filename))

    #visualize_stream_plan_bipartite(stream_plan, os.path.join(STREAM_PLAN_DIR, 'fused_' + filename))
    visualize_stream_plan(stream_plan,
                          os.path.join(STREAM_PLAN_DIR, 'fused_' + filename))
Beispiel #16
0
 def next_results(self, verbose=False):
     start_time = time.time()
     assert not self.enumerated
     self.enumerated = True
     input_values = self.get_input_values()
     value = self.external.fn(*input_values)
     self.value = self.external.codomain(value)
     # TODO: cast the inputs and test whether still equal?
     #if not (type(self.value) is self.external._codomain):
     #if not isinstance(self.value, self.external.codomain):
     if self.value < 0:
         raise ValueError(
             'Function [{}] produced a negative value [{}]'.format(
                 self.external.name, self.value))
     if (self.value is not False) and verbose:
         start_call = 0
         print('{}) {}{}={}'.format(
             start_call, get_prefix(self.external.head),
             str_from_object(self.get_input_values()), self.value))
     results = [
         self._Result(self, self.value, opt_index=None, optimistic=False)
     ]
     #if isinstance(self, PredicateInstance) and (self.value != self.external.opt_fn(*input_values)):
     #    self.update_statistics(start_time, [])
     self.update_statistics(start_time, results)
     new_facts = []
     return results, new_facts
Beispiel #17
0
def read_raw_masses(stackings):
    if not stackings:
        return {}
    weights = {
        SCALE_FROM_BUS[bus]: weight
        for bus, weight in read_scales().items()
    }
    print('Raw weights (oz):', str_from_object(weights))
    for scale in stackings:
        if scale not in weights:
            # TODO: return which scale failed
            print('Scale {} is not turned on!'.format(scale))
            return None
    #assert all(0 < weight for weight in weights.values()) # TODO: check that objects are on
    masses = {
        stackings[scale]: KG_PER_OZ * weight
        for scale, weight in weights.items()
    }
    print('Raw masses (kg):', str_from_object(masses))
    return masses
Beispiel #18
0
def estimate_masses(masses, bowl_masses, material=None):
    print('Bowl masses (kg):', bowl_masses)
    #material_masses = {bowl: max(0.0, mass - bowl_masses[bowl])
    #                   for bowl, mass in masses.items()}
    material_masses = {
        bowl: mass - bowl_masses[bowl]
        for bowl, mass in masses.items()
    }
    print('Material masses (kg):', str_from_object(material_masses))
    #if material is not None:
    #    estimate_particles(masses, material)
    return material_masses
Beispiel #19
0
def plan_functions(functions, externals):
    external_from_function = {}
    for external in filter(lambda e: isinstance(e, Function), externals):
        assert external.function not in external_from_function
        external_from_function[external.function] = external
    function_plan = set()
    for term in functions:
        if get_prefix(term) not in external_from_function:
            raise ValueError('{} is not implemented'.format(get_prefix(term)))
        external = external_from_function[get_prefix(term)]
        instance = external.get_instance(get_args(term))
        [result] = instance.next_optimistic()
        function_plan.add(result)
    print('Function plan:', str_from_object(function_plan))
    return function_plan
Beispiel #20
0
 def next_results(self, verbose=False):
     assert not self.enumerated
     start_time = time.time()
     start_calls = self.num_calls
     start_history = len(self.history)
     value = self._compute_output()
     if (value is not False) and verbose:
         print('{}) {}{}={}'.format(
             start_calls, get_prefix(self.external.head),
             str_from_object(self.get_input_values()), value))
     new_results = [self._Result(self, value, optimistic=False)]
     new_facts = []
     if start_history < len(self.history):
         self.update_statistics(start_time, new_results)
     self.successful |= any(r.is_successful() for r in new_results)
     return new_results, new_facts
Beispiel #21
0
    def next_results(self, verbose=False):
        assert not self.enumerated
        start_time = time.time()
        start_history = len(self.history)
        value = self._compute_output()
        new_results = [self._Result(self, value, optimistic=False)]
        new_facts = []

        if (value is not False) and verbose:
            # TODO: str(new_results[-1])
            print('iter={}, outs={}) {}{}={:.3f}'.format(
                self.get_iteration(), len(new_results), get_prefix(self.external.head),
                str_from_object(self.get_input_values()), value))
        if start_history <= len(self.history) - 1:
            self.update_statistics(start_time, new_results)
        self.successful |= any(r.is_successful() for r in new_results)
        return new_results, new_facts
Beispiel #22
0
def score_masses(args, task, ros_world, init_total_mass, bowl_masses,
                 final_raw_masses):
    # TODO: assert that mass is not zero if object known to be above
    # TODO: unify this with the simulator scoring
    cup_name, bowl_name = REQUIREMENT_FNS[args.problem](ros_world)
    name_from_type = {
        'cup': cup_name,
    }
    if POUR:
        name_from_type.update({
            'bowl': bowl_name,
        })

    final_masses = estimate_masses(final_raw_masses, bowl_masses,
                                   args.material)
    if POUR:
        final_total_mass = sum(final_masses.values())
        print('Total mass:', final_total_mass)
        print(
            'Spilled (%):',
            clip(init_total_mass - final_total_mass, min_value=0, max_value=1))
    score = {'total_mass': init_total_mass}
    score.update({
        'mass_in_{}'.format(ty): final_masses[name]
        for ty, name in name_from_type.items()
    })
    if POUR:
        final_percentages = {
            name: mass / init_total_mass
            for name, mass in final_masses.items()
        }
        print('Percentages (%):', str_from_object(final_percentages))
    #score.update({'fraction_in_{}'.format(ty): final_percentages[name]
    #             for ty, name in name_from_type.items()})
    if task.holding:
        [spoon_name] = task.holding
        spoon_capacity = SPOON_CAPACITIES[get_type(spoon_name), args.material]
        fraction_filled = final_masses[cup_name] / spoon_capacity
        print('Spoon percentage filled (%):', fraction_filled)
        score.update({
            'mass_in_spoon': final_masses[cup_name],
            #'fraction_in_spoon': final_masses[cup_name] / init_total_mass,
            #'spoon_capacity': spoon_capacity,
            #'fraction_filled': fraction_filled,
        })
    return score
Beispiel #23
0
def decompose_discrete(results, **kwargs):
    data_from_discrete = {}
    for result in results:
        key = frozenset((feature, result[FEATURE][feature]) for feature in DISCRETE_FEATURES
                        if feature in result[FEATURE])
        data_from_discrete.setdefault(key, []).append(result)

    sorted_triplets = []
    for key, key_data in data_from_discrete.items():
        category_values = get_category_values(key_data, **kwargs)
        scores = category_values[SCORE]['score'] if SCORE in category_values else []
        sorted_triplets.append((dict(key), len(scores), compute_percentiles(scores, **kwargs)))
    for i, (discrete, num, percentiles) in enumerate(
            sorted(sorted_triplets, key=lambda t: (t[-1][-1], t[1]), reverse=True)):
        print('{}) {} | Num: {} | %: {}'.format(
            i, str_from_object(discrete), num, percentiles.round(3).tolist()))
        #analyze_data(data_name, data_from_discrete[key])
    return data_from_discrete
Beispiel #24
0
def run_trials(trials, data_path=None, num_cores=False, **kwargs):
    # https://stackoverflow.com/questions/15314189/python-multiprocessing-pool-hangs-at-join
    # https://stackoverflow.com/questions/39884898/large-amount-of-multiprocessing-process-causing-deadlock
    # TODO: multiprocessing still seems to hang on one thread before starting
    assert (get_python_version() == 3)
    results = []
    if not trials:
        return results
    start_time = time.time()
    serial = (num_cores is False)  # None is the max number
    failures = 0
    scored = 0
    try:
        for result in map_general(run_trial,
                                  trials,
                                  serial,
                                  num_cores=num_cores,
                                  **kwargs):
            num_trials = len(results) + failures
            print(
                '{}\nTrials: {} | Successes: {} | Failures: {} | Scored: {} | Time: {:.3f}'
                .format(SEPARATOR, num_trials, len(results), failures, scored,
                        elapsed_time(start_time)))
            print('Result:', str_from_object(result))
            if result is None:
                failures += 1
                print('Error! Trial resulted in an exception')
                continue
            scored += int(result.get('score', None) is not None)
            results.append(result)
            write_results(data_path, results)
    # except BaseException as e:
    #    traceback.print_exc() # e
    finally:
        print(SEPARATOR)
        safe_rm_dir(TEMP_DIRECTORY)
        write_results(data_path, results)
        print('Hours: {:.3f}'.format(elapsed_time(start_time) / HOURS_TO_SECS))
    # TODO: make a generator version of this
    return results
Beispiel #25
0
def main():
    parser = create_parser()
    parser.add_argument('-enable', action='store_true', help='Enables rendering during planning')
    parser.add_argument('-teleport', action='store_true', help='Teleports between configurations')
    parser.add_argument('-simulate', action='store_true', help='Simulates the system')
    parser.add_argument('-viewer', action='store_true', help='Enable the viewer and visualizes the plan')
    args = parser.parse_args()
    print('Arguments:', args)

    connect(use_gui=args.viewer)
    robot, names, movable = load_world()
    print('Objects:', names)
    saver = WorldSaver()

    problem = pddlstream_from_problem(robot, movable=movable, teleport=args.teleport)
    _, _, _, stream_map, init, goal = problem
    print('Init:', init)
    print('Goal:', goal)
    print('Streams:', str_from_object(set(stream_map)))

    with Profiler():
        with LockRenderer(lock=not args.enable):
            solution = solve(problem, algorithm=args.algorithm, unit_costs=args.unit, success_cost=INF)
            saver.restore()
    print_solution(solution)
    plan, cost, evaluations = solution
    if (plan is None) or not has_gui():
        disconnect()
        return

    command = postprocess_plan(plan)
    if args.simulate:
        wait_for_user('Simulate?')
        command.control()
    else:
        wait_for_user('Execute?')
        #command.step()
        command.refine(num_steps=10).execute(time_step=0.001)
    wait_for_user('Finish?')
    disconnect()
Beispiel #26
0
def solve_serialized(initial_problem,
                     stream_info={},
                     unit_costs=False,
                     unit_efforts=False,
                     verbose=True,
                     retain_facts=True,
                     **kwargs):
    # TODO: be careful of CanMove deadends
    domain_pddl, constant_map, stream_pddl, stream_map, init, goal = initial_problem
    _, _, domain, streams = parse_problem(initial_problem,
                                          stream_info,
                                          constraints=None,
                                          unit_costs=unit_costs,
                                          unit_efforts=unit_efforts)
    static_init, _ = partition_facts(
        domain, init)  # might not be able to reprove static_int
    #global_all, global_preimage = [], []
    global_plan = []
    global_cost = 0
    state = list(init)
    goals = serialize_goal(goal)
    # TODO: instead just track how the true init updates
    for i in range(len(goals)):
        # TODO: option in algorithms to pass in existing facts
        for stream in streams:
            stream.reset()
        goal = And(*goals[:i + 1])
        print('Goal:', str_from_object(goal))
        # No strict need to reuse streams because generator functions
        #local_problem = PDDLProblem(domain_pddl, constant_map, stream_pddl, stream_map, state, goal)
        local_problem = PDDLProblem(domain_pddl, constant_map, streams, None,
                                    state, goal)
        with Verbose(verbose):
            solution = solve_focused(local_problem,
                                     stream_info=stream_info,
                                     unit_costs=unit_costs,
                                     unit_efforts=unit_efforts,
                                     verbose=True,
                                     **kwargs)
        print_solution(solution)
        local_plan, local_cost, local_certificate = solution
        if local_plan is None:
            # TODO: replan upon failure
            global_certificate = Certificate(all_facts={}, preimage_facts=None)
            return None, INF, global_certificate

        if retain_facts:
            state = local_certificate.all_facts
        else:
            _, fluent_facts = partition_facts(domain, state)
            state = static_init + fluent_facts + local_certificate.preimage_facts  # TODO: include functions
        #print('State:', state)
        # TODO: indicate when each fact is used
        # TODO: record failed facts
        global_plan.extend(
            local_plan)  # TODO: compute preimage of the executed plan
        global_cost += local_cost

        static_state, _ = partition_facts(domain, state)
        #global_all.extend(partition_facts(domain, local_certificate.all_facts)[0])
        #global_preimage.extend(static_state)
        print('Static:', static_state)
        state = apply_actions(domain, state, local_plan, unit_costs=unit_costs)
        print(SEPARATOR)
        #user_input('Continue?')
        # TODO: could also just test the goal here
        # TODO: constrain future plan skeletons

    global_certificate = Certificate(all_facts={}, preimage_facts=None)
    return global_plan, global_cost, global_certificate
Beispiel #27
0
def solve_abstract(problem,
                   constraints=PlanConstraints(),
                   stream_info={},
                   replan_actions=set(),
                   unit_costs=False,
                   success_cost=INF,
                   max_time=INF,
                   max_iterations=INF,
                   max_memory=INF,
                   initial_complexity=0,
                   complexity_step=1,
                   max_complexity=INF,
                   max_skeletons=INF,
                   search_sample_ratio=0,
                   bind=True,
                   max_failures=0,
                   unit_efforts=False,
                   max_effort=INF,
                   effort_weight=None,
                   reorder=True,
                   visualize=False,
                   verbose=True,
                   **search_kwargs):
    """
    Solves a PDDLStream problem by first planning with optimistic stream outputs and then querying streams
    :param problem: a PDDLStream problem
    :param constraints: PlanConstraints on the set of legal solutions
    :param stream_info: a dictionary from stream name to StreamInfo altering how individual streams are handled
    :param replan_actions: the actions declared to induce replanning for the purpose of deferred stream evaluation

    :param unit_costs: use unit action costs rather than numeric costs
    :param success_cost: the exclusive (strict) upper bound on plan cost to successfully terminate

    :param max_time: the maximum runtime
    :param max_iterations: the maximum number of search iterations
    :param max_memory: the maximum amount of memory

    :param initial_complexity: the initial stream complexity limit
    :param complexity_step: the increase in the stream complexity limit per iteration
    :param max_complexity: the maximum stream complexity limit

    :param max_skeletons: the maximum number of plan skeletons (max_skeletons=None indicates not adaptive)
    :param search_sample_ratio: the desired ratio of sample time / search time when max_skeletons!=None
    :param bind: if True, propagates parameter bindings when max_skeletons=None
    :param max_failures: the maximum number of stream failures before switching phases when max_skeletons=None

    :param unit_efforts: use unit stream efforts rather than estimated numeric efforts
    :param max_effort: the maximum amount of stream effort
    :param effort_weight: a multiplier for stream effort compared to action costs
    :param reorder: if True, reorder stream plans to minimize the expected sampling overhead

    :param visualize: if True, draw the constraint network and stream plan as a graphviz file
    :param verbose: if True, print 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 (INF if no plan), and evaluations is init expanded
        using stream applications
    """
    # TODO: select whether to search or sample based on expected success rates
    # TODO: no optimizers during search with relaxed_stream_plan
    # TODO: locally optimize only after a solution is identified
    # TODO: replan with a better search algorithm after feasible
    # TODO: change the search algorithm and unit costs based on the best cost
    use_skeletons = (max_skeletons is not None)
    #assert implies(use_skeletons, search_sample_ratio > 0)
    eager_disabled = (effort_weight is None
                      )  # No point if no stream effort biasing
    num_iterations = eager_calls = 0
    complexity_limit = initial_complexity

    evaluations, goal_exp, domain, externals = parse_problem(
        problem,
        stream_info=stream_info,
        constraints=constraints,
        unit_costs=unit_costs,
        unit_efforts=unit_efforts)
    identify_non_producers(externals)
    enforce_simultaneous(domain, externals)
    compile_fluent_streams(domain, externals)
    # TODO: make effort_weight be a function of the current cost
    # if (effort_weight is None) and not has_costs(domain):
    #     effort_weight = 1

    load_stream_statistics(externals)
    if visualize and not has_pygraphviz():
        visualize = False
        print(
            'Warning, visualize=True requires pygraphviz. Setting visualize=False'
        )
    if visualize:
        reset_visualizations()
    streams, functions, negative, optimizers = partition_externals(
        externals, verbose=verbose)
    eager_externals = list(filter(lambda e: e.info.eager, externals))
    positive_externals = streams + functions + optimizers
    has_optimizers = bool(optimizers)  # TODO: deprecate
    assert implies(has_optimizers, use_skeletons)

    ################

    store = SolutionStore(evaluations,
                          max_time,
                          success_cost,
                          verbose,
                          max_memory=max_memory)
    skeleton_queue = SkeletonQueue(store, domain, disable=not has_optimizers)
    disabled = set()  # Max skeletons after a solution
    while (not store.is_terminated()) and (
            num_iterations < max_iterations) and (complexity_limit <=
                                                  max_complexity):
        num_iterations += 1
        eager_instantiator = Instantiator(
            eager_externals, evaluations)  # Only update after an increase?
        if eager_disabled:
            push_disabled(eager_instantiator, disabled)
        if eager_externals:
            eager_calls += process_stream_queue(
                eager_instantiator,
                store,
                complexity_limit=complexity_limit,
                verbose=verbose)

        ################

        print(
            '\nIteration: {} | Complexity: {} | Skeletons: {} | Skeleton Queue: {} | Disabled: {} | Evaluations: {} | '
            'Eager Calls: {} | Cost: {:.3f} | Search Time: {:.3f} | Sample Time: {:.3f} | Total Time: {:.3f}'
            .format(num_iterations, complexity_limit,
                    len(skeleton_queue.skeletons), len(skeleton_queue),
                    len(disabled), len(evaluations), eager_calls,
                    store.best_cost, store.search_time, store.sample_time,
                    store.elapsed_time()))
        optimistic_solve_fn = get_optimistic_solve_fn(
            goal_exp,
            domain,
            negative,
            replan_actions=replan_actions,
            reachieve=use_skeletons,
            max_cost=min(store.best_cost, constraints.max_cost),
            max_effort=max_effort,
            effort_weight=effort_weight,
            **search_kwargs)
        # TODO: just set unit effort for each stream beforehand
        if (max_skeletons is None) or (len(skeleton_queue.skeletons) <
                                       max_skeletons):
            disabled_axioms = create_disabled_axioms(
                skeleton_queue) if has_optimizers else []
            if disabled_axioms:
                domain.axioms.extend(disabled_axioms)
            stream_plan, opt_plan, cost = iterative_plan_streams(
                evaluations,
                positive_externals,
                optimistic_solve_fn,
                complexity_limit,
                max_effort=max_effort)
            for axiom in disabled_axioms:
                domain.axioms.remove(axiom)
        else:
            stream_plan, opt_plan, cost = OptSolution(
                INFEASIBLE, INFEASIBLE, INF)  # TODO: apply elsewhere

        ################

        #stream_plan = replan_with_optimizers(evaluations, stream_plan, domain, externals) or stream_plan
        stream_plan = combine_optimizers(evaluations, stream_plan)
        #stream_plan = get_synthetic_stream_plan(stream_plan, # evaluations
        #                                       [s for s in synthesizers if not s.post_only])
        #stream_plan = recover_optimistic_outputs(stream_plan)
        if reorder:
            # TODO: this blows up memory wise for long stream plans
            stream_plan = reorder_stream_plan(store, stream_plan)

        num_optimistic = sum(r.optimistic
                             for r in stream_plan) if stream_plan else 0
        action_plan = opt_plan.action_plan if is_plan(opt_plan) else opt_plan
        print('Stream plan ({}, {}, {:.3f}): {}\nAction plan ({}, {:.3f}): {}'.
              format(get_length(stream_plan), num_optimistic,
                     compute_plan_effort(stream_plan), stream_plan,
                     get_length(action_plan), cost,
                     str_from_plan(action_plan)))
        if is_plan(stream_plan) and visualize:
            log_plans(stream_plan, action_plan, num_iterations)
            create_visualizations(evaluations, stream_plan, num_iterations)

        ################

        if (stream_plan is INFEASIBLE) and (not eager_instantiator) and (
                not skeleton_queue) and (not disabled):
            break
        if not is_plan(stream_plan):
            print('No plan: increasing complexity from {} to {}'.format(
                complexity_limit, complexity_limit + complexity_step))
            complexity_limit += complexity_step
            if not eager_disabled:
                reenable_disabled(evaluations, domain, disabled)

        #print(stream_plan_complexity(evaluations, stream_plan))
        if not use_skeletons:
            process_stream_plan(store,
                                domain,
                                disabled,
                                stream_plan,
                                opt_plan,
                                cost,
                                bind=bind,
                                max_failures=max_failures)
            continue

        ################

        #optimizer_plan = replan_with_optimizers(evaluations, stream_plan, domain, optimizers)
        optimizer_plan = None
        if optimizer_plan is not None:
            # TODO: post process a bound plan
            print('Optimizer plan ({}, {:.3f}): {}'.format(
                get_length(optimizer_plan),
                compute_plan_effort(optimizer_plan), optimizer_plan))
            skeleton_queue.new_skeleton(optimizer_plan, opt_plan, cost)

        allocated_sample_time = (search_sample_ratio * store.search_time) - store.sample_time \
            if len(skeleton_queue.skeletons) <= max_skeletons else INF
        if skeleton_queue.process(stream_plan, opt_plan, cost,
                                  complexity_limit,
                                  allocated_sample_time) is INFEASIBLE:
            break

    ################

    summary = store.export_summary()
    summary.update({
        'iterations': num_iterations,
        'complexity': complexity_limit,
        'skeletons': len(skeleton_queue.skeletons),
    })
    print('Summary: {}'.format(str_from_object(
        summary, ndigits=3)))  # TODO: return the summary

    write_stream_statistics(externals, verbose)
    return store.extract_solution()
Beispiel #28
0
 def __repr__(self):
     return '{}:{}->{}'.format(self.external.name,
                               str_from_object(self.instance.input_objects),
                               str_from_object(self.output_objects))
Beispiel #29
0
def solve_incremental(problem,
                      constraints=PlanConstraints(),
                      unit_costs=False,
                      success_cost=INF,
                      max_iterations=INF,
                      max_time=INF,
                      max_memory=INF,
                      initial_complexity=0,
                      complexity_step=1,
                      max_complexity=INF,
                      verbose=False,
                      **search_args):
    """
    Solves a PDDLStream problem by alternating between applying all possible streams and searching
    :param problem: a PDDLStream problem
    :param constraints: PlanConstraints on the set of legal solutions
    :param max_time: the maximum amount of time to apply streams
    :param max_iterations: the maximum amount of search iterations
    :param initial_complexity: the stream complexity on the first iteration
    :param complexity_step: the increase in the complexity limit after each iteration
    :param max_complexity: the maximum stream complexity
    :param unit_costs: use unit action costs rather than numeric costs
    :param success_cost: an exclusive (strict) upper bound on plan cost to terminate
    :param verbose: if True, this prints the result of each stream application
    :param search_args: 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
    """
    # max_complexity = 0 => current
    # complexity_step = INF => exhaustive
    # success_cost = terminate_cost = decision_cost
    evaluations, goal_expression, domain, externals = parse_problem(
        problem, constraints=constraints, unit_costs=unit_costs)
    store = SolutionStore(
        evaluations, max_time, success_cost, verbose,
        max_memory=max_memory)  # TODO: include other info here?
    if UPDATE_STATISTICS:
        load_stream_statistics(externals)
    static_externals = compile_fluents_as_attachments(domain, externals)
    num_iterations = num_calls = 0
    complexity_limit = initial_complexity
    instantiator = Instantiator(static_externals, evaluations)
    num_calls += process_stream_queue(instantiator,
                                      store,
                                      complexity_limit,
                                      verbose=verbose)
    while not store.is_terminated() and (
            num_iterations <= max_iterations) and (complexity_limit <=
                                                   max_complexity):
        num_iterations += 1
        print(
            'Iteration: {} | Complexity: {} | Calls: {} | Evaluations: {} | Solved: {} | Cost: {} | Time: {:.3f}'
            .format(num_iterations, complexity_limit, num_calls,
                    len(evaluations), store.has_solution(), store.best_cost,
                    store.elapsed_time()))
        plan, cost = solve_finite(evaluations,
                                  goal_expression,
                                  domain,
                                  max_cost=min(store.best_cost,
                                               constraints.max_cost),
                                  **search_args)
        if is_plan(plan):
            store.add_plan(plan, cost)
        if not instantiator:
            break
        if complexity_step is None:
            # TODO: option to select the next k-smallest complexities
            complexity_limit = instantiator.min_complexity()
        else:
            complexity_limit += complexity_step
        num_calls += process_stream_queue(instantiator,
                                          store,
                                          complexity_limit,
                                          verbose=verbose)
    #retrace_stream_plan(store, domain, goal_expression)
    #print('Final queue size: {}'.format(len(instantiator)))

    summary = store.export_summary()
    summary.update({
        # TODO: integrate into store
        'iterations': num_iterations,
        'complexity': complexity_limit,
        # TODO: optimal, infeasible, etc...
    })
    print(str_from_object(summary))  # TODO: return the summary

    if UPDATE_STATISTICS:
        write_stream_statistics(externals, verbose)
    return store.extract_solution()
Beispiel #30
0
def str_from_plan(plan):
    if not is_plan(plan):
        return str(plan)
    return str_from_object(list(map(str_from_action, plan)))