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!')
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]
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" )