Example #1
0
 def next_optimistic(self):
     # TODO: compute this just once and store
     if self.enumerated or self.disabled:
         return []
     # TODO: (potentially infinite) sequence of optimistic objects
     # TODO: how do I distinguish between real and not real verifications of things?
     # TODO: reuse these?
     self.opt_results = []
     output_set = set()
     for output_list in self.opt_gen_fn(*self.get_input_values()):
         self._check_output_values(output_list)
         for i, output_values in enumerate(output_list):
             output_objects = []
             for output_index, value in enumerate(output_values):
                 # TODO: maybe record history of values here?
                 unique = UniqueOptValue(self, len(self.opt_results),
                                         output_index)  # object()
                 param = unique if self.use_unique() else value
                 output_objects.append(
                     OptimisticObject.from_opt(value, param))
             output_objects = tuple(output_objects)
             if output_objects not in output_set:
                 output_set.add(
                     output_objects
                 )  # No point returning the exact thing here...
                 self.opt_results.append(
                     self._Result(self,
                                  output_objects,
                                  opt_index=self.opt_index,
                                  call_index=len(self.opt_results),
                                  list_index=0))
     return self.opt_results
Example #2
0
def convert_fluent_streams(stream_plan, real_states, action_plan,
                           step_from_fact, node_from_atom):
    #return stream_plan
    import pddl
    assert len(real_states) == len(action_plan) + 1
    steps_from_stream = get_steps_from_stream(stream_plan, step_from_fact,
                                              node_from_atom)

    # TODO: ensure that derived facts aren't in fluents?
    # TODO: handle case where costs depend on the outputs
    _, outgoing_edges = neighbors_from_orders(
        get_partial_orders(stream_plan,
                           init_facts=map(
                               fact_from_fd,
                               filter(lambda f: isinstance(f, pddl.Atom),
                                      real_states[0]))))
    static_plan = []
    fluent_plan = []
    for result in stream_plan:
        external = result.external
        if isinstance(result, FunctionResult) or (result.opt_index != 0) or (
                not external.is_fluent):
            static_plan.append(result)
            continue
        if outgoing_edges[result]:
            # No way of taking into account the binding of fluent inputs when preventing cycles
            raise NotImplementedError(
                'Fluent stream is required for another stream: {}'.format(
                    result))
        #if (len(steps_from_stream[result]) != 1) and result.output_objects:
        #    raise NotImplementedError('Fluent stream required in multiple states: {}'.format(result))
        for state_index in steps_from_stream[result]:
            new_output_objects = [
                #OptimisticObject.from_opt(out.value, object())
                OptimisticObject.from_opt(
                    out.value, UniqueOptValue(result.instance, object(), name))
                for name, out in safe_zip(result.external.outputs,
                                          result.output_objects)
            ]
            if new_output_objects and (state_index <= len(action_plan) - 1):
                # TODO: check that the objects aren't used in any effects
                instance = copy.copy(action_plan[state_index])
                action_plan[state_index] = instance
                output_mapping = get_mapping(
                    list(map(pddl_from_object, result.output_objects)),
                    list(map(pddl_from_object, new_output_objects)))
                instance.var_mapping = {
                    p: output_mapping.get(v, v)
                    for p, v in instance.var_mapping.items()
                }
            new_instance = get_fluent_instance(external,
                                               result.instance.input_objects,
                                               real_states[state_index])
            # TODO: handle optimistic here
            new_result = new_instance.get_result(new_output_objects,
                                                 opt_index=result.opt_index)
            fluent_plan.append(new_result)
    return static_plan + fluent_plan
Example #3
0
 def wrap_optimistic(self, output_values, call_index):
     output_objects = []
     for name, value in safe_zip(self.external.outputs, output_values):
         unique = UniqueOptValue(instance=self,
                                 sequence_index=call_index,
                                 output=name)  # object()
         param = unique if (
             self.opt_index
             == 0) else value  # TODO: make a proper abstraction generator
         output_objects.append(OptimisticObject.from_opt(value, param))
     return tuple(output_objects)
Example #4
0
def convert_fluent_streams(stream_plan, real_states, action_plan,
                           step_from_fact, node_from_atom):
    import pddl
    assert len(real_states) == len(action_plan) + 1
    steps_from_stream = {}
    for result in reversed(stream_plan):
        steps_from_stream[result] = set()
        for fact in result.get_certified():
            if (fact in step_from_fact) and (node_from_atom[fact].result
                                             == result):
                steps_from_stream[result].update(step_from_fact[fact])
        for fact in result.instance.get_domain():
            step_from_fact[fact] = step_from_fact.get(
                fact, set()) | steps_from_stream[result]
            # TODO: apply this recursively

    # TODO: ensure that derived facts aren't in fluents?
    # TODO: handle case where costs depend on the outputs
    _, outgoing_edges = neighbors_from_orders(
        get_partial_orders(stream_plan,
                           init_facts=map(
                               fact_from_fd,
                               filter(lambda f: isinstance(f, pddl.Atom),
                                      real_states[0]))))
    static_plan = []
    fluent_plan = []
    for result in stream_plan:
        external = result.external
        if (result.opt_index != 0) or (not external.is_fluent()):
            static_plan.append(result)
            continue
        if outgoing_edges[result]:
            # No way of taking into account the binding of fluent inputs when preventing cycles
            raise NotImplementedError(
                'Fluent stream is required for another stream: {}'.format(
                    result))
        #if (len(steps_from_stream[result]) != 1) and result.output_objects:
        #    raise NotImplementedError('Fluent stream required in multiple states: {}'.format(result))
        for state_index in steps_from_stream[result]:
            new_output_objects = [  # OptimisticObject.from_opt(out.value, object())
                OptimisticObject.from_opt(
                    out.value, UniqueOptValue(result.instance, object(), i))
                for i, out in enumerate(result.output_objects)
            ]
            if new_output_objects and (state_index < len(action_plan)):
                # TODO: check that the objects aren't used in any effects
                instance = copy.copy(action_plan[state_index])
                action_plan[state_index] = instance
                output_mapping = get_mapping(
                    map(pddl_from_object, result.output_objects),
                    map(pddl_from_object, new_output_objects))
                instance.var_mapping = {
                    p: output_mapping.get(v, v)
                    for p, v in instance.var_mapping.items()
                }
            fluent_facts = list(
                map(
                    fact_from_fd,
                    filter(
                        lambda f: isinstance(f, pddl.Atom) and
                        (f.predicate in external.fluents),
                        real_states[state_index])))
            new_instance = external.get_instance(result.instance.input_objects,
                                                 fluent_facts=fluent_facts)
            new_result = new_instance.get_result(new_output_objects,
                                                 opt_index=result.opt_index)
            fluent_plan.append(new_result)
    return static_plan + fluent_plan