def test_unify_nullary(self): raws = [ Function("afact",[Number(1),String("test")]), Function("nullary1",[]), Function("nullary2",[]), Function("afact",[Number(2),String("test")]), ] class Afact(Predicate): anum=IntegerField() astr=StringField() class Meta: name = "afact" class Nullary1(Predicate): class Meta: name = "nullary1" class Nullary2(Predicate): class Meta: name = "nullary2" af_1=Afact(anum=1,astr="test") af_2=Afact(anum=2,astr="test") u_1=Nullary1() u_2=Nullary2() self.assertEqual(list(unify([Nullary1],raws)),[u_1]) self.assertEqual(list(unify([Nullary2],raws)),[u_2]) self.assertEqual(set(unify([Afact,Nullary1,Nullary2],raws)), set([af_1,af_2,u_1,u_2]))
def test_register_name(self): SF = StringField IF = IntegerField CF = ConstantField n1 = Number(1) n2 = Number(2) n3 = Number(3) n4 = Number(4) s1 = String("ab") s2 = String("cd") s3 = String("abcd") c1 = Function("ab", []) c2 = Function("cd", []) c3 = Function("abcd", []) # Test the register_name as a decorator cb1 = ContextBuilder() @cb1.register_name("addi") # use function annotations def add1(a: IF, b: IF) -> IF: return a + b # external signature self.assertEqual(add1(1, 2), 3) @cb1.register_name("adds", SF, SF, SF) def add2(a, b): return a + b self.assertEqual(add2("ab", "cd"), "abcd") # Non-decorator call - re-using a function but with a different signature cb1.register_name("addc", CF, CF, CF, add1) # Non-decorator call - setting a function with the function annotation cb1.register_name("addi_alt", add1) ctx1 = cb1.make_context() self.assertEqual(ctx1.addi(n1, n2), n3) self.assertEqual(ctx1.addi_alt(n1, n2), n3) self.assertEqual(ctx1.adds(s1, s2), s3) self.assertEqual(ctx1.addc(c1, c2), c3) # Things that should fail with self.assertRaises(TypeError) as ctx: self.assertEqual(ctx1.addc(s1, s2), s3) with self.assertRaises(TypeError) as ctx: self.assertEqual(ctx1.addc(s1, s2), c3) # Fails since add2 has no function annotations with self.assertRaises(TypeError) as ctx: cb1.register_name("addo", add2) # Function name already assigned with self.assertRaises(ValueError) as ctx: cb1.register_name("addi", add1)
def test_unify(self): raws = [ Function("afact",[Number(1),String("test")]), Function("afact",[Number(2),Number(3),String("test")]), Function("afact",[Number(1),Function("fun",[Number(1)])]), Function("bfact",[Number(3),String("test")]) ] class Afact1(Predicate): anum=IntegerField() astr=StringField() class Meta: name = "afact" class Afact2(Predicate): anum1=IntegerField() anum2=IntegerField() astr=StringField() class Meta: name = "afact" class Afact3(Predicate): class Fun(ComplexTerm): fnum=IntegerField() anum=IntegerField() afun=Fun.Field() # afun=ComplexField(Fun) class Meta: name = "afact" class Bfact(Predicate): anum=IntegerField() astr=StringField() af1_1=Afact1(anum=1,astr="test") af2_1=Afact2(anum1=2,anum2=3,astr="test") af3_1=Afact3(anum=1,afun=Afact3.Fun(fnum=1)) bf_1=Bfact(anum=3,astr="test") g1=list(unify([Afact1],raws)) g2=list(unify([Afact2],raws)) g3=list(unify([Afact3],raws)) g4=list(unify([Bfact],raws)) g5=list(unify([Afact1,Bfact],raws)) self.assertEqual([af1_1], g1) self.assertEqual([af2_1], g2) self.assertEqual([af3_1], g3) self.assertEqual([bf_1], g4) self.assertEqual([af1_1,bf_1], g5) # Test the ordered option that returns a list of facts that preserves # the order of the original symbols. g1=unify([Afact1,Afact2,Bfact], raws, ordered=True) self.assertEqual(g1, [af1_1,af2_1,bf_1])
def test_symbolpredicateunifier_with_subfields(self): spu = SymbolPredicateUnifier() class CT(ComplexTerm): a = IntegerField b = StringField(index=True) c = (IntegerField(index=True),ConstantField) @spu.register class P(Predicate): d = CT.Field(index=True) e = CT.Field() expected=set([hashable_path(P.d), hashable_path(P.d.b), hashable_path(P.d.c.arg1), hashable_path(P.e.b), hashable_path(P.e.c.arg1)]) self.assertEqual(spu.predicates, (P,)) self.assertEqual(set([hashable_path(p) for p in spu.indexes]), set(expected)) ct_func=Function("ct",[Number(1),String("aaa"), Function("",[Number(1),Function("const",[])])]) p1=Function("p",[ct_func,ct_func]) fb=spu.unify(symbols=[p1],raise_on_empty=True) self.assertEqual(len(fb),1) self.assertEqual(set([hashable_path(p) for p in fb.indexes]), expected)
def test_string(self): ''' Test strings. ''' s = String("blub") self.assertEqual(s.string, "blub") self.assertEqual(s.type, SymbolType.String)
def test_repr(self): ''' Test representation of symbols. ''' self.assertEqual( repr(Function('test', [Number(10), Infimum, Supremum, String("test")], False)), "Function('test', [Number(10), Infimum, Supremum, String('test')], False)")
def test_unify_catch_exceptions(self): # Define a class that converts strings but makes bad exceptions for any # other input class TmpField(BaseField): def cltopy(raw): if raw.type == SymbolType.String: return raw.string return blah.blah.error1(raw) def pytocl(v): if isinstance(v,str): return String(v) import blah return blah.error2(v) # This is good self.assertEqual(TmpField.cltopy(String("blah")), "blah") self.assertEqual(TmpField.pytocl("blah"), String("blah")) # Some things that should throw an exception with self.assertRaises(AttributeError) as ctx: r=TmpField.cltopy(1) check_errmsg("'int' object has no attribute 'type'",ctx) with self.assertRaises(NameError) as ctx: r=TmpField.cltopy(Number(1)) check_errmsg("name 'blah' is not defined",ctx) with self.assertRaises(ModuleNotFoundError) as ctx: r=TmpField.pytocl(1) check_errmsg("No module named 'blah'",ctx) class F(Predicate): v=TmpField # Ok raw=Function("f",[String("astring")]) unify([F],[raw]) # Bad with self.assertRaises(NameError) as ctx: raw=Function("f",[Number(1)]) unify([F],[raw]) check_errmsg("name 'blah' is not defined",ctx)
def optimization(prg, assignments, constraints): # only want one optimal variable assignment for each combination. change to 0 to see other alternatives prg.configuration.solve.models = 0 # parse the assignments to be groundable assignments = parsed_assignments(assignments) # ground the optimization program prg.ground([("utility_optimization", [])]) # add constraints, the program will have problem with #show utility/1. But this program works only if added after we grounded optimization program. add_dcop_constraints(prg, constraints) # for each combination, find the optimal variable assignment. optimized_results = [] for assignment in assignments: # assign_external the facts to for variable, value in assignment: prg.assign_external(Function("assignment", [String(variable), String(value)]), True) optimal_symbols = [] with prg.solve(yield_=True) as handle: for model in handle: optimal_symbols.append(model.symbols(shown=True)) for variable, value in assignment: # prg.release_external would remove the same assignment from following answer set. prg.assign_external(Function("assignment", [String(variable), String(value)]), False) optimized_results.append(optimal_symbols) return optimized_results
def _get_constraint_parameters(self, location: dict): """ Get the correct parameters for the weak constraint in the conversion. """ idx = ast.SymbolicTerm(location, Number(self.rule_idx)) self.global_variables = ast.Function(location, "", self.global_variables, False) if self.weight == 'alpha': self.weight = ast.SymbolicTerm(location, String('alpha')) constraint_weight = ast.SymbolicTerm(location, Number(1)) priority = Number(1) else: constraint_weight = self.weight priority = Number(0) priority = ast.SymbolicTerm(location, priority) return idx, constraint_weight, priority
def __call__(self, term: Any): ''' Evaluate the given term. Parameters ---------- term The term to evaluate. Returns ------- The evaluated term in form of a symbol. ''' # tuples if term.type == TheoryTermType.Tuple: return Tuple_([self(x) for x in term.arguments]) # functions and arithmetic operations if term.type == TheoryTermType.Function: arguments = [self(x) for x in term.arguments] # binary operations if len(arguments) == 2: return self.evaluate_binary(term.name, *arguments) # unary operations if len(arguments) == 1: return self.evaluate_unary(term.name, *arguments) # functions return Function(term.name, arguments) # constants if term.type == TheoryTermType.Symbol: if term.name.startswith('"') and term.name.endswith('"'): return String(_unquote(term.name[1:-1])) return Function(term.name) # numbers if term.type == TheoryTermType.Number: return Number(term.number) raise RuntimeError("cannot evaluate term")
def test_predicate_instance_raw_term(self): raw1 = Function("func",[Number(1)]) raw2 = Function("bob",[String("no")]) rf1 = RawField() rt1 = Function("tmp", [Number(1), raw1]) rt2 = Function("tmp", [Number(1), raw2]) self.assertTrue(rf1.unifies(raw1)) class Tmp(Predicate): n1 = IntegerField() r1 = RawField() self.assertTrue(Tmp._unify(rt1) is not None) self.assertTrue(Tmp._unify(rt2) is not None) t1 = Tmp(1,Raw(raw1)) t2 = Tmp(1,Raw(raw2)) self.assertEqual(set([f for f in unify([Tmp], [rt1,rt2])]),set([t1,t2])) self.assertEqual(t1.r1.symbol, raw1) self.assertEqual(t2.r1.symbol, raw2)
def test_signature_with_tuples(self): DateField = self.DateField # Some complicated signatures sig1 = TypeCastSignature((IntegerField, DateField), (IntegerField, DateField)) sig2 = TypeCastSignature(DateField, [(IntegerField, DateField)]) @sig1.wrap_function def test_sig1(pair): return (pair[0], pair[1]) @sig2.wrap_function def test_sig2(dt): return [(1, dt), (2, dt)] s_raw = String("20180101") t1_raw = Function("", [Number(1), s_raw]) t2_raw = Function("", [Number(2), s_raw]) # result = test_sig1(t1_raw) self.assertEqual(test_sig1(t1_raw), t1_raw) self.assertEqual(test_sig2(s_raw), [t1_raw, t2_raw])
def test_symbolpredicateunifier_symbols(self): class Afact(Predicate): num1=IntegerField() num2=IntegerField() str1=StringField() class Bfact(Predicate): num1=IntegerField() str1=StringField() class Cfact(Predicate): num1=IntegerField() af1 = Afact(1,10,"bbb") af2 = Afact(2,20,"aaa") af3 = Afact(3,20,"aaa") bf1 = Bfact(1,"aaa") bf2 = Bfact(2,"bbb") cf1 = Cfact(1) raws = [ Function("afact",[Number(1), Number(10), String("bbb")]), Function("afact",[Number(2), Number(20), String("aaa")]), Function("afact",[Number(3), Number(20), String("aaa")]), Function("bfact",[Number(1),String("aaa")]), Function("bfact",[Number(2),String("bbb")]), Function("cfact",[Number(1)]) ] spu = SymbolPredicateUnifier(predicates=[Afact,Bfact,Cfact]) # Test the different ways that facts can be added fb = spu.unify(symbols=raws) self.assertFalse(fb._delayed_init) self.assertEqual(set(fb.predicates), set([Afact,Bfact,Cfact])) s_af_all = fb.query(Afact) self.assertEqual(set(s_af_all.all()), set([af1,af2,af3])) fb = spu.unify(symbols=raws, delayed_init=True) self.assertTrue(fb._delayed_init) self.assertEqual(set(fb.predicates), set([Afact,Bfact,Cfact])) s_af_all = fb.query(Afact) self.assertEqual(set(s_af_all.all()), set([af1,af2,af3])) fb = FactBase() fb.add([af1,af2,af3]) #### self.assertEqual(fb.add([af1,af2,af3]),3) s_af_all = fb.query(Afact) self.assertEqual(set(s_af_all.all()), set([af1,af2,af3])) fb = FactBase() fb.add(af1) fb.add(af2) fb.add(af3) #### self.assertEqual(fb.add(af1),1) #### self.assertEqual(fb.add(af2),1) #### self.assertEqual(fb.add(af3),1) s_af_all = fb.query(Afact) self.assertEqual(set(s_af_all.all()), set([af1,af2,af3])) # Test that adding symbols can handle symbols that don't unify fb = spu.unify(symbols=raws) s_af_all = fb.query(Afact) self.assertEqual(set(s_af_all.all()), set([af1,af2,af3])) return # Test the specification of indexes class MyFactBase3(FactBase): predicates = [Afact, Bfact] spu = SymbolPredicateUnifier(predicates=[Afact,Bfact,Cfact], indexes=[Afact.num1, Bfact.num1]) fb = spu.unify(symbols=raws) s = fb.query(Afact).where(Afact.num1 == 1) self.assertEqual(s.get_unique(), af1) s = fb.query(Bfact).where(Bfact.num1 == 1) self.assertEqual(s.get_unique(), bf1)
def pytocl(v): if isinstance(v,str): return String(v) import blah return blah.error2(v)
def test_signature(self): DateField = self.DateField DowField = self.DowField EDate = self.EDate sig1 = TypeCastSignature(DateField) # returns a single date sig2 = TypeCastSignature([DateField]) # returns a list of dates sig3 = TypeCastSignature( DateField, DowField) # takes a date and returns the day or week sig4 = TypeCastSignature( EDate.Field, EDate.Field) # takes an EDate and returns an EDate # Some bad declarations with self.assertRaises(TypeError) as ctx: sig5 = TypeCastSignature(int) with self.assertRaises(TypeError) as ctx: sig5 = TypeCastSignature(DateField, int) with self.assertRaises(TypeError) as ctx: sig5 = TypeCastSignature(DateField, [int]) with self.assertRaises(TypeError) as ctx: sig5 = TypeCastSignature(DateField, [DateField, DateField]) date1 = datetime.date(2018, 1, 1) date2 = datetime.date(2019, 2, 2) edate1 = EDate(idx=1, date=date1) edate2 = EDate(idx=2, date=date2) # Test simple output and list output def getdate1(): return date1 def getdates(): return [date1, date2] cl_getdate1 = sig1.wrap_function(getdate1) cl_getdates = sig2.wrap_function(getdates) self.assertEqual(cl_getdate1(), String("20180101")) self.assertEqual( cl_getdates(), [String("20180101"), String("20190202")]) # Use decoractor mode @sig3.wrap_function def getdow(dt): return dt result = getdow(String("20180101")) self.assertEqual(result, Function("monday", [])) # Test a ComplexTerm input and output @sig4.wrap_function def getedate(indate): return indate self.assertEqual(getedate(edate1.raw), edate1.raw) self.assertEqual(getedate(edate2.raw), edate2.raw) # Now test the method wrapper class Tmp(object): def __init__(self, x, y): self._x = x self._y = y def get_pair(self): return [self._x, self._y] cl_get_pair = sig2.wrap_method(get_pair) t = Tmp(date1, date2) self.assertEqual( t.cl_get_pair(), [String("20180101"), String("20190202")])
def test_make_function_asp_callable(self): DateField = self.DateField DowField = self.DowField EDate = self.EDate date1 = datetime.date(2018, 1, 1) date2 = datetime.date(2019, 2, 2) edate1 = EDate(idx=1, date=date1) edate2 = EDate(idx=2, date=date2) def getdate1(): return date1 def getdates(): return [date1, date2] # Test wrapper as a normal function and specifying a signature cl_getdate1 = make_function_asp_callable(DateField, getdate1) self.assertEqual(cl_getdate1(), String("20180101")) cl_getdates = make_function_asp_callable([DateField], getdates) self.assertEqual( cl_getdates(), [String("20180101"), String("20190202")]) # Test wrapper as a decorator and specifying a signature @make_function_asp_callable(DateField) def getdate1(): return date1 self.assertEqual(getdate1(), String("20180101")) @make_function_asp_callable([DateField]) def getdates(): return [date1, date2] self.assertEqual(getdates(), [String("20180101"), String("20190202")]) @make_function_asp_callable def getdates2(x: DateField, y: EDate.Field) -> [DateField]: '''GETDATES2''' return [date1, date2] self.assertEqual( getdates2(String("20180101"), edate1.raw), [String("20180101"), String("20190202")]) self.assertEqual(getdates2.__doc__, '''GETDATES2''') with self.assertRaises(TypeError) as ctx: @make_function_asp_callable def getdates3(x, y): return [date1, date2] with self.assertRaises(TypeError) as ctx: @make_function_asp_callable def getdates4(x: DateField, y: DateField): return [date1, date2] # Now test the method wrapper class Tmp(object): def __init__(self, x, y): self._x = x self._y = y def get_pair(self): return [self._x, self._y] cl_get_pair = make_method_asp_callable([DateField], get_pair) @make_method_asp_callable def get_pair2(self) -> [DateField]: return [self._x, self._y] t = Tmp(date1, date2) self.assertEqual( t.cl_get_pair(), [String("20180101"), String("20190202")]) self.assertEqual( t.get_pair2(), [String("20180101"), String("20190202")])