Ejemplo n.º 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
Ejemplo n.º 2
0
def instantiate_unsatisfiable(state,
                              action,
                              var_mapping,
                              negative_from_name={}):
    precondition = []
    for effect in action.effects:
        if effect.literal.predicate == UNSATISFIABLE:
            # Condition must be false for plan to succeed
            conditions = set(get_conjunctive_parts(effect.condition))
            negative = {
                literal
                for literal in conditions
                if literal.predicate in negative_from_name
            }
            if not negative:
                continue
            assert len(negative) == 1
            # TODO: handle the case where negative is not used (not (CFree ..))
            normal_conjunction = pddl.Conjunction(conditions - negative)
            # TODO: assumes that can instantiate with just predicate_to_atoms
            normal_effect = pddl.Effect(effect.parameters, normal_conjunction,
                                        effect.literal)
            # TODO: avoid recomputing these
            objects_by_type = instantiate.get_objects_by_type([], [])
            predicate_to_atoms = instantiate.get_atoms_by_predicate(state)
            result = []
            normal_effect.instantiate(var_mapping, state, {effect.literal},
                                      objects_by_type, predicate_to_atoms,
                                      result)
            for _, _, _, mapping in result:
                for literal in negative:
                    new_literal = literal.rename_variables(mapping).negate()
                    assert (not new_literal.free_variables())
                    precondition.append(new_literal)
    return precondition
Ejemplo n.º 3
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
Ejemplo n.º 4
0
def process_conditional_effect(effect, negative_from_predicate):
    import pddl
    new_parts = []
    stream_facts = []
    for disjunctive in get_conjunctive_parts(effect.condition):
        for literal in get_disjunctive_parts(disjunctive):
            # TODO: assert only one disjunctive part
            if isinstance(literal,
                          pddl.Literal) and (literal.predicate
                                             in negative_from_predicate):
                stream = negative_from_predicate[literal.predicate]
                if not isinstance(stream, ConstraintStream):
                    new_parts.append(literal)
                    continue
                certified = find_unique(
                    lambda f: get_prefix(f) == literal.predicate,
                    stream.certified)
                mapping = get_mapping(get_args(certified), literal.args)
                stream_facts.append(
                    fd_from_fact(
                        substitute_expression(stream.stream_fact, mapping)))
                # TODO: add the negated literal as precondition here?
            else:
                new_parts.append(literal)
    return new_parts, stream_facts
Ejemplo n.º 5
0
def compile_fluents_as_attachments(domain, externals):
    import pddl
    state_streams = set(
        filter(lambda e: isinstance(e, Stream) and e.is_fluent(),
               externals))  # is_special
    if not state_streams:
        return externals

    predicate_map = get_predicate_map(state_streams)
    if predicate_map and (get_pyplanners_path() is None):
        # TODO: fluent streams with outputs
        # Could convert the free parameter to a constant
        raise NotImplementedError(
            'Algorithm does not support fluent streams: {}'.format(
                [stream.name for stream in state_streams]))

    domain.constants.append(make_object(PLACEHOLDER.pddl))
    for action in domain.actions:
        for effect in action.effects:
            # TODO: conditional effects
            if any(literal.predicate in predicate_map
                   for literal in get_literals(effect.condition)):
                raise ValueError(
                    'Attachments cannot be in action effects: {}'.format(
                        effect))
        action.attachments = {}
        preconditions = set()
        for literal in get_conjunctive_parts(action.precondition):
            #if not isinstance(literal, pddl.Literal):
            #    raise NotImplementedError('Only literals are supported: {}'.format(literal))
            if not get_predicates(literal) & set(predicate_map):
                preconditions.add(literal)
                continue
            if not isinstance(literal, pddl.Literal):
                raise NotImplementedError(literal)
            # Drops the original precondition
            stream = predicate_map[literal.predicate]
            mapping = remap_certified(literal, stream)
            assert mapping is not None
            action.attachments[literal] = stream
            preconditions.update(
                pddl.Atom(EQ, (mapping[out], PLACEHOLDER.pddl))
                for out in stream.outputs)
            preconditions.update(
                fd_from_fact(substitute_fact(fact, mapping))
                for fact in stream.domain)
        action.precondition = pddl.Conjunction(preconditions).simplified()
        #fn = lambda l: pddl.Truth() if l.predicate in predicate_map else l
        #action.precondition = replace_literals(fn, action.precondition).simplified()
        #action.dump()
    return [
        external for external in externals if external not in state_streams
    ]
Ejemplo n.º 6
0
def universal_to_conditional(action):
    import pddl
    new_parts = []
    unsatisfiable = fd_from_fact((UNSATISFIABLE,))
    for quant in get_conjunctive_parts(action.precondition):
        if isinstance(quant, pddl.UniversalCondition):
            condition = quant.parts[0]
            # TODO: normalize first?
            if isinstance(condition, pddl.Disjunction) or isinstance(condition, pddl.Literal):
                action.effects.append(pddl.Effect(quant.parameters, condition.negate(), unsatisfiable))
                continue
        new_parts.append(quant)
    action.precondition = pddl.Conjunction(new_parts)
Ejemplo n.º 7
0
def optimizer_conditional_effects(domain, externals):
    import pddl
    #from pddlstream.algorithms.scheduling.negative import get_negative_predicates
    # TODO: extend this to predicates
    if UNIVERSAL_TO_CONDITIONAL:
        negative_streams = list(filter(lambda e: e.is_negated(), externals))
    else:
        negative_streams = list(
            filter(
                lambda e: isinstance(e, ConstraintStream) and e.is_negated(),
                externals))
    negative_from_predicate = get_predicate_map(negative_streams)
    if not negative_from_predicate:
        return
    for action in domain.actions:
        universal_to_conditional(action)
        new_effects = []
        for effect in action.effects:
            if effect.literal.predicate != UNSATISFIABLE:
                new_effects.append(effect)
                continue
            new_parts = []
            stream_facts = []
            for disjunctive in get_conjunctive_parts(effect.condition):
                for literal in get_disjunctive_parts(disjunctive):
                    # TODO: assert only one disjunctive part
                    if isinstance(literal, pddl.Literal) and (
                            literal.predicate in negative_from_predicate):
                        stream = negative_from_predicate[literal.predicate]
                        if not isinstance(stream, ConstraintStream):
                            new_parts.append(literal)
                            continue
                        certified = find_unique(
                            lambda f: get_prefix(f) == literal.predicate,
                            stream.certified)
                        mapping = get_mapping(get_args(certified),
                                              literal.args)
                        stream_facts.append(
                            fd_from_fact(
                                substitute_expression(stream.stream_fact,
                                                      mapping)))
                        # TODO: add the negated literal as precondition here?
                    else:
                        new_parts.append(literal)
            if not stream_facts:
                new_effects.append(effect)
            for stream_fact in stream_facts:
                new_effects.append(
                    pddl.Effect(effect.parameters, pddl.Conjunction(new_parts),
                                stream_fact))
        action.effects = new_effects
Ejemplo n.º 8
0
def compile_fluent_attachments(domain, externals):
    import pddl
    state_streams = set(
        filter(lambda e: isinstance(e, Stream) and e.is_fluent(),
               externals))  # is_special
    predicate_map = get_predicate_map(state_streams)
    if predicate_map and not os.path.exists(PYPLANNERS_PATH):
        raise NotImplementedError(
            'Algorithm does not support fluent streams: {}'.format(
                [stream.name for stream in predicate_map.values()]))
    for action in domain.actions:
        for effect in action.effects:
            # TODO: conditional effects
            if any(literal.predicate in predicate_map
                   for literal in get_literals(effect.condition)):
                raise ValueError(effect)
        action.attachments = {}
        preconditions = []
        for literal in get_conjunctive_parts(action.precondition):
            if not isinstance(literal, pddl.Literal):
                raise NotImplementedError(literal)
            if literal.predicate in predicate_map:
                stream = predicate_map[literal.predicate]
                if not stream.is_test():
                    raise NotImplementedError(stream)
                assert remap_certified(literal, stream) is not None
                action.attachments[literal] = stream
            else:
                preconditions.append(literal)
        action.precondition = pddl.Conjunction(preconditions).simplified()
        #fn = lambda l: pddl.Truth() if l.predicate in predicate_map else l
        #action.precondition = replace_literals(fn, action.precondition).simplified()
        #action.dump()
    return [
        external for external in externals if external not in state_streams
    ]
Ejemplo n.º 9
0
def instantiate_goal(goal):
    goal_list = get_conjunctive_parts(goal)
    assert all(isinstance(item, pddl.Literal) for item in goal_list)
    return goal_list
Ejemplo n.º 10
0
def reinstantiate_action(state, instance, negative_from_name={}):
    # Recomputes the instances with without any pruned preconditions
    # TODO: making the assumption that no negative derived predicates
    action = instance.action
    var_mapping = instance.var_mapping
    init_facts = set()
    fluent_facts = MockSet()
    precondition = []
    try:
        action.precondition.instantiate(var_mapping, init_facts, fluent_facts,
                                        precondition)
    except pddl.conditions.Impossible:
        return None
    effects = []
    effect_from_literal = {
        literal: (cond, effect, effect_mapping)
        for cond, literal, effect, effect_mapping in instance.effect_mappings
    }
    for effect in action.effects:
        if effect.literal.predicate == UNSATISFIABLE:
            # Condition must be false for plan to succeed
            conditions = set(get_conjunctive_parts(effect.condition))
            negative = {
                literal
                for literal in conditions
                if literal.predicate in negative_from_name
            }
            if not negative:
                continue
            assert len(negative) == 1
            # TODO: handle the case where negative is not used (not (CFree ..))
            normal_conjunction = pddl.Conjunction(conditions - negative)
            # TODO: assumes that can instantiate with just predicate_to_atoms
            normal_effect = pddl.Effect(effect.parameters, normal_conjunction,
                                        effect.literal)
            # TODO: avoid recomputing these
            objects_by_type = instantiate.get_objects_by_type([], [])
            predicate_to_atoms = instantiate.get_atoms_by_predicate(state)
            result = []
            normal_effect.instantiate(var_mapping, state, {effect.literal},
                                      objects_by_type, predicate_to_atoms,
                                      result)
            for _, _, _, mapping in result:
                for literal in negative:
                    new_literal = literal.rename_variables(mapping).negate()
                    assert (not new_literal.free_variables())
                    precondition.append(new_literal)

    for literal in instance.applied_effects:
        cond, effect, effect_mapping = effect_from_literal[literal]
        if effect is None:  # Stream effect
            #effects.append((cond, literal, cond, effect))
            continue
        else:
            effect._instantiate(effect_mapping, init_facts, fluent_facts,
                                effects)

    new_effects = []
    for cond, effect, e, m in effects:
        precondition.extend(cond)
        new_effects.append(([], effect, e, m))
    return pddl.PropositionalAction(instance.name, precondition, new_effects,
                                    instance.cost, action, var_mapping)