Beispiel #1
0
def simple_from_durative_action(durative_actions, fluents):
    from pddlstream.algorithms.algorithm import get_predicates
    import pddl
    simple_actions = {}
    for action in durative_actions:
        parameters = convert_parameters(action.parameters)
        conditions = list(map(convert_condition, action.condition))
        start_effects, end_effects = action.effects
        over_effects = []
        effects = list(
            map(convert_effects, [start_effects, over_effects, end_effects]))

        static_condition = pddl.Conjunction(
            list({
                part
                for condition in conditions
                for part in get_conjunctive_parts(condition.simplified())
                if not isinstance(part, pddl.Truth)
                and not (get_predicates(part) & fluents)
            }))
        # TODO: deal with case where there are fluents
        actions = []
        for i, (condition, effect) in enumerate(safe_zip(conditions, effects)):
            # TODO: extract the durations by pretending they are action costs
            actions.append(
                pddl.Action(
                    SIMPLE_TEMPLATE.format(action.name, i), parameters,
                    len(parameters),
                    pddl.Conjunction([static_condition,
                                      condition]).simplified(), effect, None))
            #actions[-1].dump()
        simple_actions[action] = actions
    return simple_actions
Beispiel #2
0
def simple_from_durative_action(durative_actions, fluents):
    import pddl
    simple_actions = {}
    for action in durative_actions:
        parameters = convert_parameters(action.parameters)
        conditions = list(map(convert_condition, action.condition))
        start_effects, end_effects = action.effects
        over_effects = []
        effects = list(
            map(convert_effects, [start_effects, over_effects, end_effects]))

        static_condition = pddl.Conjunction(
            list({
                literal
                for condition in conditions
                for literal in get_conjunctive_parts(condition.simplified())
                if literal.predicate not in fluents
            }))
        actions = []
        for i, (condition, effect) in enumerate(safe_zip(conditions, effects)):
            actions.append(
                pddl.Action(
                    SIMPLE_TEMPLATE.format(action.name, i), parameters,
                    len(parameters),
                    pddl.Conjunction([static_condition,
                                      condition]).simplified(), effect, None))
            #actions[-1].dump()
        simple_actions[action] = actions
    return simple_actions
Beispiel #3
0
def get_stream_action(result, name, unit_cost, effect_scale=1):
    #from pddl_parser.parsing_functions import parse_action
    import pddl

    parameters = []
    preconditions = [
        fd_from_fact(fact) for fact in result.instance.get_domain()
    ]
    precondition = pddl.Conjunction(preconditions)
    effects = [
        pddl.Effect(parameters=[],
                    condition=pddl.Truth(),
                    literal=fd_from_fact(fact))
        for fact in result.get_certified()
    ]

    effort = 1 if unit_cost else result.instance.get_effort()
    if effort == INF:
        return None
    fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[])
    expression = pddl.NumericConstant(int_ceil(effect_scale *
                                               effort))  # Integer
    cost = pddl.Increase(fluent=fluent,
                         expression=expression)  # Can also be None

    return pddl.Action(name=name,
                       parameters=parameters,
                       num_external_parameters=len(parameters),
                       precondition=precondition,
                       effects=effects,
                       cost=cost)
Beispiel #4
0
    def add_inequality_preconds(self, action, reachable_action_params):
        if reachable_action_params is None or len(action.parameters) < 2:
            return action
        inequal_params = []
        combs = itertools.combinations(range(len(action.parameters)), 2)
        for pos1, pos2 in combs:
            for params in reachable_action_params[action]:
                if params[pos1] == params[pos2]:
                    break
            else:
                inequal_params.append((pos1, pos2))

        if inequal_params:
            precond_parts = [action.precondition]
            for pos1, pos2 in inequal_params:
                param1 = action.parameters[pos1].name
                param2 = action.parameters[pos2].name
                new_cond = pddl.NegatedAtom("=", (param1, param2))
                precond_parts.append(new_cond)
            precond = pddl.Conjunction(precond_parts).simplified()
            return pddl.Action(
                action.name, action.parameters, action.num_external_parameters,
                precond, action.effects, action.cost)
        else:
            return action
Beispiel #5
0
    def add_inequality_preconds(self, action, reachable_action_params):
        if reachable_action_params is None or len(action.parameters) < 2:
            return action
        inequal_params = []
        combs = itertools.combinations(range(len(action.parameters)), 2)
        for pos1, pos2 in combs:
            inequality = True
            for params in reachable_action_params[action.name]:
                if params[pos1] == params[pos2]:
                    inequality = False
                    break
            if inequality:
                inequal_params.append((pos1, pos2))

        if inequal_params:
            precond_parts = list(action.precondition.parts)
            for pos1, pos2 in inequal_params:
                param1 = action.parameters[pos1].name
                param2 = action.parameters[pos2].name
                new_cond = pddl.NegatedAtom("=", (param1, param2))
                precond_parts.append(new_cond)
            precond = action.precondition.change_parts(precond_parts)
            return pddl.Action(action.name, action.parameters, precond,
                               action.effects, action.cost)
        else:
            return action
Beispiel #6
0
 def __init__(self, task, reachable_action_params):
     self.predicates_to_add_actions = defaultdict(set)
     self.action_to_heavy_action = {}
     for act in task.actions:
         action = self.add_inequality_preconds(act, reachable_action_params)
         too_heavy_effects = []
         create_heavy_act = False
         heavy_act = action
         # FOND
         for nondet_choice in action.effects:
             too_heavy_nondet_choice = []
             for eff in nondet_choice:
                 too_heavy_nondet_choice.append(eff)
                 if eff.parameters:  # universal effect
                     create_heavy_act = True
                     too_heavy_nondet_choice.append(eff.copy())
                 if not eff.literal.negated:
                     predicate = eff.literal.predicate
                     self.predicates_to_add_actions[predicate].add(action)
             too_heavy_effects.append(too_heavy_nondet_choice)
         if create_heavy_act:
             heavy_act = pddl.Action(action.name, action.parameters,
                                     action.num_external_parameters,
                                     action.precondition, too_heavy_effects,
                                     action.observation, action.cost)
         # heavy_act: duplicated universal effects and assigned unique names
         # to all quantified variables (implicitly in constructor)
         self.action_to_heavy_action[action] = heavy_act
Beispiel #7
0
    def __init__(self, task, reachable_action_params):
#        print("*'*'*'*DEBUG invariant_finder.BalanceChecker.__init__*'*'*'*")
        self.predicates_to_add_actions = defaultdict(set)
        self.action_to_heavy_action = {}
        for act in task.actions:
            action = self.add_inequality_preconds(act, reachable_action_params)
            too_heavy_effects = []
            create_heavy_act = False
            heavy_act = action
            for eff in action.effects:
                too_heavy_effects.append(eff)
                if eff.parameters: # universal effect
                    create_heavy_act = True
                    too_heavy_effects.append(eff.copy())
                if isinstance(eff.peffect, pddl.Atom): #not eff.peffect.negated:
                    predicate = eff.peffect.predicate
                    self.predicates_to_add_actions[predicate].add(action)
            if create_heavy_act:
                heavy_act = pddl.Action(action.name, action.parameters,
                                        action.num_external_parameters,
                                        action.precondition, too_heavy_effects,
                                        action.cost)
            # heavy_act: duplicated universal effects and assigned unique names
            # to all quantified variables (implicitly in constructor)
            self.action_to_heavy_action[action] = heavy_act
Beispiel #8
0
def make_action(name, parameters, preconditions, effects, cost=None):
    # Usually all parameters are external
    return pddl.Action(name=name,
                       parameters=make_parameters(parameters),
                       num_external_parameters=len(parameters),
                       precondition=make_preconditions(preconditions),
                       effects=make_effects(effects),
                       cost=make_cost(cost))
Beispiel #9
0
def transform_exp_actions(actions, mutex_groups):
    """ 
    Exponential transformation of actions with sdac 
    into actions with constant action costs.
    """

    mutex_dict = dict()
    for group in mutex_groups:
        for elem in group:
            mutex_dict[elem] = group
    del_actions = []
    new_actions = actions
    add_actions = []
    for action in new_actions:
        if isinstance(action.cost, pddl_parser.CostNode):
            del_actions.append(action)
            if not is_usefull(action):
                continue
            at_list = []
            consistent_actions = []
            used_dict = dict()
            for atom in action.cost.get_atoms_set():
                if atom not in mutex_dict:
                    at_list.append(
                        [atom,
                         pddl.NegatedAtom(atom.predicate, atom.args)])
                elif len(mutex_dict[atom]) == 1:
                    at_list.append(
                        [atom,
                         pddl.NegatedAtom(atom.predicate, atom.args)])
                elif str(mutex_dict[atom]) not in used_dict:
                    at_list.append(mutex_dict[atom])
                    used_dict[str(mutex_dict[atom])] = True
            for combi in itertools.product(*at_list):
                pre = []
                pre.extend(action.precondition)
                pre.extend(combi)
                if not is_consistent(combi, action.precondition, mutex_dict):
                    continue
                if isinstance(action, pddl.Action):
                    action_copy = pddl.Action(action.name, action.parameters,
                                              action.num_external_parameters,
                                              pre, action.effects,
                                              str(action.cost.get_cost(combi)))
                else:
                    action_copy = pddl.PropositionalAction(
                        action.name, pre, [], str(action.cost.get_cost(combi)))
                    action_copy.add_effects.extend(action.add_effects)
                    action_copy.del_effects.extend(action.del_effects)
                consistent_actions.append(action_copy)
            add_actions.extend(consistent_actions)
    for a in del_actions:
        new_actions.remove(a)
    new_actions.extend(add_actions)
    return new_actions
Beispiel #10
0
def get_necessary_axioms(conditions, axioms, negative_from_name):
    if not conditions or not axioms:
        return {}
    axioms_from_name = get_derived_predicates(axioms)
    atom_queue = []
    processed_atoms = set()

    def add_literals(literals):
        for lit in literals:
            atom = lit.positive()
            if atom not in processed_atoms:
                atom_queue.append(
                    atom)  # Previously was lit.positive() for some reason?
                processed_atoms.add(atom)

    import pddl
    add_literals(conditions)
    axiom_from_action = {}
    partial_instantiations = set()
    while atom_queue:
        literal = atom_queue.pop()
        for axiom in axioms_from_name[literal.predicate]:
            derived_parameters = axiom.parameters[:axiom.
                                                  num_external_parameters]
            var_mapping = {
                p.name: a
                for p, a in zip(derived_parameters, literal.args)
                if not is_parameter(a)
            }
            key = (axiom, frozenset(var_mapping.items()))
            if key in partial_instantiations:
                continue
            partial_instantiations.add(key)
            parts = [
                l.rename_variables(var_mapping)
                for l in get_literals(axiom.condition)
                if l.predicate not in negative_from_name
            ]  # Assumes a conjunction?
            # new_condition = axiom.condition.uniquify_variables(None, var_mapping)
            effect_args = [
                var_mapping.get(a.name, a.name) for a in derived_parameters
            ]
            effect = pddl.Effect([], pddl.Truth(),
                                 pddl.conditions.Atom(axiom.name, effect_args))
            free_parameters = [
                p for p in axiom.parameters if p.name not in var_mapping
            ]
            new_action = pddl.Action(axiom.name, free_parameters,
                                     len(free_parameters),
                                     pddl.Conjunction(parts), [effect], None)
            # Creating actions so I can partially instantiate (impossible with axioms)
            axiom_from_action[new_action] = (axiom, var_mapping)
            add_literals(parts)
    return axiom_from_action
Beispiel #11
0
def get_necessary_axioms(instance, axioms, negative_from_name):
    import pddl

    axioms_from_name = get_derived_predicates(axioms)
    atom_queue = []
    processed_atoms = set()

    def add_literals(literals):
        for literal in literals:
            atom = literal.positive()
            if atom not in processed_atoms:
                atom_queue.append(literal.positive())
                processed_atoms.add(atom)

    add_literals(instance.precondition)
    for (cond, _) in (instance.add_effects + instance.del_effects):
        add_literals(cond)

    axiom_from_action = {}
    partial_instantiations = set()
    while atom_queue:
        literal = atom_queue.pop()
        for axiom in axioms_from_name[literal.predicate]:
            derived_parameters = axiom.parameters[:axiom.
                                                  num_external_parameters]
            var_mapping = {
                p.name: a
                for p, a in zip(derived_parameters, literal.args)
                if a[0] != '?'
            }
            key = (axiom, frozenset(var_mapping.items()))
            if key in partial_instantiations:
                continue
            partial_instantiations.add(key)
            parts = []
            for literal in get_literals(axiom.condition):
                if literal.predicate in negative_from_name:
                    continue
                parts.append(literal.rename_variables(var_mapping))
            # new_condition = axiom.condition.uniquify_variables(None, var_mapping)
            effect_args = [
                var_mapping.get(a.name, a.name) for a in derived_parameters
            ]
            effect = pddl.Effect([], pddl.Truth(),
                                 pddl.conditions.Atom(axiom.name, effect_args))
            free_parameters = [
                p for p in axiom.parameters if p.name not in var_mapping
            ]
            new_action = pddl.Action(axiom.name, free_parameters, 0,
                                     pddl.Conjunction(parts), [effect], None)
            # Creating actions so I can partially instantiate (impossible with axioms)
            axiom_from_action[new_action] = (axiom, var_mapping)
            add_literals(parts)
    return axiom_from_action
Beispiel #12
0
def parse_action(alist, type_dict, predicate_dict):
    if DEBUG: print("parsing action %s" % [alist])
    iterator = iter(alist)
    action_tag = next(iterator)
    assert action_tag == ":action", "Expected ':action' got '%s'" % action_tag
    name = next(iterator)
    parameters_tag_opt = next(iterator)
    if parameters_tag_opt == ":parameters":
        parameters = parse_typed_list(next(iterator), only_variables=True)
        precondition_tag_opt = next(iterator)
    else:
        parameters = []
        precondition_tag_opt = parameters_tag_opt
    if precondition_tag_opt == ":precondition":
        precondition_list = next(iterator)
        if not precondition_list:
            # Note that :precondition () is allowed in PDDL.
            precondition = pddl.Conjunction([])
        else:
            precondition = parse_condition(precondition_list, type_dict,
                                           predicate_dict)
            precondition = precondition.simplified()
        effect_tag = next(iterator)
    else:
        precondition = pddl.Conjunction([])
        effect_tag = precondition_tag_opt
    assert effect_tag == ":effect"
    effect_list = next(iterator)
    eff = []
    if effect_list:
        try:
            cost = parse_effects(effect_list, eff, type_dict, predicate_dict)
            if cost is None and eff:
                if DEBUG:
                    print(
                        "adding artificial effect (increase total-cost 1) to %s"
                        % name)
                cost = pddl.NumericEffect(
                    parse_assignment(['increase', 'total-cost', 1])
                )  # artificially add a numeric effect that increases the total cost by one
                add_effect(cost, eff)
            assert (isinstance(cost, pddl.NumericEffect)
                    ), "instance of cost is %s " % cost.__class__
        except ValueError as e:
            raise SystemExit("Error in Action %s\nReason: %s." % (name, e))
    for rest in iterator:
        assert False, rest
    if eff:
        return pddl.Action(name, parameters, len(parameters), precondition,
                           eff, cost)
    else:
        return None
def parse_action(alist, type_dict, predicate_dict):
    iterator = iter(alist)
    action_tag = next(iterator)
    assert action_tag == ":action"
    name = next(iterator)
    parameters_tag_opt = next(iterator)
    if parameters_tag_opt == ":parameters":
        parameters = parse_typed_list(next(iterator), only_variables=True)
        precondition_tag_opt = next(iterator)
    else:
        parameters = []
        precondition_tag_opt = parameters_tag_opt
    parameters_dict = dict((p.name, p) for p in parameters)
    if precondition_tag_opt == ":precondition":
        precondition_list = next(iterator)
        if not precondition_list:
            # Note that :precondition () is allowed in PDDL.
            precondition = pddl.Conjunction([])
        else:
            precondition = parse_condition(precondition_list, type_dict,
                                           predicate_dict)
            precondition = precondition.simplified()
        effect_tag = next(iterator)
    else:
        precondition = pddl.Conjunction([])
        effect_tag = precondition_tag_opt
    assert effect_tag == ":effect"
    effect_list = next(iterator)
    eff = []
    if effect_list:
        try:
            cost = parse_effects(effect_list, eff, type_dict, predicate_dict)
        except ValueError as e:
            raise SystemExit("Error in Action %s\nReason: %s." % (name, e))
    for rest in iterator:
        # Parse cost function
        if rest == ":cost":
            outer_op = None
            cost_list = next(iterator)
            cost = cost_node.CostNode("")
            cost = cost.parse_cost(cost_list, outer_op, predicate_dict,
                                   parameters_dict, cost)
            break
    for rest in iterator:
        assert False, rest
    if eff:
        return pddl.Action(name, parameters, len(parameters), precondition,
                           eff, cost)
    else:
        return None
Beispiel #14
0
def parse_action(alist, type_dict, predicate_dict):
    iterator = iter(alist)
    action_tag = next(iterator)
    assert action_tag == ":action" or action_tag == ':action'
    name = next(iterator)
    parameters_tag_opt = next(iterator)
    if parameters_tag_opt == ":parameters":
        parameters = parse_typed_list(next(iterator), only_variables=True)
        precondition_tag_opt = next(iterator)
    else:
        parameters = []
        precondition_tag_opt = parameters_tag_opt
    if precondition_tag_opt == ":precondition":
        precondition_list = next(iterator)
        if not precondition_list:
            # Note that :precondition () is allowed in PDDL.
            precondition = pddl.Conjunction([])
        else:
            precondition = parse_condition(precondition_list, type_dict,
                                           predicate_dict)
            precondition = precondition.simplified()
        effect_tag = next(iterator)
    else:
        precondition = pddl.Conjunction([])
        effect_tag = precondition_tag_opt
    assert effect_tag == ":effect"
    effect_list = next(iterator)
    eff = []
    if effect_list:
        try:
            cost = parse_effects(effect_list, eff, type_dict, predicate_dict)
        except ValueError as e:
            raise SystemExit("Error in Action %s\nReason: %s." % (name, e))
    next(iterator) == ":duration"
    duration = next(iterator)
    if len(duration[2]) == 1:
        duration = pddl.NumericConstant(int(duration[2]))
    else:
        duration = pddl.f_expression.PrimitiveNumericExpression(
            duration[2][0], duration[2][1:])
    for rest in iterator:
        assert False, rest
    if eff:
        return pddl.Action(name, parameters, len(parameters), precondition,
                           eff, cost, duration)
    else:
        return None
def parse_action(alist, type_dict, predicate_dict):
    iterator = iter(alist)
    action_tag = next(iterator)
    assert action_tag == ":action"
    name = next(iterator)
    parameters_tag_opt = next(iterator)
    if parameters_tag_opt == ":parameters":
        parameters = parse_typed_list(next(iterator),
                                      only_variables=True)
        precondition_tag_opt = next(iterator)
    else:
        parameters = []
        precondition_tag_opt = parameters_tag_opt
    if precondition_tag_opt == ":precondition":
        precondition_list = next(iterator)
        if not precondition_list:
            # Note that :precondition () is allowed in PDDL.
            precondition = pddl.Conjunction([])
        else:
            precondition = parse_condition(
                precondition_list, type_dict, predicate_dict)
            precondition = precondition.simplified()
        effect_tag = next(iterator)
    else:
        precondition = pddl.Conjunction([])
        effect_tag = precondition_tag_opt
    assert effect_tag == ":effect"
    effect_list = next(iterator)
    eff = []
    if effect_list:
        try:
            cost = parse_effects(
                effect_list, eff, type_dict, predicate_dict)
        except ValueError as e:
            raise SystemExit("Error in Action %s\nReason: %s." % (name, e))
    for rest in iterator:
        assert False, rest
    # if eff:
    #     return pddl.Action(name, parameters, len(parameters),
    #                        precondition, eff, cost)
    # else:
    #     return None

    return pddl.Action(name, parameters, len(parameters),
                           precondition, eff, None)
Beispiel #16
0
def get_stream_actions(results,
                       unique_binding=False,
                       unit_efforts=True,
                       effort_scale=1):
    #from pddl_parser.parsing_functions import parse_action
    import pddl
    stream_result_from_name = {}
    stream_actions = []
    for i, result in enumerate(results):
        #if not isinstance(stream_result, StreamResult):
        if type(result) == FunctionResult:
            continue
        effort = get_instance_effort(result.instance, unit_efforts)
        if effort == INF:
            continue
        # TODO: state constraints
        # TODO: selectively negate axioms
        result_name = '{}-{}'.format(result.external.name, i)
        #result_name = '{}_{}_{}'.format(result.external.name, # No spaces & parens
        #                        ','.join(map(pddl_from_object, result.instance.input_objects)),
        #                        ','.join(map(pddl_from_object, result.output_objects)))
        assert result_name not in stream_result_from_name
        stream_result_from_name[result_name] = result

        preconditions = list(result.instance.get_domain())
        effects = list(result.get_certified())
        #if ORDER_OUTPUT:
        #    enforce_output_order(result, preconditions, effects)
        if unique_binding:
            enforce_single_binding(result, preconditions, effects)
        if is_optimizer_result(
                result):  # These effects don't seem to be pruned
            effects.append(
                substitute_expression(result.external.stream_fact,
                                      result.get_mapping()))
        parameters = []  # Usually all parameters are external
        stream_actions.append(
            pddl.Action(name=result_name,
                        parameters=parameters,
                        num_external_parameters=len(parameters),
                        precondition=make_preconditions(preconditions),
                        effects=make_effects(effects),
                        cost=make_cost(effort_scale *
                                       effort)))  # Can also be None
    return stream_actions, stream_result_from_name
Beispiel #17
0
    def visit_action_stmt(self, node):
        """Visits a PDDL action statement."""
        signature = list()
        # Visit all parameters and create signature.
        for v in node.parameters:
            v.accept(self)
            signatureTuple = self.get_in(v)
            signature.append(signatureTuple)

        # Visit the precondition statement.
        node.precond.accept(self)
        precond = self.get_in(node.precond)

        # Visit the effect statement.
        node.effect.accept(self)
        effect = self.get_in(node.effect)

        # Create new PDDL action and store in node.
        self.set_in(node, pddl.Action(node.name, signature, precond, effect))
Beispiel #18
0
def compile_to_exogenous_actions(evaluations, domain, streams):
    import pddl
    # TODO: automatically derive fluents
    # TODO: version of this that operates on fluents of length one?
    # TODO: better instantiation when have full parameters
    # TODO: conversion from stream cost to real cost units?
    # TODO: any predicates derived would need to be replaced as well
    fluent_predicates = get_fluents(domain)
    certified_predicates = {
        get_prefix(a)
        for s in streams for a in s.certified
    }
    future_map = {p: 'f-{}'.format(p) for p in certified_predicates}
    augment_evaluations(evaluations, future_map)
    rename_future = lambda a: rename_atom(a, future_map)
    for stream in list(streams):
        if not isinstance(stream, Stream):
            raise NotImplementedError(stream)
        # TODO: could also just have conditions asserting that one of the fluent conditions fails
        streams.append(
            create_static_stream(stream, evaluations, fluent_predicates,
                                 rename_future))
        stream_atom = streams[-1].certified[0]
        parameters = [
            pddl.TypedObject(p, OBJECT) for p in get_args(stream_atom)
        ]
        # TODO: add to predicates as well?
        domain.predicate_dict[get_prefix(stream_atom)] = pddl.Predicate(
            get_prefix(stream_atom), parameters)
        preconditions = [stream_atom] + list(stream.domain)
        effort = 1  # TODO: use stream info
        #effort = 1 if unit_cost else result.instance.get_effort()
        #if effort == INF:
        #    continue
        domain.actions.append(
            pddl.Action(name='call-{}'.format(stream.name),
                        parameters=parameters,
                        num_external_parameters=len(parameters),
                        precondition=make_preconditions(preconditions),
                        effects=make_effects(stream.certified),
                        cost=make_cost(effort)))
        stream.certified = tuple(
            set(stream.certified) | set(map(rename_future, stream.certified)))
Beispiel #19
0
def compile_to_exogenous_actions(evaluations, domain, streams):
    import pddl
    # TODO: automatically derive fluents
    # TODO: version of this that operates on fluents of length one?
    # TODO: better instantiation when have full parameters
    # TODO: conversion from stream cost to real cost units?
    # TODO: any predicates derived would need to be replaced as well
    fluent_predicates = get_fluents(domain)
    domain_predicates = {get_prefix(a) for s in streams for a in s.domain}
    if not (domain_predicates & fluent_predicates):
        return

    certified_predicates = {get_prefix(a) for s in streams for a in s.certified}
    future_map = {p: 'f-{}'.format(p) for p in certified_predicates}
    augment_evaluations(evaluations, future_map)
    rename_future = lambda a: rename_atom(a, future_map)
    for stream in list(streams):
        if not isinstance(stream, Stream):
            raise NotImplementedError(stream)
        # TODO: could also just have conditions asserting that one of the fluent conditions fails
        streams.append(create_static_stream(stream, evaluations, fluent_predicates, rename_future))
        stream_atom = streams[-1].certified[0]
        parameters = [pddl.TypedObject(p, 'object') for p in get_args(stream_atom)]
        # TODO: add to predicates as well?
        domain.predicate_dict[get_prefix(stream_atom)] = pddl.Predicate(get_prefix(stream_atom), parameters)
        precondition = pddl.Conjunction(tuple(map(fd_from_fact, (stream_atom,) + tuple(stream.domain))))
        effects = [pddl.Effect(parameters=[], condition=pddl.Truth(),
                               literal=fd_from_fact(fact)) for fact in stream.certified]
        effort = 1 # TODO: use stream info
        #effort = 1 if unit_cost else result.instance.get_effort()
        #if effort == INF:
        #    continue
        fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[])
        expression = pddl.NumericConstant(int_ceil(effort)) # Integer
        cost = pddl.Increase(fluent=fluent, expression=expression) # Can also be None
        domain.actions.append(pddl.Action(name='call-{}'.format(stream.name),
                                          parameters=parameters,
                                          num_external_parameters=len(parameters),
                                          precondition=precondition, effects=effects, cost=cost))
        stream.certified = tuple(set(stream.certified) |
                                 set(map(rename_future, stream.certified)))
Beispiel #20
0
def simplify_actions(opt_evaluations, action_plan, task, actions, unit_costs):
    # TODO: add ordering constraints to simplify the optimization
    import pddl
    import instantiate

    fluent_facts = MockSet()
    init_facts = set()
    type_to_objects = instantiate.get_objects_by_type(task.objects, task.types)
    results_from_head = get_results_from_head(opt_evaluations)

    action_from_name = {}
    function_plan = set()
    for i, (name, args) in enumerate(action_plan):
        action = find_unique(lambda a: a.name == name, actions)
        assert (len(action.parameters) == len(args))
        # parameters = action.parameters[:action.num_external_parameters]
        var_mapping = {p.name: a for p, a in zip(action.parameters, args)}
        new_name = '{}-{}'.format(name, i)
        new_parameters = action.parameters[len(args):]
        new_preconditions = []
        action.precondition.instantiate(var_mapping, init_facts, fluent_facts, new_preconditions)
        new_effects = []
        for eff in action.effects:
            eff.instantiate(var_mapping, init_facts, fluent_facts, type_to_objects, new_effects)
        new_effects = [pddl.Effect([], pddl.Conjunction(conditions), effect)
                       for conditions, effect in new_effects]
        cost = pddl.Increase(fluent=pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]),
                             expression=pddl.NumericConstant(1))
        # cost = None
        task.actions.append(pddl.Action(new_name, new_parameters, len(new_parameters),
                                        pddl.Conjunction(new_preconditions), new_effects, cost))
        action_from_name[new_name] = (name, map(obj_from_pddl, args))
        if not unit_costs:
            function_result = extract_function_results(results_from_head, action, args)
            if function_result is not None:
                function_plan.add(function_result)
    return action_from_name, list(function_plan)
Beispiel #21
0
def sequential_stream_plan(evaluations, goal_expression, domain, stream_results, negated, unit_costs=True, **kwargs):
    if negated:
        raise NotImplementedError()
    # 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 = solve_from_task(opt_task, **kwargs)
    if action_plan is None:
        return None, action_cost

    import instantiate
    fluent_facts = MockSet()
    init_facts = set()
    task = task_from_domain_problem(domain, get_problem(evaluations, goal_expression, domain, unit_costs))

    type_to_objects = instantiate.get_objects_by_type(task.objects, task.types)
    task.actions, stream_result_from_name = get_stream_actions(stream_results)
    results_from_head = get_results_from_head(opt_evaluations)

    # TODO: add ordering constraints to simplify the optimization
    import pddl
    action_from_name = {}
    function_plan = set()
    for i, (name, args) in enumerate(action_plan):
        action = find_unique(lambda a: a.name == name, domain.actions)
        assert(len(action.parameters) == len(args))
        #parameters = action.parameters[:action.num_external_parameters]
        var_mapping = {p.name: a for p, a in zip(action.parameters, args)}
        new_name = '{}-{}'.format(name, i)
        new_parameters = action.parameters[len(args):]
        new_preconditions = []
        action.precondition.instantiate(var_mapping, init_facts, fluent_facts, new_preconditions)
        new_effects = []
        for eff in action.effects:
            eff.instantiate(var_mapping, init_facts, fluent_facts, type_to_objects, new_effects)
        new_effects = [pddl.Effect([], pddl.Conjunction(conditions), effect)
                      for conditions, effect in new_effects]
        cost = pddl.Increase(fluent=pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[]),
                             expression=pddl.NumericConstant(1))
        #cost = None
        task.actions.append(pddl.Action(new_name, new_parameters, 0,
                                   pddl.Conjunction(new_preconditions), new_effects, cost))
        action_from_name[new_name] = (name, map(obj_from_pddl, args))
        if not unit_costs:
            function_plan.update(extract_function_results(results_from_head, action, args))

    planner = kwargs.get('planner', 'ff-astar')
    combined_plan, _ = solve_from_task(task, planner=planner, **kwargs)
    if combined_plan is None:
        return None, obj_from_pddl_plan(action_plan), 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])
    stream_plan += list(function_plan)
    combined_plan = stream_plan + action_plan

    return combined_plan, action_cost
Beispiel #22
0
def parse_action(alist, type_dict, predicate_dict):
    iterator = iter(alist)
    action_tag = next(iterator)
    assert action_tag == ":action"
    name = next(iterator)
    parameters_tag_opt = next(iterator)
    if parameters_tag_opt == ":parameters":
        parameters = parse_typed_list(next(iterator), only_variables=True)
        precondition_tag_opt = next(iterator)
    else:
        parameters = []
        precondition_tag_opt = parameters_tag_opt
    if precondition_tag_opt == ":precondition":
        precondition_list = next(iterator)
        if not precondition_list:
            # Note that :precondition () is allowed in PDDL.
            precondition = pddl.Conjunction([])
        else:
            precondition = parse_condition(precondition_list, type_dict,
                                           predicate_dict)
            precondition = precondition.simplified()
        effect_tag = next(iterator)
    else:
        precondition = pddl.Conjunction([])
        effect_tag = precondition_tag_opt
    assert effect_tag == ":effect"
    effect_list = next(iterator)
    eff = []
    if effect_list:
        try:
            cost_eff_pairs = parse_effects(effect_list, eff, type_dict,
                                           predicate_dict)
            if 1 == len(cost_eff_pairs):
                cost_eff_pairs = [(cost_eff_pairs[0][0], cost_eff_pairs[0][1],
                                   '')]
            else:
                # Convert floats to fractions to output
                # TODO : Benchmark this fraction conversion
                all_fractions = []
                # summed = fractions.Fraction(0)
                for cep in cost_eff_pairs:
                    all_fractions.append(
                        fractions.Fraction(cep[2]).limit_denominator())
                    # summed += all_fractions[-1]
                # assert(summed == fractions.Fraction(1))
                lcm = functools.reduce(
                    lambda a, b: (a * b) / fractions.gcd(a, b),
                    [f.denominator for f in all_fractions], 1)
                # Use the fractions and lcm to build the weights
                cost_eff_pairs = [(cost_eff_pairs[i][0], cost_eff_pairs[i][1],
                                   "_DETDUP_%d_WEIGHT_%d_%d" %
                                   (i, all_fractions[i].numerator *
                                    (lcm / all_fractions[i].denominator), lcm))
                                  for i in range(len(cost_eff_pairs))]
        except ValueError as e:
            raise SystemExit("Error in Action %s\nReason: %s." % (name, e))
    for rest in iterator:
        assert False, rest
    return [
        pddl.Action(name + suffix, parameters, len(parameters), precondition,
                    eff, cost) for (cost, eff, suffix) in cost_eff_pairs
    ]