示例#1
0
def fact_from_evaluation(evaluation):
    fact = Fact(evaluation.head.function, evaluation.head.args)
    if is_atom(evaluation):
        return fact
    elif is_negated_atom(evaluation):
        return Not(fact)
    return Equal(fact, evaluation.value)
示例#2
0
def instantiate_optimizer_axioms(instantiated, domain, results):
    # Needed for instantiating axioms before adding stream action effects
    # Otherwise, FastDownward will prune these unreachable axioms
    # TODO: compute this first and then apply the eager actions
    stream_init = {
        fd_from_fact(result.stream_fact)
        for result in results if isinstance(result, StreamResult)
    }
    evaluations = list(
        map(evaluation_from_fd, stream_init | instantiated.atoms))
    temp_domain = make_domain(
        predicates=[make_predicate(UNSATISFIABLE, [])],
        axioms=[ax for ax in domain.axioms if ax.name == UNSATISFIABLE])
    temp_problem = get_problem(evaluations, Not((UNSATISFIABLE, )),
                               temp_domain)
    # TODO: UNSATISFIABLE might be in atoms making the goal always infeasible
    with Verbose():
        # TODO: the FastDownward instantiation prunes static preconditions
        use_fd = False if using_optimizers(results) else FD_INSTANTIATE
        new_instantiated = instantiate_task(task_from_domain_problem(
            temp_domain, temp_problem),
                                            use_fd=use_fd,
                                            check_infeasible=False,
                                            prune_static=False)
        assert new_instantiated is not None
    instantiated.axioms.extend(new_instantiated.axioms)
    instantiated.atoms.update(new_instantiated.atoms)
示例#3
0
def add_unsatisfiable_to_goal(domain, goal_expression, negate_actions=False):
    import pddl
    add_predicate(domain, make_predicate(UNSATISFIABLE, []))
    if negate_actions:
        negated_atom = pddl.NegatedAtom(UNSATISFIABLE, tuple())
        for action in domain.actions:
            if negated_atom not in action.precondition.parts:
                action.precondition = pddl.Conjunction(
                    [action.precondition, negated_atom]).simplified()
    return And(goal_expression, Not((UNSATISFIABLE, )))
示例#4
0
def add_unsatisfiable_to_goal(domain, goal_expression):
    import pddl
    from pddlstream.language.optimizer import UNSATISFIABLE
    add_predicate(domain, make_predicate(UNSATISFIABLE, []))
    negated_atom = pddl.NegatedAtom(UNSATISFIABLE, tuple())
    for action in domain.actions:
        if negated_atom not in action.precondition.parts:
            action.precondition = pddl.Conjunction(
                [action.precondition, negated_atom]).simplified()
    return And(goal_expression, Not((UNSATISFIABLE, )))
示例#5
0
def augment_goal(domain, goal_expression, negate_actions=False):
    # TODO: only do this if optimizers are present
    #return goal_expression
    import pddl
    predicate = pddl.predicates.Predicate(UNSATISFIABLE, tuple())
    if predicate.name not in domain.predicate_dict:
        domain.predicates.append(predicate)
        domain.predicate_dict[predicate.name] = predicate
    if negate_actions:
        negated_atom = pddl.NegatedAtom(UNSATISFIABLE, tuple())
        for action in domain.actions:
            if negated_atom not in action.precondition.parts:
                action.precondition = pddl.Conjunction(
                    [action.precondition, negated_atom]).simplified()
    return And(goal_expression, Not((UNSATISFIABLE, )))
示例#6
0
def planning_from_satisfaction(init, constraints):
    clusters = cluster_constraints(constraints)
    prefix = get_internal_prefix(internal=False)
    assigned_predicate = ASSIGNED_PREDICATE.format(prefix)
    order_predicate = ORDER_PREDICATE.format(prefix)
    #order_value_facts = make_order_facts(order_predicate, 0, len(clusters)+1)
    order_value_facts = [(order_predicate, '_t{}'.format(i))
                         for i in range(len(clusters) + 1)]
    init.append(order_value_facts[0])
    goal_expression = order_value_facts[-1]
    order_facts = list(map(obj_from_value_expression, order_value_facts))
    bound_parameters = set()
    actions = []
    #constants = {}
    for i, cluster in enumerate(clusters):
        objectives = list(map(obj_from_value_expression, cluster.constraints))
        constraints, negated, costs = partition_facts(objectives)
        if negated:
            raise NotImplementedError(negated)
        #free_parameters = cluster.parameters - bound_parameters
        existing_parameters = cluster.parameters & bound_parameters
        # TODO: confirm that negated predicates work as intended

        name = 'cluster-{}'.format(i)
        parameters = list(sorted(cluster.parameters))
        preconditions = [(assigned_predicate, to_constant(p), p) for p in sorted(existing_parameters)] + \
                        constraints + [order_facts[i]]
        effects = [(assigned_predicate, to_constant(p), p) for p in parameters] + \
                  [order_facts[i+1], Not(order_facts[i])]

        if costs:
            assert len(costs) == 1
            [cost] = costs
        else:
            cost = None
        actions.append(
            make_action(name, parameters, preconditions, effects, cost))
        #actions[-1].dump()
        bound_parameters.update(cluster.parameters)

    predicates = [make_predicate(order_predicate, ['?step'])]  # '?num',
    domain = make_domain(predicates=predicates, actions=actions)
    return domain, goal_expression
示例#7
0
def planning_from_satisfaction(init, constraints):
    clusters = cluster_constraints(constraints)
    order_value_facts = [(ORDER_PREDICATE, 't{}'.format(i))
                         for i in range(len(clusters) + 1)]
    init.append(order_value_facts[0])
    goal_expression = order_value_facts[-1]
    order_facts = list(map(obj_from_value_expression, order_value_facts))
    bound_parameters = set()
    actions = []
    #constants = {}
    for i, cluster in enumerate(clusters):
        objectives = list(map(obj_from_value_expression, cluster.constraints))
        #free_parameters = cluster.parameters - bound_parameters
        existing_parameters = cluster.parameters & bound_parameters
        # TODO: confirm that negated predicates work as intended

        name = 'cluster-{}'.format(i)
        parameters = list(sorted(cluster.parameters))
        preconditions = [(ASSIGNED_PREDICATE, to_constant(p), p) for p in sorted(existing_parameters)] + \
                        get_constraints(objectives) + [order_facts[i]]
        effects = [(ASSIGNED_PREDICATE, to_constant(p), p) for p in parameters] + \
                  [order_facts[i+1], Not(order_facts[i])]

        costs = get_costs(objectives)
        cost = None
        if costs:
            assert len(costs) == 1
            cost = get_args(costs[0])[0]
        actions.append(
            make_action(name, parameters, preconditions, effects, cost))
        #actions[-1].dump()
        bound_parameters.update(cluster.parameters)

    predicates = [make_predicate(ORDER_PREDICATE, ['?x'])]
    domain = make_domain(predicates=predicates, actions=actions)
    return domain, goal_expression
示例#8
0
 def get_certified(self):
     # TODO: cache these results
     expression = self.instance.get_head()
     return [expression if self.value else Not(expression)]
示例#9
0
def fact_from_fd(fd):
    assert (isinstance(fd, pddl.Literal))
    atom = (fd.predicate, ) + tuple(map(obj_from_pddl, fd.args))
    return Not(atom) if fd.negated else atom
示例#10
0
def enforce_single_binding(result, preconditions, effects):
    binding_facts = [(BOUND_PREDICATE, pddl_from_object(out))
                     for out in result.output_objects]
    preconditions.extend(Not(fact) for fact in binding_facts)
    effects.extend(fact for fact in binding_facts)
示例#11
0
 def get_certified(self):
     expression = self.instance.get_head()
     if self.value:
         return [expression]
     return [Not(expression)]
示例#12
0
def add_plan_constraints(constraints,
                         domain,
                         evaluations,
                         goal_exp,
                         internal=False):
    if (constraints is None) or (constraints.skeletons is None):
        return goal_exp
    import pddl
    # TODO: unify this with the constraint ordering
    # TODO: can constrain to use a plan prefix
    prefix = get_internal_prefix(internal)
    assigned_predicate = ASSIGNED_PREDICATE.format(prefix)
    bound_predicate = BOUND_PREDICATE.format(prefix)
    group_predicate = GROUP_PREDICATE.format(prefix)
    order_predicate = ORDER_PREDICATE.format(prefix)
    new_facts = []
    for group in constraints.groups:
        for value in constraints.groups[group]:
            # TODO: could make all constants groups (like an equality group)
            fact = (group_predicate, to_obj(group), to_obj(value))
            new_facts.append(fact)
    new_actions = []
    new_goals = []
    for num, skeleton in enumerate(constraints.skeletons):
        actions, orders = skeleton
        incoming_orders, _ = neighbors_from_orders(orders)
        order_facts = [(order_predicate, to_obj('n{}'.format(num)),
                        to_obj('t{}'.format(step)))
                       for step in range(len(actions))]
        for step, (name, args) in enumerate(actions):
            # TODO: could also just remove the free parameter from the action
            new_action = deepcopy(
                find_unique(lambda a: a.name == name, domain.actions))
            local_from_global = {
                a: p.name
                for a, p in safe_zip(args, new_action.parameters)
                if is_parameter(a)
            }

            ancestors, descendants = get_ancestors(step,
                                                   orders), get_descendants(
                                                       step, orders)
            parallel = set(range(
                len(actions))) - ancestors - descendants - {step}

            parameters = set(filter(is_parameter, args))
            ancestor_parameters = parameters & set(
                filter(is_parameter,
                       (p for idx in ancestors for p in actions[idx][1])))
            #descendant_parameters = parameters & set(filter(is_parameter, (p for idx in descendants for p in actions[idx][1])))
            parallel_parameters = parameters & set(
                filter(is_parameter,
                       (p for idx in parallel for p in actions[idx][1])))

            #bound_preconditions = [Imply(bound, assigned) for bound, assigned in safe_zip(bound_facts, assigned_facts)]
            bound_condition = pddl.Conjunction([
                pddl.Disjunction(
                    map(fd_from_fact, [
                        Not((bound_predicate, to_constant(p))),
                        (assigned_predicate, to_constant(p),
                         local_from_global[p])
                    ])) for p in parallel_parameters
            ])
            existing_preconditions = [(assigned_predicate, to_constant(p),
                                       local_from_global[p])
                                      for p in ancestor_parameters]

            constant_pairs = [(a, p.name)
                              for a, p in safe_zip(args, new_action.parameters)
                              if is_constant(a)]
            group_preconditions = [
                (group_predicate if is_hashable(a) and
                 (a in constraints.groups) else EQ, to_obj(a), p)
                for a, p in constant_pairs
            ]
            order_preconditions = [
                order_facts[idx] for idx in incoming_orders[step]
            ]
            new_preconditions = existing_preconditions + group_preconditions + order_preconditions + [
                Not(order_facts[step])
            ]
            new_action.precondition = pddl.Conjunction([
                new_action.precondition, bound_condition,
                make_preconditions(new_preconditions)
            ]).simplified()

            new_parameters = parameters - ancestors
            bound_facts = [(bound_predicate, to_constant(p))
                           for p in new_parameters]
            assigned_facts = [(assigned_predicate, to_constant(p),
                               local_from_global[p]) for p in new_parameters]
            new_effects = bound_facts + assigned_facts + [order_facts[step]]
            new_action.effects.extend(make_effects(new_effects))
            # TODO: should also negate the effects of all other sequences here

            new_actions.append(new_action)
            #new_action.dump()
        new_goals.append(
            And(*[order_facts[idx] for idx in incoming_orders[GOAL_INDEX]]))

    add_predicate(domain, make_predicate(order_predicate, ['?num', '?step']))
    if constraints.exact:
        domain.actions[:] = []
    domain.actions.extend(new_actions)
    new_goal_exp = And(goal_exp, Or(*new_goals))
    for fact in new_facts:
        add_fact(evaluations, fact, result=INTERNAL_EVALUATION)
    return new_goal_exp
示例#13
0
def add_plan_constraints(constraints,
                         domain,
                         evaluations,
                         goal_exp,
                         internal=False):
    if (constraints is None) or (constraints.skeletons is None):
        return goal_exp
    import pddl
    # TODO: can search over skeletons first and then fall back
    # TODO: unify this with the constraint ordering
    # TODO: can constrain to use a plan prefix
    prefix = '_' if internal else ''
    assigned_predicate = ASSIGNED_PREDICATE.format(prefix)
    group_predicate = GROUP_PREDICATE.format(prefix)
    order_predicate = ORDER_PREDICATE.format(prefix)
    for group in constraints.groups:
        for value in constraints.groups[group]:
            # TODO: could make all constants groups (like an equality group)
            fact = (group_predicate, to_obj(group), to_obj(value))
            add_fact(evaluations, fact, result=INTERNAL_EVALUATION)
    new_actions = []
    new_goals = []
    for num, skeleton in enumerate(constraints.skeletons):
        # TODO: change the prefix for these
        order_facts = [(order_predicate, to_obj('n{}'.format(num)),
                        to_obj('t{}'.format(step)))
                       for step in range(len(skeleton) + 1)]
        add_fact(evaluations, order_facts[0], result=INTERNAL_EVALUATION)
        new_goals.append(order_facts[-1])
        bound_parameters = set()
        for step, (name, args) in enumerate(skeleton):
            # TODO: could also just remove the free parameter from the action
            new_action = deepcopy(
                find_unique(lambda a: a.name == name, domain.actions))
            constant_pairs = [(a, p.name)
                              for a, p in safe_zip(args, new_action.parameters)
                              if not is_parameter(a) and a != WILD]
            skeleton_parameters = list(filter(is_parameter, args))
            existing_parameters = [
                p for p in skeleton_parameters if p in bound_parameters
            ]
            local_from_global = {
                a: p.name
                for a, p in safe_zip(args, new_action.parameters)
                if is_parameter(a)
            }

            group_preconditions = [
                (group_predicate if is_hashable(a) and
                 (a in constraints.groups) else EQ, to_obj(a), p)
                for a, p in constant_pairs
            ]
            new_preconditions = make_assignment_facts(assigned_predicate, local_from_global, existing_parameters) + \
                                group_preconditions + [order_facts[step]]
            new_action.precondition = pddl.Conjunction([
                new_action.precondition,
                make_preconditions(new_preconditions)
            ]).simplified()

            new_effects = make_assignment_facts(assigned_predicate, local_from_global, skeleton_parameters) \
                          + [Not(order_facts[step]), order_facts[step + 1]]
            new_action.effects.extend(make_effects(new_effects))
            # TODO: should also negate the effects of all other sequences here

            new_actions.append(new_action)
            bound_parameters.update(skeleton_parameters)
            #new_action.dump()
    add_predicate(domain, make_predicate(order_predicate, ['?num', '?step']))
    if constraints.exact:
        domain.actions[:] = []
    domain.actions.extend(new_actions)
    new_goal_exp = And(goal_exp, Or(*new_goals))
    return new_goal_exp
示例#14
0
def get_goal(belief,
             init,
             base_threshold=(0.05, 0.05, math.radians(10)),
             arm_threshold=math.radians(10)):
    # TODO: order goals for serialization
    # TODO: make independent of belief and world
    world = belief.world  # One world per state
    task = world.task  # One task per world
    init_bq = belief.base_conf
    init_aq = belief.arm_conf

    carry_aq = world.carry_conf
    goal_literals = [Not(('Unsafe', ))]
    if task.goal_hand_empty:
        goal_literals.append(('HandEmpty', ))
    if task.goal_holding is not None:
        goal_literals.append(('Holding', task.goal_holding))
    goal_literals += [('On', name, surface) for name, surface in task.goal_on.items()] + \
                     [Not(('Pressed', name)) for name in KNOBS] + \
                     [('HasLiquid', cup, liquid) for cup, liquid in task.goal_liquid] + \
                     [('Cooked', name) for name in task.goal_cooked] + \
                     [('Localized', name) for name in task.goal_detected] + \
                     [door_closed_formula(joint_name) for joint_name in task.goal_closed] + \
                     [door_open_formula(joint_name) for joint_name in task.goal_open] + \
                     list(task.goal)

    if not task.movable_base or task.return_init_bq:  # fixed_base?
        goal_bq = world.goal_bq if task.movable_base else init_bq
        init.extend([
            ('BConf', goal_bq),
            ('AConf', goal_bq, carry_aq),
            ('CloseTo', goal_bq, goal_bq),
        ])

        base_difference_fn = get_difference_fn(world.robot, world.base_joints)
        if np.less_equal(
                np.abs(base_difference_fn(init_bq.values, goal_bq.values)),
                base_threshold).all():
            print('Close to goal base configuration')
            init.append(('CloseTo', init_bq, goal_bq))
        goal_literals.append(
            Exists(['?bq'], And(('CloseTo', '?bq', goal_bq),
                                ('AtBConf', '?bq'))))

        goal_aq = task.goal_aq
        if task.return_init_aq:
            goal_aq = init_aq if are_confs_close(
                init_aq, world.goal_aq) else world.goal_aq
        if goal_aq is not None:
            arm_difference_fn = get_difference_fn(world.robot,
                                                  world.arm_joints)
            if np.less_equal(
                    np.abs(arm_difference_fn(init_aq.values, goal_aq.values)),
                    arm_threshold * np.ones(len(world.arm_joints))).all():
                print('Close to goal arm configuration')
                init.append(('CloseTo', init_aq, goal_aq))
            init.extend([
                ('AConf', goal_bq, goal_aq),
                ('CloseTo', goal_aq, goal_aq),
            ])
            goal_literals.append(
                Exists(['?aq'],
                       And(('CloseTo', '?aq', goal_aq), ('AtAConf', '?aq'))))
    return existential_quantification(goal_literals)
示例#15
0
def pddlstream_from_tamp(tamp_problem,
                         use_stream=True,
                         use_optimizer=False,
                         collisions=True):
    initial = tamp_problem.initial
    assert (initial.holding is None)

    domain_pddl = read(get_file_path(__file__, 'domain.pddl'))
    external_paths = []
    if use_stream:
        external_paths.append(get_file_path(__file__, 'stream.pddl'))
    if use_optimizer:
        external_paths.append(get_file_path(
            __file__, 'optimizer1.pddl'))  # optimizer1 | optimizer2
    external_pddl = [read(path) for path in external_paths]

    constant_map = {}
    init = [
        ('CanMove',),
        ('Conf', initial.conf),
        ('AtConf', initial.conf),
        ('HandEmpty',),
        Equal((TOTAL_COST,), 0)] + \
           [('Block', b) for b in initial.block_poses.keys()] + \
           [('Pose', b, p) for b, p in initial.block_poses.items()] + \
           [('AtPose', b, p) for b, p in initial.block_poses.items()] + \
           [('Placeable', b, GROUND_NAME) for b in initial.block_poses.keys()] + \
           [('Placeable', b, r) for b, r in tamp_problem.goal_regions.items()] + \
           [('Region', r) for r in list(tamp_problem.goal_regions.values()) + [GROUND_NAME]]

    goal_literals = [Not(('Unsafe', ))]  # ('HandEmpty',)
    goal_literals += [('In', b, r)
                      for b, r in tamp_problem.goal_regions.items()]
    if tamp_problem.goal_conf is not None:
        goal_literals += [('AtConf', tamp_problem.goal_conf)]
    goal = And(*goal_literals)

    stream_map = {
        's-motion':
        from_fn(plan_motion),
        's-region':
        from_gen_fn(get_pose_gen(tamp_problem.regions)),
        't-region':
        from_test(get_region_test(tamp_problem.regions)),
        's-ik':
        from_fn(inverse_kin_fn),
        #'s-ik': from_gen_fn(unreliable_ik_fn),
        'distance':
        distance_fn,
        't-cfree':
        from_test(
            lambda *args: implies(collisions, not collision_test(*args))),
        'posecollision':
        collision_test,  # Redundant
        'trajcollision':
        lambda *args: False,
    }
    if use_optimizer:
        # To avoid loading gurobi
        stream_map.update({
            'gurobi':
            from_list_fn(
                get_optimize_fn(tamp_problem.regions, collisions=collisions)),
            'rrt':
            from_fn(cfree_motion_fn),
        })
    #stream_map = 'debug'

    return PDDLProblem(domain_pddl, constant_map, external_pddl, stream_map,
                       init, goal)