示例#1
0
def convert_tarski_formula(
        env: Environment, fluents: Dict[str, 'unified_planning.model.Fluent'],
        objects: Dict[str, 'unified_planning.model.Object'],
        action_parameters: Dict[str, 'unified_planning.model.Parameter'],
        types: Dict[str, Optional['unified_planning.model.Type']],
        formula: Union[Formula, Term]) -> 'unified_planning.model.FNode':
    """Converts a tarski formula in a unified_planning expression."""
    em = env.expression_manager
    if is_and(formula):
        children = [
            convert_tarski_formula(env, fluents, objects, action_parameters,
                                   types, f) for f in formula.subformulas
        ]
        return em.And(*children)
    elif is_or(formula):
        children = [
            convert_tarski_formula(env, fluents, objects, action_parameters,
                                   types, f) for f in formula.subformulas
        ]
        return em.Or(*children)
    elif is_neg(formula):
        assert len(formula.subformulas) == 1
        return em.Not(
            convert_tarski_formula(env, fluents, objects, action_parameters,
                                   types, formula.subformulas[0]))
    elif is_atom(formula) or isinstance(formula, CompoundTerm):
        children = [
            convert_tarski_formula(env, fluents, objects, action_parameters,
                                   types, f) for f in formula.subterms
        ]
        if is_atom(formula):
            symbol = formula.predicate.symbol
        else:
            symbol = formula.symbol.name
        if symbol == BuiltinPredicateSymbol.EQ:
            assert len(children) == 2
            return em.Equals(children[0], children[1])
        elif symbol == BuiltinPredicateSymbol.NE:
            assert len(children) == 2
            return em.Not(em.Equals(children[0], children[1]))
        elif symbol == BuiltinPredicateSymbol.LT:
            assert len(children) == 2
            return em.LT(children[0], children[1])
        elif symbol == BuiltinPredicateSymbol.LE:
            assert len(children) == 2
            return em.LE(children[0], children[1])
        elif symbol == BuiltinPredicateSymbol.GT:
            assert len(children) == 2
            return em.GT(children[0], children[1])
        elif symbol == BuiltinPredicateSymbol.GE:
            assert len(children) == 2
            return em.GE(children[0], children[1])
        elif symbol == BuiltinFunctionSymbol.ADD:
            assert len(children) == 2
            return em.Plus(children[0], children[1])
        elif symbol == BuiltinFunctionSymbol.SUB:
            assert len(children) == 2
            return em.Minus(children[0], children[1])
        elif symbol == BuiltinFunctionSymbol.MUL:
            assert len(children) == 2
            return em.Times(children[0], children[1])
        elif symbol == BuiltinFunctionSymbol.DIV:
            assert len(children) == 2
            return em.Div(children[0], children[1])
        elif symbol in fluents:
            return fluents[symbol](*children)
        else:
            raise UPProblemDefinitionError(symbol + ' not supported!')
    elif isinstance(formula, Constant):
        if formula.sort.name == 'number':
            return em.Real(Fraction(float(formula.name)))
        elif isinstance(formula.sort, tarski.syntax.Interval):
            if formula.sort.language.is_subtype(\
                formula.sort, formula.sort.language.Integer)\
                or formula.sort.language.is_subtype(\
                    formula.sort, formula.sort.language.Natural):
                return em.Int(int(formula.name))
            elif formula.sort.language.is_subtype(\
                formula.sort, formula.sort.language.Real):
                return em.Real(Fraction(float(formula.name)))
            else:
                raise NotImplementedError
        elif formula.name in objects:
            return em.ObjectExp(objects[formula.name])
        else:
            raise UPProblemDefinitionError(formula + ' not supported!')
    elif isinstance(formula, Variable):
        if formula.symbol in action_parameters:
            return em.ParameterExp(action_parameters[formula.symbol])
        else:
            return em.VariableExp(unified_planning.model.Variable(formula.symbol, \
                cast(unified_planning.model.Type, _convert_type_and_update_dict(formula.sort, types, env.type_manager, formula.sort.language))))
    elif isinstance(formula, QuantifiedFormula):
        expression = convert_tarski_formula(env, fluents, objects,
                                            action_parameters, types,
                                            formula.formula)
        variables = [
            unified_planning.model.Variable(
                v.symbol,
                cast(
                    unified_planning.model.Type,
                    _convert_type_and_update_dict(v.sort, types,
                                                  env.type_manager,
                                                  v.sort.language)))
            for v in formula.variables
        ]
        if formula.quantifier == Quantifier.Exists:
            return em.Exists(expression, *variables)
        elif formula.quantifier == Quantifier.Forall:
            return em.Forall(expression, *variables)
        else:
            raise NotImplementedError
    elif isinstance(formula, Tautology):
        return em.TRUE()
    elif isinstance(formula, Contradiction):
        return em.FALSE()
    else:
        raise UPProblemDefinitionError(str(formula) + ' not supported!')
示例#2
0
    def generate_goal_predicate_constraints(self, predicate):
        # We generate gates for positive and negative clauses separately,
        pos_final_gate = 0
        neg_final_gate = 0
        zero_arity_predicate = 0

        list_obj_instances_pos = []
        list_obj_instances_neg = []
        if (fr.is_atom(self.tfunc.parsed_instance.parsed_problem.goal)):
            list_subformulas = [self.tfunc.parsed_instance.parsed_problem.goal]
        else:
            list_subformulas = self.tfunc.parsed_instance.parsed_problem.goal.subformulas
            assert (self.tfunc.parsed_instance.parsed_problem.goal.connective
                    == fr.Connective.And)
        for atom in list_subformulas:
            # If it is negative atom, then we need to consider as
            # compund formula:
            if (fr.is_neg(atom)):
                # Asserting negation connective:
                assert (atom.connective == fr.Connective.Not)
                # Asserting single atom:
                assert (len(atom.subformulas) == 1)
                cur_atom = atom.subformulas[0]
            else:
                # If not negative, we do not change:
                cur_atom = atom
            if (cur_atom.predicate.name == predicate):
                # If it a zero arity predicate, then either positive or negative must
                # be present so returning directly if found:
                if (len(cur_atom.subterms) == 0):
                    # again checking if positive or negative:
                    if (fr.is_neg(atom)):
                        zero_arity_predicate = -1
                    else:
                        zero_arity_predicate = 1
                    # We do not look further:
                    break
                # Gates for one proposition:
                single_instance_gates = []
                # We generate and gates for each parameter:
                for i in range(len(cur_atom.subterms)):
                    subterm = cur_atom.subterms[i]
                    cur_variables = self.forall_variables_list[i]
                    # Finding object index:
                    obj_index = self.tfunc.probleminfo.object_names.index(
                        subterm.name)
                    gate_variables = self.tfunc.generate_binary_format(
                        cur_variables, obj_index)
                    self.gates_generator.and_gate(gate_variables)
                    single_instance_gates.append(
                        self.gates_generator.output_gate)
                # We only generate of some instantiation occurs:
                if (len(single_instance_gates) != 0):
                    self.gates_generator.and_gate(single_instance_gates)
                    # Appending to the right list:
                    if (fr.is_neg(atom)):
                        list_obj_instances_neg.append(
                            self.gates_generator.output_gate)
                    else:
                        list_obj_instances_pos.append(
                            self.gates_generator.output_gate)

        if (len(list_obj_instances_pos) != 0):
            # Finally an or gate for all the pos instances:
            self.encoding.append(['# Or gate for pos instances:'])
            self.gates_generator.or_gate(list_obj_instances_pos)
            pos_final_gate = self.gates_generator.output_gate
        if (len(list_obj_instances_neg) != 0):
            # Finally an or gates for all the neg instances:
            self.encoding.append(['# Or gate for neg instances:'])
            self.gates_generator.or_gate(list_obj_instances_neg)
            neg_final_gate = self.gates_generator.output_gate
        return [pos_final_gate, neg_final_gate, zero_arity_predicate]
示例#3
0
    def generate_only_nonstatic_predicate_constraints(self):

        self.predicate_constraints = []

        # TODO: also remove static predicates
        # For each normal predicates, we add constraints from each action,
        # WARNING: generating constraints, errors possible,
        # TODO: add rigorous testing for several domains:
        for predicate in self.lang.predicates:
            # Handling =, != symbols by converting them to strings:
            single_predicate_constraints = pc(str(predicate.name))
            for action_name in self.valid_actions:
                action = self.parsed_problem.get_action(action_name)
                # If single condition, then not a compound formula
                # so handling both conditions:
                if (fr.is_atom(action.precondition)):
                    preconditions_list = [action.precondition]
                elif (isinstance(action.precondition, fr.Tautology)):
                    preconditions_list = []
                else:
                    assert (
                        action.precondition.connective == fr.Connective.And)
                    preconditions_list = action.precondition.subformulas
                # Adding preconditons to constraints:
                for precondition in preconditions_list:
                    # If it is negative atom, then we need to consider as
                    # compund formula:
                    if (fr.is_neg(precondition)):
                        # Asserting negation connective:
                        assert (precondition.connective == fr.Connective.Not)
                        # Asserting single precondition:
                        assert (len(precondition.subformulas) == 1)
                        cur_predicate = precondition.subformulas[0]
                        if (cur_predicate.predicate.name == predicate.name):
                            single_predicate_constraints.add_negpre_constraint(
                                action_name,
                                self.get_parameter_symbols(cur_predicate))
                    else:
                        if (precondition.predicate.name == predicate.name):
                            single_predicate_constraints.add_pospre_constraint(
                                action_name,
                                self.get_parameter_symbols(precondition))
                # Adding effects to constraints:
                for effect in action.effects:
                    if (isinstance(effect, fs.AddEffect)):
                        if (effect.atom.predicate.name == predicate.name):
                            single_predicate_constraints.add_poseff_constraint(
                                action_name,
                                self.get_parameter_symbols(effect.atom))
                    elif (isinstance(effect, fs.DelEffect)):
                        if (effect.atom.predicate.name == predicate.name):
                            single_predicate_constraints.add_negeff_constraint(
                                action_name,
                                self.get_parameter_symbols(effect.atom))
                    else:
                        # Must not be reachable yet:
                        assert (True)
                        print("TODO: handle conditional effects")
                        #print(effect, effect.atom.predicate)
            self.predicate_constraints.append(single_predicate_constraints)

        if (self.args.debug >= 1):
            print(
                "#------------------------------------------------------------------------\n"
            )
            print("Predicate constraints: ")
            for single_predicate_constraints in self.predicate_constraints:
                print(single_predicate_constraints)
            print(
                "#------------------------------------------------------------------------\n"
            )