def test_num_to_bools_operators(self): s = Simplifier(get_env()) su = Substituter(get_env()) a = FluentExp(Fluent("a", IntType())) b = FluentExp(Fluent("b", IntType())) c = FluentExp(Fluent("c", IntType())) d = FluentExp(Fluent("d", IntType())) x = FluentExp(Fluent("x")) y = FluentExp(Fluent("y")) t = Bool(True) f = Bool(False) #[(a+5 > b iff c != d) & x] iff (x xor y) e = Iff(And(x, Iff(GT(Plus(a, 5), b), Not(Equals(c, d)))), Or(And(x, Not(y)), And(Not(x), y))) sub1 = {x: False, y: False, a: 0, b: 5, c: 0, d: 1} s1 = su.substitute(e, sub1) r1 = s.simplify(s1) self.assertEqual(r1, t) sub2 = {x: True, y: False, a: 0, b: 5, c: 0, d: 1} s2 = su.substitute(e, sub2) r2 = s.simplify(s2) self.assertEqual(r2, f) sub3 = {y: False, a: 0, b: 5, c: 0, d: 1} s3 = su.substitute(e, sub3) r3 = s.simplify(s3) self.assertEqual(r3, Not(x)) sub4 = {y: False, a: 1, b: 5, c: 0, d: 1} s4 = su.substitute(e, sub4) r4 = s.simplify(s4) self.assertEqual(r4, t) sub5 = {Not(Equals(c, d)): GT(Plus(a, 5), b), y: False} s5 = su.substitute(e, sub5) r5 = s.simplify(s5) self.assertEqual(r5, t)
def test_nnf_dnf_4(self): n = Nnf(get_env()) dnf = Dnf(get_env()) a = FluentExp(Fluent('a')) b = FluentExp(Fluent('b')) # (a && ( a => b)) Iff (b || ( ((a => b ) && (b => a)) Iff ( a Iff b))) e4 = Iff(And(a, Implies(a, b)), Or(b, Iff(And(Implies(a, b), Implies(b, a)), Iff(a, b)))) nnf4 = n.get_nnf_expression(e4) dnf4 = dnf.get_dnf_expression(e4) subs = {a: True, b: True} self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(nnf4, subs)) self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(dnf4, subs)) subs = {a: True, b: False} self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(nnf4, subs)) self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(dnf4, subs)) subs = {a: False, b: False} self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(nnf4, subs)) self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(dnf4, subs)) subs = {a: False, b: True} self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(nnf4, subs)) self.assertEqual(self._subs_simp(e4, subs), self._subs_simp(dnf4, subs))
def test_or_fluent(self): s = Simplifier(get_env()) su = Substituter(get_env()) x = Fluent('x') y = FluentExp(Fluent('y')) t = Bool(True) f = Bool(False) e1 = Or(x, t) sub = {x: False} s1 = su.substitute(e1, sub) r1 = s.simplify(s1) self.assertEqual(r1, t) self.assertEqual(r1.constant_value(), True) e2 = Or(x, e1) sub = {x: False} s2 = su.substitute(e2, sub) r2 = s.simplify(s2) self.assertEqual(r2, t) self.assertEqual(r2.constant_value(), True) e3 = Or(x, f, f) e4 = Or(e3, f) sub = {x: False} s4_1 = su.substitute(e4, sub) r4_1 = s.simplify(s4_1) self.assertEqual(r4_1, f) sub = {x: True} s4_2 = su.substitute(e4, sub) r4_2 = s.simplify(s4_2) self.assertEqual(r4_2, t) e5 = Or(x, x) sub = {x: False} s5 = su.substitute(e5, sub) r5 = s.simplify(s5) self.assertEqual(r5, f) e6 = Or(Or(x, y), Or(y, x)) sub = {x: False} s6 = su.substitute(e6, sub) r6 = s.simplify(s6) self.assertEqual(r6, y) e7 = Or(Or(x, y), Or(y, Not(x))) sub = {y: False} s7 = su.substitute(e7, sub) r7 = s.simplify(s7) self.assertEqual(r7, t) e8 = Or(Or(x, y), Not(x)) sub = {y: False} s8 = su.substitute(e8, sub) r8 = s.simplify(s8) self.assertEqual(r8, t) sub = {x: False} s9 = su.substitute(e7, sub) r9 = s.simplify(s9) self.assertEqual(r9, t)
def test_nnf_dnf_1(self): n = Nnf(get_env()) dnf = Dnf(get_env()) a = FluentExp(Fluent('a')) b = FluentExp(Fluent('b')) c = FluentExp(Fluent('c')) # !(a => (b && c)) e1 = Not(Implies(a, And(b, c))) nnf1 = n.get_nnf_expression(e1) self.assertIn("(a and ((not b) or (not c)))", str(nnf1)) dnf1 = dnf.get_dnf_expression(e1) self.assertIn("((a and (not b)) or (a and (not c)))", str(dnf1))
def OneshotPlanner( *, name: Optional[str] = None, names: Optional[List[str]] = None, params: Union[Dict[str, str], List[Dict[str, str]]] = None, problem_kind: ProblemKind = ProblemKind(), optimality_guarantee: Optional[Union[ 'up.solvers.solver.OptimalityGuarantee', str]] = None ) -> Optional[Solver]: """ Returns a oneshot planner. There are three ways to call this method: - using 'name' (the name of a specific planner) and 'params' (planner dependent options). e.g. OneshotPlanner(name='tamer', params={'heuristic': 'hadd'}) - using 'names' (list of specific planners name) and 'params' (list of planner dependent options) to get a Parallel solver. e.g. OneshotPlanner(names=['tamer', 'tamer'], params=[{'heuristic': 'hadd'}, {'heuristic': 'hmax'}]) - using 'problem_kind' and 'optimality_guarantee'. e.g. OneshotPlanner(problem_kind=problem.kind, optimality_guarantee=SOLVED_OPTIMALLY) """ return get_env().factory.OneshotPlanner( name=name, names=names, params=params, problem_kind=problem_kind, optimality_guarantee=optimality_guarantee)
def test_all(self): pv = SequentialPlanValidator(env=get_env()) for p in self.problems.values(): if p.problem.kind.has_continuous_time(): continue problem, plan = p.problem, p.plan self.assertTrue(pv.validate(problem, plan))
def __init__(self, env: Environment = None): self._env = get_env(env) self._em = self._env.expression_manager self._tm = self._env.type_manager self._operators: Dict[str, Callable] = { 'and': self._em.And, 'or': self._em.Or, 'not': self._em.Not, 'imply': self._em.Implies, '>=': self._em.GE, '<=': self._em.LE, '>': self._em.GT, '<': self._em.LT, '=': self._em.Equals, '+': self._em.Plus, '-': self._em.Minus, '/': self._em.Div, '*': self._em.Times } grammar = PDDLGrammar() self._pp_domain = grammar.domain self._pp_problem = grammar.problem self._pp_parameters = grammar.parameters self._fve = up.walkers.FreeVarsExtractor() self._totalcost: typing.Optional[up.model.FNode] = None
def test_minus_fluent(self): #minus with fluent s = Simplifier(get_env()) data2 = 3 x = Fluent('x', IntType()) y = Fluent('y', IntType()) fnode2 = Int(data2) x_2 = Minus(x, fnode2) data_list = [1, 5, 6, 2, 3, 4, -3, 5] fnode_of_data_list = x_2 for a in data_list: fnode_of_data_list = Minus(fnode_of_data_list, Int(a)) fnode_simplified = s.simplify(fnode_of_data_list) fnode_of_data_list_expected = x_2 for a in data_list: if a > 0: fnode_of_data_list_expected = Minus( fnode_of_data_list_expected, Int(a)) else: fnode_of_data_list_expected = Plus(fnode_of_data_list_expected, Int(-a)) self.assertEqual(fnode_simplified, fnode_of_data_list_expected) fnode_of_data_list = Int(0) for a in data_list: fnode_of_data_list = Minus(fnode_of_data_list, Int(a)) x_fnode_of_data_list = Minus(x, fnode_of_data_list) fnode_simplified = s.simplify(x_fnode_of_data_list) self.assertEqual(fnode_simplified, Plus(x, Int(23))) e1 = Minus(x, y) r1 = s.simplify(e1) self.assertEqual(r1, e1)
def test_times_constant(self): #simple times s = Simplifier(get_env()) data1 = 5 data2 = 3 fnode1 = Int(data1) fnode2 = Int(data2) fnode1_2 = Times(fnode1, fnode2) result1_2 = s.simplify(fnode1_2) self.assertTrue(result1_2.constant_value() == 15) data_list = [1, 5, 6, 2, 3, 4, -3, 5] fnode_of_data_list = Times(0, *data_list) fnode_simplified = s.simplify(fnode_of_data_list) self.assertTrue(fnode_simplified.is_int_constant()) self.assertEqual(fnode_simplified.constant_value(), 0) data_list = [1, 5, 6, 2, 3, 4, -3, 5] fnode_of_data_list = Times(data_list) fnode_simplified = s.simplify(fnode_of_data_list) self.assertTrue(fnode_simplified.is_int_constant()) self.assertEqual(fnode_simplified.constant_value(), -10800) e1 = Times(Int(5), Minus(-3, Plus(-5, 2))) r1 = s.simplify(e1) self.assertTrue(r1.is_constant()) self.assertTrue(r1.constant_value() == 0) self.assertEqual(r1, Int(0))
def test_div_fluent(self): #div with fluent s = Simplifier(get_env()) data2 = 3 x = Fluent('x', IntType()) fnode2 = Int(data2) x_2 = Div(x, fnode2) data_list = [Fraction(5), Fraction(1, 5)] fnode_of_data_list = Int(1) for a in data_list: fnode_of_data_list = Div(fnode_of_data_list, Real(Fraction(a))) fnode_of_data_list = Div(x_2, fnode_of_data_list) fnode_simplified = s.simplify(fnode_of_data_list) self.assertEqual(fnode_simplified, Div(Div(x, Int(3)), Real(Fraction(1)))) data_list = ['1.0', '0.5', '10', '0.25', '0.125'] fnode_of_data_list = Int(1) for a in data_list: fnode_of_data_list = Div(fnode_of_data_list, Real(Fraction(a))) fnode_of_data_list = Div(fnode_of_data_list, x_2) fnode_simplified = s.simplify(fnode_of_data_list) self.assertEqual(fnode_simplified, Div(Fraction('6.4'), Div(x, Int(3))))
def test_times_fluent(self): #plus with fluent s = Simplifier(get_env()) data2 = 3 x = FluentExp(Fluent('x', IntType())) fnode2 = Int(data2) x_2 = Times(x, fnode2) data_list = [1, 5, 6, 2, 3, 4, -3, 5] fnode_of_data_list = Int(0) for a in data_list: fnode_of_data_list = Times(fnode_of_data_list, Int(a)) fnode_of_data_list = Times(fnode_of_data_list, x_2) fnode_simplified = s.simplify(fnode_of_data_list) self.assertEqual(fnode_simplified, Int(0)) fnode_of_data_list = Int(1) for a in data_list: fnode_of_data_list = Times(fnode_of_data_list, Int(a)) fnode_of_data_list = Times(fnode_of_data_list, x_2) fnode_simplified = s.simplify(fnode_of_data_list) self.assertEqual(fnode_simplified, Times(x, Int(-32400))) e1 = Times(x, Div(1, 5), Int(5)) r1 = s.simplify(e1) self.assertEqual(r1, x)
def test_not(self): s = Simplifier(get_env()) su = Substituter(get_env()) x = Fluent('x') t = Bool(True) f = Bool(False) e1 = Or(x, Not(t)) sub = {x: False} s1 = su.substitute(e1, sub) r1 = s.simplify(s1) self.assertEqual(r1, f) e2 = Not(Or(x, e1)) sub = {x: False} s2 = su.substitute(e2, sub) r2 = s.simplify(s2) self.assertEqual(r2, t)
def test_implies(self): s = Simplifier(get_env()) x = FluentExp(Fluent('x')) y = FluentExp(Fluent('y')) t = Bool(True) f = Bool(False) e1 = Implies(x, y) r1 = s.simplify(e1) self.assertEqual(r1, e1) e2 = Implies(e1, e1) r2 = s.simplify(e2) self.assertEqual(r2, t) e3 = Implies(And(t, y), Or(y, f)) r3 = s.simplify(e3) self.assertEqual(r3, t) e4 = Implies(And(x, y), And(y, x)) r4 = s.simplify(e4) self.assertEqual(r4, e4) e5 = Implies(And(x, y), y) r5 = s.simplify(e5) self.assertEqual(r5, e5) e6 = Implies(And(x, y), t) r6 = s.simplify(e6) self.assertEqual(r6, t) e7 = Implies(And(x, f), Not(f)) r7 = s.simplify(e7) self.assertEqual(r7, t) e8 = Implies(t, x) r8 = s.simplify(e8) self.assertEqual(r8, x) e9 = Implies(x, f) r9 = s.simplify(e9) self.assertEqual(r9, Not(x))
def test_or_fluent(self): s = Simplifier(get_env()) x = Fluent('x') y = Fluent('y') t = Bool(True) f = Bool(False) e1 = Or(x, t) r1 = s.simplify(e1) self.assertEqual(r1, t) self.assertEqual(r1.constant_value(), True) e2 = Or(x, e1) r2 = s.simplify(e2) self.assertEqual(r2, t) self.assertEqual(r2.constant_value(), True) e3 = Or(x, f, f) e4 = Or(e3, f) r4 = s.simplify(e4) self.assertEqual(FluentExp(x), r4) e5 = Or(x, x) r5 = s.simplify(e5) self.assertEqual(r5, FluentExp(x)) e6 = Or(Or(x, y), Or(y, x)) r6 = s.simplify(e6) self.assertEqual(r6, Or(x, y)) e7 = Or(Or(x, y), Or(y, Not(x))) r7 = s.simplify(e7) self.assertEqual(r7, t) e8 = Or(Or(x, y), Not(x)) r8 = s.simplify(e8) self.assertEqual(r8, t)
def __init__(self, name: str, typename: 'up.model.types.Type' = None, _signature: Optional[ Union[OrderedDict[str, 'up.model.types.Type'], List['up.model.parameter.Parameter']]] = None, env: Environment = None, **kwargs: 'up.model.types.Type'): self._env = get_env(env) self._name = name if typename is None: self._typename = self._env.type_manager.BoolType() else: self._typename = typename self._signature: List['up.model.parameter.Parameter'] = [] if _signature is not None: assert len(kwargs) == 0 if isinstance(_signature, OrderedDict): for param_name, param_type in _signature.items(): self._signature.append( up.model.parameter.Parameter(param_name, param_type)) elif isinstance(_signature, List): self._signature = _signature[:] else: raise NotImplementedError else: for param_name, param_type in kwargs.items(): self._signature.append( up.model.parameter.Parameter(param_name, param_type))
def test_and_fluent(self): s = Simplifier(get_env()) x = Fluent('x') y = Fluent('y') t = Bool(True) f = Bool(False) e1 = And(x, f) r1 = s.simplify(e1) self.assertEqual(r1, f) self.assertEqual(r1.constant_value(), False) e2 = And(x, e1) r2 = s.simplify(e2) self.assertEqual(r2, f) self.assertEqual(r2.constant_value(), False) e3 = And(x, t, t) e4 = And(e3, t) r4 = s.simplify(e4) self.assertEqual(FluentExp(x), r4) e5 = And(x, x) r5 = s.simplify(e5) self.assertEqual(r5, FluentExp(x)) e6 = And(And(x, y), And(y, x)) r6 = s.simplify(e6) self.assertEqual(r6, And(x, y)) e7 = And(And(x, y), And(y, Not(x))) r7 = s.simplify(e7) self.assertEqual(r7, f) e8 = And(And(x, y), Not(x)) r8 = s.simplify(e8) self.assertEqual(r8, f)
def __call__(self, test_fun): msg = "no plan validator available for the given problem kind" cond = get_env().factory._get_solver_class('plan_validator', problem_kind=self.kind) is None @unittest.skipIf(cond, msg) @wraps(test_fun) def wrapper(*args, **kwargs): return test_fun(*args, **kwargs) return wrapper
def __call__(self, test_fun): msg = "%s not available" % self.solver cond = self.solver not in get_env().factory.solvers @unittest.skipIf(cond, msg) @wraps(test_fun) def wrapper(*args, **kwargs): return test_fun(*args, **kwargs) return wrapper
def test_nnf_dnf_3(self): n = Nnf(get_env()) dnf = Dnf(get_env()) a = FluentExp(Fluent('a')) b = FluentExp(Fluent('b')) c = FluentExp(Fluent('c')) # (a => b) Iff (a => c) e3 = Iff(Implies(a, b), Implies(a, c)) nnf3 = n.get_nnf_expression(e3) dnf3 = dnf.get_dnf_expression(e3) self.assertIn( "(((not a) or b) and ((not a) or c)) or ((a and (not b)) and (a and (not c)))", str(nnf3)) self.assertIn( "(not a) or ((not a) and c) or (b and (not a)) or (b and c) or (a and (not b) and (not c)", str(dnf3))
def test_implies(self): s = Simplifier(get_env()) su = Substituter(get_env()) x = FluentExp(Fluent('x')) y = FluentExp(Fluent('y')) t = Bool(True) f = Bool(False) e1 = Implies(x, y) sub = {x: False} s1 = su.substitute(e1, sub) r1 = s.simplify(s1) self.assertEqual(r1, t) e3 = Implies(And(t, y), x) sub = {y: x, x: False} s3 = su.substitute(e3, sub) r3 = s.simplify(s3) self.assertEqual(r3, Not(x))
def __call__(self, test_fun): msg = "no oneshot planner available for the given optimality guarantee" cond = get_env().factory._get_solver_class('oneshot_planner', optimality_guarantee=self.optimality_guarantee) is None @unittest.skipIf(cond, msg) @wraps(test_fun) def wrapper(*args, **kwargs): return test_fun(*args, **kwargs) return wrapper
def test_and_fluent(self): s = Simplifier(get_env()) su = Substituter(get_env()) x = Fluent('x') y = FluentExp(Fluent('y')) t = Bool(True) f = Bool(False) e1 = And(x, f) sub = {x: True} s1 = su.substitute(e1, sub) r1 = s.simplify(s1) self.assertEqual(r1, f) self.assertEqual(r1.constant_value(), False) e2 = And(x, e1) sub = {x: True} s2 = su.substitute(e2, sub) r2 = s.simplify(s2) self.assertEqual(r2, f) self.assertEqual(r2.constant_value(), False) e3 = And(x, t, t) e4 = And(e3, t) sub = {x: True} s4 = su.substitute(e4, sub) r4 = s.simplify(s4) self.assertEqual(t, r4) e5 = And(x, x) sub = {x: True} s5 = su.substitute(e5, sub) r5 = s.simplify(s5) self.assertEqual(r5, t) e6 = And(And(x, y), And(y, x)) sub = {x: True} s6_1 = su.substitute(e6, sub) r6_1 = s.simplify(s6_1) self.assertEqual(r6_1, y) sub = {x: True, y: True} s6_2 = su.substitute(e6, sub) r6_2 = s.simplify(s6_2) self.assertEqual(r6_2, t) e7 = And(And(x, y), And(y, Not(x))) sub = {x: True, y: True} s7 = su.substitute(e7, sub) r7 = s.simplify(s7) self.assertEqual(r7, f)
def test_dnf_2(self): dnf = Dnf(get_env()) a = FluentExp(Fluent('a')) b = FluentExp(Fluent('b')) c = FluentExp(Fluent('c')) d = FluentExp(Fluent('d')) # a && (!b || (!c && d)) e2 = And(a, Or(Not(b), And(Not(c), d))) dnf2 = dnf.get_dnf_expression(e2) self.assertIn("((a and (not b)) or (a and (not c) and d))", str(dnf2))
def __init__(self, _name: str, _parameters: 'OrderedDict[str, up.model.types.Type]' = None, _env: Environment = None, **kwargs: 'up.model.types.Type'): self._env = get_env(_env) self._name = _name self._parameters: 'OrderedDict[str, up.model.parameter.Parameter]' = OrderedDict() if _parameters is not None: assert len(kwargs) == 0 for n, t in _parameters.items(): self._parameters[n] = up.model.parameter.Parameter(n, t) else: for n, t in kwargs.items(): self._parameters[n] = up.model.parameter.Parameter(n, t)
def test_iff(self): s = Simplifier(get_env()) su = Substituter(get_env()) x = FluentExp(Fluent('x')) y = FluentExp(Fluent('y')) t = Bool(True) f = Bool(False) e1 = Iff(x, y) sub = {x: False} s1 = su.substitute(e1, sub) r1 = s.simplify(s1) self.assertEqual(r1, Not(y)) e4 = Iff(And(x, y), And(y, x)) sub = {x: False} s4 = su.substitute(e4, sub) r4 = s.simplify(s4) self.assertEqual(r4, t) e5 = Iff(And(x, t), f) sub = {x: False} s5 = su.substitute(e5, sub) r5 = s.simplify(s5) self.assertEqual(r5, t)
def test_substitution(self): s = Substituter(get_env()) xfluent = Fluent('x', IntType()) x = FluentExp(xfluent) subst = {} subst[x] = Int(5) e1 = Plus(x, 1) s1 = s.substitute(e1, subst) self.assertEqual(s1, Plus(5, 1)) #Testing that (a & b) with sbust = {a <- c, (c & b) <- d, (a & b) <- c} is c a = Fluent('a') b = Fluent('b') c = FluentExp(Fluent('c')) d = Fluent('d') subst = {} subst[a] = c subst[And(c, b)] = d subst[And(a, b)] = c e2 = And(a, b) s2 = s.substitute(e2, subst) self.assertEqual(s2, c) with self.assertRaises(UPTypeError): subst = {} subst[a] = c subst[And(c, b)] = d subst[And(a, b)] = Int(5) e3 = And(a, b) s3 = s.substitute(e3, subst) subst = {} subst[a] = c subst[And(c, b)] = d e4 = And(a, b, And(c, b)) s4 = s.substitute(e4, subst) self.assertEqual(s4, And(c, b, d)) subst = {} subst[a] = c subst[c] = d e5 = And(a, c, And(a, c)) s5 = s.substitute(e5, subst) self.assertEqual(s5, And(c, d, And(c, d))) with self.assertRaises(UPTypeError): subst = {} subst[a] = c subst[And(c, b)] = Plus(1, 2) e6 = Int(1) s.substitute(e6, subst)
def test_minus_constant(self): #simple minus s = Simplifier(get_env()) data1 = 5 data2 = 3 fnode1 = Int(data1) fnode2 = Int(data2) fnode1_2 = Minus(fnode1, fnode2) result1_2 = s.simplify(fnode1_2) self.assertEqual(result1_2.constant_value(), 2) data_list = [1, 5, 6, 2, 3, 4, -3, 5] fnode_of_data_list = Int(data_list.pop(0)) for a in data_list: fnode_of_data_list = Minus(fnode_of_data_list, Int(a)) fnode_simplified = s.simplify(fnode_of_data_list) self.assertEqual(fnode_simplified.constant_value(), -21)
def test_or_constant(self): s = Simplifier(get_env()) t = Bool(True) f = Bool(False) e1 = Or(t, f) r1 = s.simplify(e1) self.assertEqual(r1, t) self.assertEqual(r1.constant_value(), True) e2 = Or(t, e1) r2 = s.simplify(e2) self.assertEqual(r2, t) self.assertEqual(r2.constant_value(), True) e3 = Or(f, f) r3 = s.simplify(e3) self.assertTrue(r3.is_constant()) self.assertEqual(r3, f)
def test_and_constant(self): s = Simplifier(get_env()) t = Bool(True) f = Bool(False) e1 = And(t, f) r1 = s.simplify(e1) self.assertEqual(r1, f) self.assertEqual(r1.constant_value(), False) e2 = And(t, e1) r2 = s.simplify(e2) self.assertEqual(r2, f) self.assertEqual(r2.constant_value(), False) e3 = And(t, t) r3 = s.simplify(e3) self.assertTrue(r3.is_constant()) self.assertEqual(r3, t)
def Grounder( *, name: Optional[str] = None, params: Union[Dict[str, str], List[Dict[str, str]]] = None, problem_kind: ProblemKind = ProblemKind() ) -> Optional[Solver]: """ Returns a Grounder. There are three ways to call this method: - using 'name' (the name of a specific grounder) and 'params' (grounder dependent options). e.g. Grounder(name='tamer', params={'opt': 'val'}) - using 'problem_kind' parameter. e.g. Grounder(problem_kind=problem.kind) """ return get_env().factory.Grounder(name=name, params=params, problem_kind=problem_kind)