def answerQuestion(peer_name, net, user_password): policy_filename = 'entities/' + peer_name + '/datalog_policy.data' data_filename = 'entities/' + peer_name + '/data.data' queryString = net.recv(); queryList = queryString.split(network_protocol.SEPARATOR) print(queryList) trusted_peer_dict = getTrustedPeers(peer_name) for other_peer, trusted_with in trusted_peer_dict.items(): data = getDataFromTrustedPeer(peer_name, other_peer, user_password) pruned_data = prune(data, trusted_with) add_facts(pruned_data) # Add our own data if(fileIO.fileExists(data_filename)): add_facts(fileIO.readFile(data_filename)) pyDatalog.load(fileIO.readFile(policy_filename)) print("Asking question: " + queryList[0]) query_result = pyDatalog.ask(queryList[0]); print('Query result:',query_result) if(query_result != None): net.send(queryList[1]) else: net.send(queryList[2])
def assertDefaultPolicy(self,direction): if not self.assertedDefaultPolicy: last_clause = self.clauses[-1] if len(last_clause.matchers) == 0: for a in last_clause.actions: pyDatalog.load("+(default%sPolicy(%s,%s,%s))" % (direction,self.name,a.getActionTuple()[0],a.getActionTuple()[1])) self.assertedDefaultPolicy = True
def load(self, console): """Loads the clauses from the file""" start = time.time() pyDatalog.load(self.data) if console: console.print(self.included_files, "Finished ", time.time() - start, " s")
def fillComplexRules(parent_child, child_parent, all_relations, relations): rules = "" #Originated for relation in parent_child: if relations[relation]: rules += 'originated(X, Xi, Y, Yi) <= ' + relation + '(X, Xi, Y, Yi )\n' for relation in child_parent: if relations[relation]: if relation == "etymology": rules += 'originated(X, Xi, Y, Yi) <= etymological_origin_of(Y, Yi, X, Xi)\n' elif relation == "is_derived_from": rules += 'originated(X, Xi, Y, Yi) <= has_derived_form(Y, Yi, X, Xi)\n' else: rules += 'originated(X, Xi, Y, Yi) <= ' + relation + '(Y, Yi, X, Xi)\n' #Listing for relation in all_relations: if relations[relation]: if relation == "etymology": rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & etymological_origin_of(X, Xi, Y, Yi)\n' rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & etymological_origin_of(Y, Yi, X, Xi)\n' elif relation == "is_derived_from": rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & has_derived_form(X, Xi, Y, Yi)\n' rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & has_derived_form(Y, Yi, X, Xi)\n' else: rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & ' + relation + '(X, Xi, Y, Yi)\n' rules += 'listing(Xi, Y, Yi) <= ~listing(Xi, Y, Yi) & ' + relation + '(Y, Yi, X, Xi)\n' pyDatalog.load(rules)
def load_logic(): pyDatalog.load(""" mother(X, Y) <= (parent(X, Y) & gender(X, 'Female')) father(X, Y) <= (parent(X, Y) & gender(X, 'Male')) married(X,Y) <= married(Y, X) husband(X,Y) <= married(X, Y) & gender(X, 'Male') wife(X,Y) <= husband(Y, X) child(Y, X) <= parent(X, Y) parent(X,Y) <= child(Y,X) decendent(X, Y) <= ancestor(Y, X) sibling(X,Y) <= (father(Z, X) & father(Z, Y) & ~(X==Y)) & (mother(W, X) & mother(W, Y) & ~(X==Y)) cousin(X, Y) <= parent(Z, X) & parent(W,Y) & sibling(Z, W) aunt(X,Y) <= parent(Z, Y) & sibling(Z, X) & gender(X, 'Female') aunt(X,Y) <= uncle(Z, Y) & married(Z, X) uncle(X,Y) <= parent(Z, Y) & sibling(Z, X) & gender(X, 'Male') uncle(X,Y) <= aunt(Z, Y) & married(Z, X) ancestor(X, Y) <= (parent(W,Y) & (X==W)) ancestor(X, Y) <= (parent(W,Y) & ancestor(X, W)) brother(X,Y) <= sibling(X,Y) & gender(X, 'Male') sister(X, Y) <= sibling(X,Y) & gender(X, 'Female') inbred(X) <= (father(Y, X) & buendia_blood(Y, True)) &(mother(W, X) & buendia_blood(W, True)) bastard(X) <= father(W,X) & mother(Y, X) & ~married(W, Y) buendia_blood(X, True) <= parent(Y, X) & buendia_blood(Y, True) buendia(X, True) <= buendia_blood(X, True) buendia(X, True) <= married(X, Y) & buendia_blood(Y, True) son(X, Y) <= child(X, Y) & gender(X, 'Male') daughter(X, Y) <= child(X, Y) & gender(X, 'Female') """)
def __init__(self): print('Base de conocimientos') self.conocimiento=Logic(True) pyDatalog.load(""" + usar_computadora('experto','si') + usar_computadora('inexperto','no') es_experto(Y) <= usar_computadora(Y,Z) & resp_experto(Z) # Es médico + terminologia('medico','si') + pacientes('medico','si') + recetar('medico','si') # No es médico + terminologia('persona','no') + pacientes('persona','no') + recetar('persona','no') es_medico(X) <= terminologia(X,A) & pacientes(X,A) & recetar(X,A) & resp_medico(A) tipo_usuario(X,Y) <= es_medico(X) & es_experto(Y) """)
def materialize(facts, clauses, parser): logger.info('Asserting facts ..') for f in facts: # Each fact is asserted using the index of the subject, predicate and object for avoiding syntax issues s_idx = parser.entity_to_index[f.argument_names[0]] p_idx = parser.predicate_to_index[f.predicate_name] o_idx = parser.entity_to_index[f.argument_names[1]] # Asserting p(S, P, O) pyDatalog.assert_fact('p', s_idx, p_idx, o_idx) rules_str = '\n'.join( [clause_to_str(clause, parser) for clause in clauses]) pyDatalog.load(rules_str) # Asking for all P(s, p, o) triples which hold true in the Knowledge Graph logger.info('Querying triples ..') _ans = pyDatalog.ask('p(S, P, O)') index_to_predicate = { idx: p for p, idx in parser.predicate_to_index.items() } index_to_entity = {idx: e for e, idx in parser.entity_to_index.items()} # Generating a list of inferred facts by replacing each entity and predicate index with their corresponding symbols inferred_facts = [ Fact(index_to_predicate[p], [index_to_entity[s], index_to_entity[o]]) for (s, p, o) in sorted(_ans.answers) ] return inferred_facts
def loadFacts(fileName): """ Convenience function to open a fact file and load it into the LogKB. """ facts = open(fileName) pyDatalog.load(facts.read()) facts.close()
def _(): # the function name is ignored pyDatalog.load(mc) #pyDatalog.load(""" #+ (factorial[1]==1) #(factorial[N] == F) <= (N > 1) & (F == N*factorial[N-1]) #""") print(pyDatalog.ask('factorial[4]==F'))
def __init__(self, rulesPath='../user.rules'): Logic() with open(rulesPath, 'r') as f: rules = "\n".join(f.readlines()) load(rules) print "Rules for the user loaded" print rules
def setup(instanceFile): pyDatalog.load(open(instanceFile,"r").read()) #Rules for the Architectural Style pyDatalog.load(open("architectureStyle.py","r").read()) #Rules for Vulnerabilities (Architectural Style) pyDatalog.load(open("vulnerabilityStyle.py","r").read()) #Rules for Functionalities pyDatalog.load(open("functionalStyle.py","r").read()) #Make sure every component has every plausible vulnerability pyDatalog.load(open("applyAllVulnerabilities.py","r").read())
def assert_error(code, message='^$'): _error = False try: pyDatalog.load(code) except Exception as e: e_message = e.message if hasattr(e, 'message') else e.args[0] # python 2 and 3 if not re.match(message, e_message): print(e_message) _error = True assert _error
def load(self, console): """Loads the clauses from the file""" start = time.time() try: pyDatalog.load(self.data) if console: console.print(self.included_files, "Finished ", time.time() - start, " s") except BaseException as exception: print(exception)
def test_sudoku(self): from pyDatalog import pyDatalog from examples.RLP import sudoku_example from reloop.languages.rlp.logkb import PyDatalogLogKb for u in range(1, 10): pyDatalog.assert_fact('num', u) for u in range(1, 4): pyDatalog.assert_fact('boxind', u) pyDatalog.assert_fact('initial', 1, 1, 5) pyDatalog.assert_fact('initial', 2, 1, 6) pyDatalog.assert_fact('initial', 4, 1, 8) pyDatalog.assert_fact('initial', 5, 1, 4) pyDatalog.assert_fact('initial', 6, 1, 7) pyDatalog.assert_fact('initial', 1, 2, 3) pyDatalog.assert_fact('initial', 3, 2, 9) pyDatalog.assert_fact('initial', 7, 2, 6) pyDatalog.assert_fact('initial', 3, 3, 8) pyDatalog.assert_fact('initial', 2, 4, 1) pyDatalog.assert_fact('initial', 5, 4, 8) pyDatalog.assert_fact('initial', 8, 4, 4) pyDatalog.assert_fact('initial', 1, 5, 7) pyDatalog.assert_fact('initial', 2, 5, 9) pyDatalog.assert_fact('initial', 4, 5, 6) pyDatalog.assert_fact('initial', 6, 5, 2) pyDatalog.assert_fact('initial', 8, 5, 1) pyDatalog.assert_fact('initial', 9, 5, 8) pyDatalog.assert_fact('initial', 2, 6, 5) pyDatalog.assert_fact('initial', 5, 6, 3) pyDatalog.assert_fact('initial', 8, 6, 9) pyDatalog.assert_fact('initial', 7, 7, 2) pyDatalog.assert_fact('initial', 3, 8, 6) pyDatalog.assert_fact('initial', 7, 8, 8) pyDatalog.assert_fact('initial', 9, 8, 7) pyDatalog.assert_fact('initial', 4, 9, 3) pyDatalog.assert_fact('initial', 5, 9, 1) pyDatalog.assert_fact('initial', 6, 9, 6) pyDatalog.assert_fact('initial', 8, 9, 5) pyDatalog.load(""" box(I, J, U, V) <= boxind(U) & boxind(V) & num(I) & num(J) & (I > (U-1)*3) & (I <= U*3) & (J > (V-1)*3) & (J <= V*3) """) logkb = PyDatalogLogKb() grounder = BlockGrounder(logkb) # Note: CVXOPT needs to be compiled with glpk support. See the CVXOPT documentation. solver = CvxoptSolver(solver_solver='glpk') model = sudoku_example.sudoku(grounder, solver) self.assertEqual(model, 0, "ERROR : Sudoku couldn't be solved")
def determineResidualUtilityOnceTest(rD,query="",debug=True): rMax = addRisksToLogic(rD) maxUtility = sumAllUtilities() #rMax = 4 for c,p in rD.items(): s = "probCapability[" + str(c) + "] = " + str(p) pyDatalog.load(s) #This needs to change if query == "": query = "attackPaths(SourceService,TargetService,P,E,AttackerMoves,TotalC)" #query = "worstCasePath[\"3\"] == Y" #query = "worstCasePath[TotalC] == Y" #query = "worstCasePathCombo[X,Combo] == Y" #query = "worstCasePathCombo[" + str(3) + ",[businessWorkstations]" + "] == Y" print("Query: " + query) #query = "worstCasePathSpecific[X,SourceService]==Y" utilitiesByAttackerCapabilityAnswers = pyDatalog.ask(query) if utilitiesByAttackerCapabilityAnswers != None: utilitiesByAttackerCapability = utilitiesByAttackerCapabilityAnswers.answers estimatedValue = 0 if debug: print("Query calculated.") if utilitiesByAttackerCapabilityAnswers != None: if debug: print("Query Answers:") #print("Utilities compromised by attacker capability:") #pprint.pprint(utilitiesByAttackerCapability) if len(utilitiesByAttackerCapability) > 0: #print(sorted(utilitiesByAttackerCapability,key=itemgetter(0))) pprint.pprint(sorted(utilitiesByAttackerCapability,key=itemgetter(0))) else: print("No answers") #print("Number of items: " + str(len(utilitiesByAttackerCapability))) #Undo highlight later #estimatedValue = sum(map(itemgetter(1),utilitiesByAttackerCapability)) #for capability in range(rMax+1): #query2 = "worstCasePath[" + str(capability) + "] == X" #wCPsAnswers = pyDatalog.ask(query2) #if wCPsAnswers != None: #wCPs = wCPsAnswers.answers #print "************" #print("Worst case paths by attacker capability " + str(capability) + ": ") #pprint.pprint(str(wCPs)) #Undo highlight later #estimatedValue = maxUtility - estimatedValue #if debug: # print("Single Scenario Expected Value: " + str(estimatedValue)) return estimatedValue
def alimentarBD(): load(""" hijo2(P,H,R) <= padre(X,I,X2,H) & (I==P) hermano(X, Y, H) <= padre(Z, X) & padre (Z,Y) & (X!=Y) hijo(X, Y, H) <= padre(Z,Y) & (X==Z) tio(T, S, H) <= padre(P, S) & hermano(P, T, A) & (P!=T) primo(X,Y,R) <= padre(Q,X) & padre(Z,Y) & (Q!=Y) & hermano(Q,Z,R) primoGrado(X,Y,H) <= padre(P,X) & padre(A,Y) & hermano(A,P,H) primoGrado(X,Y,R) <= padre(P,X) & padre(A,Y) & hermano(P, A, Q) &primoGrado(A,P,H) """)
def runsource(self, source, filename='console', symbol='single'): pySource = """ pyDatalog.load(''' %s ''') """ % source try: code.InteractiveConsole.runsource(self, pySource, filename, symbol) except Exception as e: print(e)
def ask(self, query_symbols, logical_query, coeff_expr=None): """ Builds a pyDataLog program from the logical_query and loads it. Then executes the query for the query_symbols. :param query_symbols: The symbols to be queried. :type query_symbols: list(SubSymbol) :param logical_query: :type: :return: """ helper_len = 0 tmp = None if not query_symbols: return None if coeff_expr is None: helper_len = len(query_symbols) helper_predicate = 'helper(' + ','.join( [str(v) for v in query_symbols]) + ')' tmp = helper_predicate + " <= " + self.transform_query( logical_query) else: helper_len = len(query_symbols) + 1 syms = OrderedSet(query_symbols) syms.add('COEFF_EXPR') helper_predicate = 'helper(' + ','.join([str(v) for v in syms]) + ')' index_query = self.transform_query(logical_query) coeff_query = "(COEFF_EXPR == " + str(coeff_expr) + ")" if index_query is None: tmp = helper_predicate + " <= " + coeff_query else: tmp = helper_predicate + " <= " + " & ".join( [index_query, coeff_query]) log.debug("pyDatalog query: " + tmp) pyDatalog.load(tmp) answer = pyDatalog.ask(helper_predicate) pyEngine.Pred.reset_clauses(pyEngine.Pred("helper", helper_len)) if answer is None: return [] return self.transform_answer(answer.answers)
def addRisksToLogic(rD): riskStr = "" maxR = 0 totalProb = float(0) #print(rD.items()) for cap, prob in list(rD.items()): #pyDatalog.assert_fact(pC(cap,prob)) #MaxR? #probCapability[cap] = prob #print("probCapability[" + str(cap) + "] = " + str(prob) + "\n") riskStr += "probCapability[" + str(cap) + "] = " + str(prob) + "\n" if cap > maxR: maxR = cap totalProb += prob #print("MaxR=" + str(maxR) + "\n") riskStr += "MaxR=" + str(maxR) + "\n" #if totalProb != 1.00: # print("FAIL: Probabilities add to " + str(totalProb)) #else: #print("OK: Probabilities add to 1.00") pyDatalog.load(riskStr) return maxR
def eval_datalog(data, rule): """ Evaluation using pyDatalog. :param data: a list of tuple string :param rule: a rule node :return: a list of resulting tuple string """ assert isinstance(data, list) assert isinstance(rule, RuleNode) def extract_query_predicate(rule): # print(rule) return QUERY_PRED.match(rule).group(1) # def db2str(tuples): # return "\n".join(["+%s(%s,%s)" % (p, s, o) for (s, p, o) in tuples]) def result2tuplestring(result): # print(rule) # query_pred = extract_query_predicate(rule.left) for (s, o) in result: yield (s, rule.left, o) pyDatalog.clear() # loguru.logger.debug('Size of loaded data: %d' % len(data)) for (s, p, o) in data: pyDatalog.assert_fact(p, s, o) pyDatalog.load(str(rule)) result = pyDatalog.ask(rule.left + '(X, Y)') if not result: loguru.logger.debug("Empty evaluation") return [] # if rule.left == config.query_relation_name: # pyDatalog.ask(config.query_relation_name + "(" + config.subject + ", Y)") return list(result2tuplestring(result.answers))
def ask(self, query_symbols, logical_query, coeff_expr=None): """ Builds a pyDataLog program from the logical_query and loads it. Then executes the query for the query_symbols. :param query_symbols: The symbols to be queried. :type query_symbols: list(SubSymbol) :param logical_query: :type: :return: """ helper_len = 0 tmp = None if not query_symbols: return None if coeff_expr is None: helper_len = len(query_symbols) helper_predicate = 'helper(' + ','.join([str(v) for v in query_symbols]) + ')' tmp = helper_predicate + " <= " + self.transform_query(logical_query) else: helper_len = len(query_symbols) + 1 syms = OrderedSet(query_symbols) syms.add('COEFF_EXPR') helper_predicate = 'helper(' + ','.join([str(v) for v in syms]) + ')' index_query = self.transform_query(logical_query) coeff_query = "(COEFF_EXPR == " + str(coeff_expr) + ")" if index_query is None: tmp = helper_predicate + " <= " + coeff_query else: tmp = helper_predicate + " <= " + " & ".join([index_query, coeff_query]) log.debug("pyDatalog query: " + tmp) pyDatalog.load(tmp) answer = pyDatalog.ask(helper_predicate) pyEngine.Pred.reset_clauses(pyEngine.Pred("helper", helper_len)) if answer is None: return [] return self.transform_answer(answer.answers)
def fillComplexRules(parent_child, child_parent, all_relations, relations): rules = "" for relation in all_relations: if relations[relation]: rules += 'palabras(X,I) <= ~palabras(X,I) & ' + relation + '(X,I,A,B)\n' rules += 'palabras(X,I) <= ~palabras(X,I) & ' + relation + '(A,B,X,I)\n' rules += 'igualesEntreIdiomas(I1,I2,X) <= palabras(X,I1) & palabras(X,I2)\n' rules += 'porcentaje(X, Y, Z) <= (Z == X / Y*100)\n' for relation in parent_child: if relations[relation]: rules += 'aporte(I1,I2,Y) <= ' + relation + '(_,I1,Y,I2) & ~(I2 == I1)\n' for relation in child_parent: if relations[relation]: if relation == "etymology": rules += 'aporte(I1,I2,Y) <= etymological_origin_of(Y,I2, _,I1) & ~(I2 == I1)\n' elif relation == "is_derived_from": rules += 'aporte(I1,I2,Y) <= has_derived_form(Y,I2, _,I1) & ~(I2 == I1)\n' else: rules += 'aporte(I1,I2,Y) <= ' + relation + '(Y,I2, _,I1) & ~(I2 == I1)\n' pyDatalog.load(rules) return
def determineResidualUtilityHelper(rD,maxUtility,debug=True): rMax = addRisksToLogic(rD) #rMax = 4 for c,p in rD.items(): s = "probCapability[" + str(c) + "] = " + str(p) pyDatalog.load(s) query = "weightedWorstCasePath[X]==Y" utilitiesByAttackerCapabilityAnswers = pyDatalog.ask(query) if utilitiesByAttackerCapabilityAnswers != None: utilitiesByAttackerCapability = utilitiesByAttackerCapabilityAnswers.answers estimatedValue = 0 if debug: print("Attacks calculated.") if utilitiesByAttackerCapabilityAnswers != None: if debug: print("Utilities compromised by attacker capability:") #pprint.pprint(utilitiesByAttackerCapability) if len(utilitiesByAttackerCapability) > 0: pprint.pprint(sorted(utilitiesByAttackerCapability,key=itemgetter(0))) else: print("None") #print("Number of items: " + str(len(utilitiesByAttackerCapability))) estimatedValue = sum(map(itemgetter(1),utilitiesByAttackerCapability)) #for capability in range(rMax+1): #query2 = "worstCasePath[" + str(capability) + "] == X" #wCPsAnswers = pyDatalog.ask(query2) #if wCPsAnswers != None: #wCPs = wCPsAnswers.answers #print "************" #print("Worst case paths by attacker capability " + str(capability) + ": ") #pprint.pprint(str(wCPs)) estimatedValue = maxUtility - estimatedValue if debug: print("Single Scenario Expected Value: " + str(estimatedValue)) return estimatedValue
def runDatalog(facts, rules, predicates): """виконує логічне виведення в pyDatalog. Повертає список тріплетів. facts - список Datalog-фактів, rules - список Datalog-правил, predicates - список предикатів, для яких будуть шукатись факти""" #if not predicates: # predicates={p for s,p,o in facts}|{r.split('(')[0] for r in rules} from pyDatalog.pyDatalog import assert_fact, load, ask, clear code = '\n'.join(facts) + '\n' + '\n'.join(rules) # факти і правила load(code) allFacts = set() for pred in predicates: # try: res = ask('%s(X,Y)' % pred).answers # except AttributeError: #Predicate without definition # continue for subj, obj in res: allFacts.add((subj.encode('utf-8'), pred.encode('utf-8'), obj.encode('utf-8'))) print subj, pred, obj clear() return allFacts
def test(): # test of expressions pyDatalog.load(""" + p(a) # p is a proposition """) assert pyDatalog.ask('p(a)') == set([('a',)]) pyDatalog.assert_fact('p', 'a', 'b') assert pyDatalog.ask('p(a, "b")') == set([('a', 'b')]) pyDatalog.retract_fact('p', 'a', 'b') assert pyDatalog.ask('p(a, "b")') == None """unary facts """ @pyDatalog.program() def unary(): +z() assert ask(z()) == set([()]) + p(a) # check that unary queries work assert ask(p(a)) == set([('a',)]) assert ask(p(X)) == set([('a',)]) assert ask(p(Y)) == set([('a',)]) assert ask(p(_X)) == set([('a',)]) assert ask(p(b)) == None assert ask(p(a) & p(b)) == None + p(b) assert ask(p(X), _fast=True) == set([('a',), ('b',)]) + p(b) # facts are unique assert ask(p(X)) == set([('a',), ('b',)]) - p(b) # retract a unary fact assert ask(p(X)) == set([('a',)]) - p(a) assert ask(p(X)) == None + p(a) # strings and integers + p('c') assert ask(p(c)) == set([('c',)]) + p(1) assert ask(p(1)) == set([(1,)]) + n(None) assert ask(n(X)) == set([(None,)]) assert ask(n(None)) == set([(None,)]) # spaces and uppercase in strings + farmer('Moshe dayan') + farmer('omar') assert ask(farmer(X)) == set([('Moshe dayan',), ('omar',)]) # execute queries in a python program moshe_is_a_farmer = pyDatalog.ask("farmer('Moshe dayan')") assert moshe_is_a_farmer == set([('Moshe dayan',)]) """ binary facts """ @pyDatalog.program() def binary(): + q(a, b) assert ask(q(a, b)) == set([('a', 'b')]) assert ask(q(X, b)) == set([('a', 'b')]) assert ask(q(a, Y)) == set([('a', 'b')]) assert ask(q(a, c)) == None assert ask(q(X, Y)) == set([('a', 'b')]) + q(a,c) assert ask(q(a, Y)) == set([('a', 'b'), ('a', 'c')]) - q(a,c) assert ask(q(a, Y)) == set([('a', 'b')]) assert ask(q(X, X)) == None +q(a, a) assert ask(q(X, X)) == set([('a', 'a')]) -q(a, a) """ (in)equality """ @pyDatalog.program() def equality(): assert ask(X==1) == set([(1,)]) assert ask(X==Y) == None assert ask(X==Y+1) == None assert ask((X==1) & (Y==1) & (X==Y)) == set([(1,1)]) assert ask((X==1) & (Y==2) & (X==Y-1)) == set([(1,2)]) #assert ask((X==1) & (Y==2) & (X+2==Y+1)) == set([(1,2)]) assert ask((X==2) & (Y==X/2)) == set([(2,1)]) assert ask((X==2) & (Y==X//2)) == set([(2,1)]) assert ask((X==1) & (Y==1+X)) == set([(1,2)]) assert ask((X==1) & (Y==1-X)) == set([(1,0)]) assert ask((X==1) & (Y==2*X)) == set([(1,2)]) assert ask((X==2) & (Y==2/X)) == set([(2,1)]) assert ask((X==2) & (Y==2//X)) == set([(2,1)]) """ Conjunctive queries """ @pyDatalog.program() def conjuctive(): assert ask(q(X, Y) & p(X)) == set([('a', 'b')]) assert ask(p(X) & p(a)) == set([('a',),('c',),(1,)]) assert ask(p(X) & p(Y) & (X==Y)) == set([('a', 'a'), ('c', 'c'), (1, 1)]) assert ask(p(X) & p(Y) & (X==Y) & (Y==a)) == set([('a', 'a')]) assert ask(q(X, Y)) == set([('a', 'b')]) assert ask(q(X, Y) & p(X)) == set([('a', 'b')]) @pyDatalog.program() def equality2(): assert ask((X==1) & (X<X+1)) == set([(1,)]) assert ask((X==1) & (Y==X)) == set([(1,1)]) assert ask((X==1) & (Y==X+1)) == set([(1,2)]) assert ask((X==1) & (Y==X+1) & (X<Y)) == set([(1,2)]) assert ask((X==1) & (X<1)) == None assert ask((X==1) & (X<=1)) == set([(1,)]) assert ask((X==1) & (X>1)) == None assert ask((X==1) & (X>=1)) == set([(1,)]) # assert ask(X==(1,2)) == set([((1,2), (1,2))]) assert ask(X in (1,)) == set([(1,)]) assert ask((X==1) & (X not in (2,))) == set([(1,)]) assert ask((X==1) & ~(X in (2,))) == set([(1,)]) assert ask((X==1) & (X not in (1,))) == None assert ask((X==1) & ~(X in (1,))) == None @pyDatalog.program() def equality3(): # equality (must be between parenthesis): s(X) <= (X == a) assert ask(s(X)) == set([('a',)]) s(X) <= (X == 1) assert ask(s(X)) == set([(1,), ('a',)]) s(X, Y) <= p(X) & (X == Y) assert ask(s(a, a)) == set([('a', 'a')]) assert ask(s(a, b)) == None assert ask(s(X,a)) == set([('a', 'a')]) assert ask(s(X, Y)) == set([('a', 'a'),('c', 'c'),(1, 1)]) assert pyDatalog.ask('p(a)') == set([('a',)]) """ clauses """ @pyDatalog.program() def clauses(): p2(X) <= p(X) assert ask(p2(a)) == set([('a',)]) p2(X) <= p(X) r(X, Y) <= p(X) & p(Y) assert ask(r(a, a)) == set([('a', 'a')]) assert ask(r(a, c)) == set([('a', 'c')]) r(X, b) <= p(X) assert ask(r(a, b)) == set([('a', 'b')]) - (r(X, b) <= p(X)) assert ask(r(a, b)) == None # TODO more tests # integer variable for i in range(10): + successor(i+1, i) assert ask(successor(2, 1)) == set([(2, 1)]) # built-in assert abs(-3)==3 assert math.sin(3)==math.sin(3) """ in """ pyDatalog.assert_fact('is_list', (1,2)) @pyDatalog.program() def _in(): assert ((X==1) & (X in (1,2))) == [(1,)] _in(X) <= (X in [1,2]) assert ask(_in(1)) == set([(1,)]) assert ask(_in(9)) == None assert ask(_in(X)) == set([(1,), (2,)]) _in2(X) <= is_list(Y) & (X in Y) assert ask(_in2(X)) == set([(1,), (2,)]) assert ask((Y==(1,2)) & (X==1) & (X in Y)) == set([((1, 2), 1)]) assert ask((Y==(1,2)) & (X==1) & (X in Y+(3,))) == set([((1, 2), 1)]) """ recursion """ @pyDatalog.program() def recursion(): + even(0) even(N) <= successor(N, N1) & odd(N1) odd(N) <= ~ even(N) assert ask(even(0)) == set([(0,)]) assert ask(even(X)) == set([(4,), (10,), (6,), (0,), (2,), (8,)]) assert ask(even(10)) == set([(10,)]) assert ask(odd(1)) == set([(1,)]) assert ask(odd(5)) == set([(5,)]) assert ask(even(5)) == None """ recursion with expressions """ # reset the engine pyDatalog.clear() @pyDatalog.program() def recursive_expression(): predecessor(X,Y) <= (X==Y-1) assert ask(predecessor(X,11)) == set([(10, 11)]) p(X,Z) <= (Y==Z-1) & (X==Y-1) assert ask(p(X,11)) == set([(9, 11)]) # odd and even + even(0) even(N) <= (N > 0) & odd(N-1) assert ask(even(0)) == set([(0,)]) odd(N) <= (N > 0) & ~ even(N) assert ask(even(0)) == set([(0,)]) assert ask(odd(1)) == set([(1,)]) assert ask(odd(5)) == set([(5,)]) assert ask(even(5)) == None assert ask((X==3) & odd(X+2)) == set([(3,)]) # Factorial pyDatalog.clear() @pyDatalog.program() def factorial(): # (factorial[N] == F) <= (N < 1) & (F == -factorial[-N]) # + (factorial[1]==1) # (factorial[N] == F) <= (N > 1) & (F == N*factorial[N-1]) # assert ask(factorial[1] == F) == set([(1, 1)]) # assert ask(factorial[4] == F) == set([(4, 24)]) # assert ask(factorial[-4] == F) == set([(-4, -24)]) pass # Fibonacci pyDatalog.clear() @pyDatalog.program() def fibonacci(): (fibonacci[N] == F) <= (N == 0) & (F==0) (fibonacci[N] == F) <= (N == 1) & (F==1) (fibonacci[N] == F) <= (N > 1) & (F == fibonacci[N-1]+fibonacci[N-2]) assert ask(fibonacci[1] == F) == set([(1, 1)]) assert ask(fibonacci[4] == F) == set([(4, 3)]) assert ask(fibonacci[18] == F) == set([(18, 2584)]) # string manipulation @pyDatalog.program() def _lambda(): split(X, Y,Z) <= (X == Y+'-'+Z) assert ask(split(X, 'a', 'b')) == set([('a-b', 'a', 'b')]) split(X, Y,Z) <= (Y == (lambda X: X.split('-')[0])) & (Z == (lambda X: X.split('-')[1])) assert ask(split('a-b', Y, Z)) == set([('a-b', 'a', 'b')]) assert ask(split(X, 'a', 'b')) == set([('a-b', 'a', 'b')]) (two[X]==Z) <= (Z==X+(lambda X: X)) assert ask(two['A']==Y) == set([('A','AA')]) """ negation """ @pyDatalog.program() def _negation(): +p(a, b) assert ask(~p(X, b)) == None assert ask(~p(X, c)) == set([('X', 'c')]) pyDatalog.load(""" + even(0) even(N) <= (N > 0) & (N1==N-1) & odd(N1) odd(N) <= (N2==N+2) & ~ even(N) & (N2>0) """) assert pyDatalog.ask('~ odd(7)', _fast=True) == None assert pyDatalog.ask('~ odd(2)', _fast=True) == set([(2,)]) assert pyDatalog.ask('odd(3)', _fast=True) == set([(3,)]) assert pyDatalog.ask('odd(3)' ) == set([(3,)]) assert pyDatalog.ask('odd(5)', _fast=True) == set([(5,)]) assert pyDatalog.ask('odd(5)' ) == set([(5,)]) assert pyDatalog.ask('even(5)', _fast=True) == None assert pyDatalog.ask('even(5)' ) == None """ functions """ pyDatalog.clear() @pyDatalog.program() def function(): + (f[a]==b) assert ask(f[X]==Y) == set([('a', 'b')]) assert ask(f[X]==b) == set([('a', 'b')]) #TODO remove 'b' from result assert ask(f[a]==X) == set([('a', 'b')]) assert ask(f[a]==b) == set([('a', 'b')]) + (f[a]==c) assert ask(f[a]==X) == set([('a', 'c')]) + (f[a]==a) assert ask(f[f[a]]==X) == set([('a',)]) assert ask(f[X]==f[a]) == set([('a',)]) assert ask(f[X]==f[a]+'') == set([('a',)]) - (f[a]==a) assert ask(f[f[a]]==X) == None + (f[a]==None) assert (ask(f[a]==X)) == set([('a',None)]) + (f[a]==(1,2)) assert (ask(f[a]==X)) == set([('a',(1,2))]) assert (ask(f[X]==(1,2))) == set([('a',(1,2))]) + (f[a]==c) + (f2[a,x]==b) assert ask(f2[a,x]==b) == set([('a', 'x', 'b')]) + (f2[a,x]==c) assert ask(f2[a,x]==X) == set([('a', 'x', 'c')]) g[X] = f[X]+f[X] assert(ask(g[a]==X)) == set([('a', 'cc')]) h(X,Y) <= (f[X]==Y) assert (ask(h(X,'c'))) == set([('a', 'c')]) assert (ask(h(X,Y))) == set([('a', 'c')]) @pyDatalog.program() def function_comparison(): assert ask(f[X]==Y) == set([('a', 'c')]) assert ask(f[a]<'d') == set([('c',)]) assert ask(f[a]>'a') == set([('c',)]) assert ask(f[a]>='c') == set([('c',)]) assert ask(f[a]>'c') == None assert ask(f[a]<='c') == set([('c',)]) assert ask(f[a]>'c') == None assert ask(f[a] in ['c',]) == set([('c',)]) assert ask((f[X]=='c') & (f[Y]==f[X])) == set([('a', 'a')]) assert ask((f[X]=='c') & (f[Y]==f[X]+'')) == set([('a', 'a')]) assert ask((f[X]=='c') & (f[Y]==(lambda X : 'c'))) == set([('a', 'a')]) assert ask(f[X]==Y+'') == None assert ask((Y=='c') &(f[X]==Y+'')) == set([('c', 'a')]) assert ask((Y=='c') &(f[X]<=Y+'')) == set([('c', 'a')]) assert ask((Y=='c') &(f[X]<Y+'')) == None assert ask((Y=='c') &(f[X]<'d'+Y+'')) == set([('c', 'a')]) assert ask((Y==('a','c')) & (f[X] in Y)) == set([(('a', 'c'), 'a')]) assert ask((Y==('a','c')) & (f[X] in (Y+('z',)))) == set([(('a', 'c'), 'a')]) assert ask(f[X]==f[X]+'') == set([('a',)]) @pyDatalog.program() def function_negation(): assert not(ask(~(f[a]<'d'))) assert not(ask(~(f[X]<'d'))) assert ask(~(f[a] in('d',))) """ aggregates """ pyDatalog.clear() @pyDatalog.program() def sum(): + p(a, c, 1) + p(b, b, 4) + p(a, b, 1) assert(sum(1,2)) == 3 (a_sum[X] == sum(Y, key=Z)) <= p(X, Z, Y) assert ask(a_sum[X]==Y) == set([('a', 2), ('b', 4)]) assert ask(a_sum[a]==X) == set([('a', 2)]) assert ask(a_sum[a]==2) == set([('a', 2)]) assert ask(a_sum[X]==4) == set([('b', 4)]) assert ask(a_sum[c]==X) == None assert ask((a_sum[X]==2) & (p(X, Z, Y))) == set([('a', 'c', 1), ('a', 'b', 1)]) (a_sum2[X] == sum(Y, for_each=X)) <= p(X, Z, Y) assert ask(a_sum2[a]==X) == set([('a', 1)]) (a_sum3[X] == sum(Y, key=(X,Z))) <= p(X, Z, Y) assert ask(a_sum3[X]==Y) == set([('a', 2), ('b', 4)]) assert ask(a_sum3[a]==X) == set([('a', 2)]) @pyDatalog.program() def len(): assert(len((1,2))) == 2 (a_len[X] == len(Z)) <= p(X, Z, Y) assert ask(a_len[X]==Y) == set([('a', 2), ('b', 1)]) assert ask(a_len[a]==X) == set([('a', 2)]) assert ask(a_len[X]==1) == set([('b', 1)]) assert ask(a_len[X]==5) == None (a_lenY[X] == len(Y)) <= p(X, Z, Y) assert ask(a_lenY[a]==X) == set([('a', 1)]) assert ask(a_lenY[c]==X) == None (a_len2[X,Y] == len(Z)) <= p(X, Y, Z) assert ask(a_len2[a,b]==X) == set([('a', 'b', 1)]) assert ask(a_len2[a,X]==Y) == set([('a', 'b', 1), ('a', 'c', 1)]) + q(a, c, 1) + q(a, b, 2) + q(b, b, 4) @pyDatalog.program() def concat(): (a_concat[X] == concat(Y, key=Z, sep='+')) <= q(X, Y, Z) assert ask(a_concat[X]==Y) == set([('b', 'b'), ('a', 'c+b')]) assert ask(a_concat[a]=='c+b') == set([('a', 'c+b')]) assert ask(a_concat[a]==X) == set([('a', 'c+b')]) assert ask(a_concat[X]==b) == set([('b', 'b')]) (a_concat2[X] == concat(Y, order_by=(Z,), sep='+')) <= q(X, Y, Z) assert ask(a_concat2[a]==X) == set([('a', 'c+b')]) (a_concat3[X] == concat(Y, key=(-Z,), sep='-')) <= q(X, Y, Z) assert ask(a_concat3[a]==X) == set([('a', 'b-c')]) @pyDatalog.program() def min(): assert min(1,2) == 1 (a_min[X] == min(Y, key=Z)) <= q(X, Y, Z) assert ask(a_min[X]==Y) == set([('b', 'b'), ('a', 'c')]) assert ask(a_min[a]=='c') == set([('a', 'c')]) assert ask(a_min[a]==X) == set([('a', 'c')]) assert ask(a_min[X]=='b') == set([('b', 'b')]) (a_minD[X] == min(Y, order_by=-Z)) <= q(X, Y, Z) assert ask(a_minD[a]==X) == set([('a', 'b')]) (a_min2[X, Y] == min(Z, key=(X,Y))) <= q(X, Y, Z) assert ask(a_min2[Y, b]==X) == set([('a', 'b', 2),('b', 'b', 4)]) assert ask(a_min2[Y, Y]==X) == set([('b', 'b', 4)]), "a_min2" (a_min3[Y] == min(Z, key=(-X,Z))) <= q(X, Y, Z) assert ask(a_min3[b]==Y) == set([('b', 4)]), "a_min3" @pyDatalog.program() def max(): assert max(1,2) == 2 (a_max[X] == max(Y, key=-Z)) <= q(X, Y, Z) assert ask(a_max[a]==X) == set([('a', 'c')]) (a_maxD[X] == max(Y, order_by=Z)) <= q(X, Y, Z) assert ask(a_maxD[a]==X) == set([('a', 'b')]) @pyDatalog.program() def rank(): (a_rank1[Z] == rank(for_each=Z, order_by=Z)) <= q(X, Y, Z) assert ask(a_rank1[X]==Y) == set([(1, 0), (2, 0), (4, 0)]) assert ask(a_rank1[X]==0) == set([(1, 0), (2, 0), (4, 0)]) assert ask(a_rank1[1]==X) == set([(1, 0)]) assert ask(a_rank1[1]==0) == set([(1, 0)]) assert ask(a_rank1[1]==1) == None # rank (a_rank[X,Y] == rank(for_each=(X,Y2), order_by=Z2)) <= q(X, Y, Z) & q(X,Y2,Z2) assert ask(a_rank[X,Y]==Z) == set([('a', 'b', 1), ('a', 'c', 0), ('b', 'b', 0)]) assert ask(a_rank[a,b]==1) == set([('a', 'b', 1)]) assert ask(a_rank[a,b]==Y) == set([('a', 'b', 1)]) assert ask(a_rank[a,X]==0) == set([('a', 'c', 0)]) assert ask(a_rank[a,X]==Y) == set([('a', 'b', 1), ('a', 'c', 0)]) assert ask(a_rank[X,Y]==1) == set([('a', 'b', 1)]) assert ask(a_rank[a,y]==Y) == None # reversed (b_rank[X,Y] == rank(for_each=(X,Y2), order_by=-Z2)) <= q(X, Y, Z) & q(X,Y2,Z2) assert ask(b_rank[X,Y]==Z) == set([('a', 'b', 0), ('a', 'c', 1), ('b', 'b', 0)]) assert ask(b_rank[a,b]==0) == set([('a', 'b', 0)]) assert ask(b_rank[a,b]==Y) == set([('a', 'b', 0)]) assert ask(b_rank[a,X]==1) == set([('a', 'c', 1)]) assert ask(b_rank[a,X]==Y) == set([('a', 'b', 0), ('a', 'c', 1)]) assert ask(b_rank[X,Y]==0) == set([('a', 'b', 0), ('b', 'b', 0)]) assert ask(b_rank[a,y]==Y) == None @pyDatalog.program() def running_sum(): # running_sum (a_run_sum[X,Y] == running_sum(Z2, for_each=(X,Y2), order_by=Z2)) <= q(X, Y, Z) & q(X,Y2,Z2) assert ask(a_run_sum[X,Y]==Z) == set([('a', 'b', 3), ('a', 'c', 1), ('b', 'b', 4)]) assert ask(a_run_sum[a,b]==3) == set([('a', 'b', 3)]) assert ask(a_run_sum[a,b]==Y) == set([('a', 'b', 3)]) assert ask(a_run_sum[a,X]==1) == set([('a', 'c', 1)]) assert ask(a_run_sum[a,X]==Y) == set([('a', 'b', 3), ('a', 'c', 1)]) assert ask(a_run_sum[X,Y]==4) == set([('b', 'b', 4)]) assert ask(a_run_sum[a,y]==Y) == None (b_run_sum[X,Y] == running_sum(Z2, for_each=(X,Y2), order_by=-Z2)) <= q(X, Y, Z) & q(X,Y2,Z2) assert ask(b_run_sum[X,Y]==Z) == set([('a', 'b', 2), ('a', 'c', 3), ('b', 'b', 4)]) assert ask(b_run_sum[a,b]==2) == set([('a', 'b', 2)]) assert ask(b_run_sum[a,b]==Y) == set([('a', 'b', 2)]) assert ask(b_run_sum[a,X]==3) == set([('a', 'c', 3)]) assert ask(b_run_sum[a,X]==Y) == set([('a', 'b', 2), ('a', 'c', 3)]) assert ask(b_run_sum[X,Y]==4) == set([('b', 'b', 4)]) assert ask(b_run_sum[a,y]==Y) == None """ simple in-line queries """ X = pyDatalog.Variable() assert ((X==1) >= X) == 1 assert ((X==1) & (X!=2) >= X) == 1 assert set(X._in((1,2))) == set([(1,),(2,)]) assert ((X==1) & (X._in ((1,2)))) == [(1,)] """ interface with python classes """ class A(pyDatalog.Mixin): def __init__(self, b): super(A, self).__init__() self.b = b def __repr__(self): return self.b @pyDatalog.program() # indicates that the following method contains pyDatalog clauses def _(): (A.c[X]==N) <= (A.b[X]==N) (A.len[X]==len(N)) <= (A.b[X]==N) @classmethod def _pyD_x1(cls, X): if X.is_const() and X.id.b == 'za': yield (X.id,) else: for X in pyDatalog.metaMixin.__refs__[cls]: if X.b == 'za': yield (X,) a = A('a') b = A('b') assert a.c == 'a' X, Y = pyDatalog.variables(2) assert (A.c[X]=='a') == [(a,)] assert (A.c[X]=='a')[0] == (a,) assert list(X.data) == [a] assert X.v() == a assert ((A.c[a]==X) >= X) == 'a' assert ((A.c[a]==X) & (A.c[a]==X) >= X) == 'a' assert ((A.c[a]==X) & (A.c[b]==X) >= X) == None (A.c[X]=='b') & (A.b[X]=='a') assert list(X.data) == [] (A.c[X]=='a') & (A.b[X]=='a') assert list(X.data) == [a] result = (A.c[X]=='a') & (A.b[X]=='a') assert result == [(a,)] assert (A.c[a] == 'a') == [()] assert (A.b[a] == 'a') == [()] assert (A.c[a]=='a') & (A.b[a]=='a') == [()] assert (A.b[a]=='f') == [] assert ((A.c[a]=='a') & (A.b[a]=='f')) == [] """ filters on python classes """ assert (A.b[X]!=Y) == [(a, None), (b, None)] assert (A.b[X]!='a') == [(b,)] assert (A.b[X]!='z') == [(a,), (b,)] assert (A.b[a]!='a') == [] assert list(A.b[b]!='a') == [()] assert ((A.b[b]!='a') & (A.b[b]!='z')) == [()] assert (A.b[X]<Y) == [(a, None), (b, None)] assert (A.b[X]<'a') == [] assert (A.b[X]<'z') == [(a,), (b,)] assert (A.b[a]<'b') == [()] assert (A.b[b]<'a') == [] assert ((A.b[b]<'z') & (A.b[b]!='z')) == [()] assert (A.b[X]<='a') == [(a,)] assert (A.b[X]<='z') == [(a,), (b,)] assert (A.b[a]<='b') == [()] assert (A.b[b]<='a') == [] assert ((A.b[b]<='z') & (A.b[b]!='z')) == [()] assert (A.b[X]>'a') == [(b,)] assert (A.b[X]>='a') == [(a,), (b,)] assert (A.c[X]<='a') == [(a,)] assert (A.c[X]<='a'+'') == [(a,)] assert (A.c[X]._in(('a',))) == [(a,)] assert (A.c[X]._in(('a',)+('z',))) == [(a,)] assert ((Y==('a',)) & (A.c[X]._in(Y))) == [(('a',), a)] # TODO make ' in ' work assert ((Y==('a',)) & (A.c[X]._in(Y+('z',)))) == [(('a',), a)] # TODO make ' in ' work assert (A.c[X]._in(('z',))) == [] # more complex queries assert ((Y=='a') & (A.b[X]!=Y)) == [('a', b)] # order of appearance of the variables ! assert (A.len[X]==Y) == [(b, 1), (a, 1)] assert (A.len[a]==Y) == [(1,)] """ subclass """ class Z(A): def __init__(self, z): super(Z, self).__init__(z+'a') self.z = z def __repr__(self): return self.z @pyDatalog.program() # indicates that the following method contains pyDatalog clauses def _(): (Z.w[X]==N) <= (Z.z[X]!=N) @classmethod def _pyD_query(cls, pred_name, args): if pred_name == 'Z.pred': if args[0].is_const() and args[0].id.b != 'za': yield (args[0].id,) else: for X in pyDatalog.metaMixin.__refs__[cls]: if X.b != 'za': yield (X,) else: raise AttributeError z = Z('z') assert z.z == 'z' assert (Z.z[X]=='z') == [(z,)] assert ((Z.z[X]=='z') & (Z.z[X]>'a')) == [(z,)] assert list(X.data) == [z] try: a.z == 'z' except Exception as e: e_message = e.message if hasattr(e, 'message') else e.args[0] if e_message != "Predicate without definition (or error in resolver): A.z[1]==/2": print(e_message) else: assert False try: (Z.z[a] == 'z') == None except Exception as e: e_message = e.message if hasattr(e, 'message') else e.args[0] if e_message != "Object is incompatible with the class that is queried.": print(e_message) else: assert False assert (Z.b[X]==Y) == [(z, 'za')] assert (Z.c[X]==Y) == [(z, 'za')] assert ((Z.c[X]==Y) & (Z.c[X]>'a')) == [(z, 'za')] assert (Z.c[X]>'a') == [(z,)] assert ((Z.c[X]>'a') & (A.c[X]=='za')) == [(z,)] assert (A.c[X]=='za') == [(z,)] assert (A.c[z]=='za') == [()] assert (z.b) == 'za' assert (z.c) == 'za' w = Z('w') w = Z('w') # duplicated to test __refs__[cls] assert(Z.x(X)) == [(z,)] assert not (~Z.x(z)) assert ~Z.x(w) assert ~ (Z.z[w]=='z') assert(Z.pred(X)) == [(w,)] # not duplicated ! assert(Z.pred(X) & ~ (Z.z[X]>='z')) == [(w,)] assert(Z.x(X) & ~(Z.pred(X))) == [(z,)] assert (Z.len[X]==Y) == [(w, 1), (z, 1)] assert (Z.len[z]==Y) == [(1,)] # TODO print (A.b[w]==Y) """ python resolvers """ @pyDatalog.predicate() def p(X,Y): yield (1,2) yield (2,3) assert pyDatalog.ask('p(X,Y)') == set([(1, 2), (2, 3)]) assert pyDatalog.ask('p(1,Y)') == set([(1, 2)]) assert pyDatalog.ask('p(1,2)') == set([(1, 2)]) """ error detection """ @pyDatalog.program() def _(): pass error = False try: _() except: error = True assert error def assert_error(code, message='^$'): _error = False try: pyDatalog.load(code) except Exception as e: e_message = e.message if hasattr(e, 'message') else e.args[0] # python 2 and 3 if not re.match(message, e_message): print(e_message) _error = True assert _error def assert_ask(code, message='^$'): _error = False try: pyDatalog.ask(code) except Exception as e: e_message = e.message if hasattr(e, 'message') else e.args[0] if not re.match(message, e_message): print(e_message) _error = True assert _error assert_error('ask(z(a),True)', 'Too many arguments for ask \!') assert_error('ask(z(a))', 'Predicate without definition \(or error in resolver\): z/1') assert_error("+ farmer(farmer(moshe))", "Syntax error: Literals cannot have a literal as argument : farmer\[\]") assert_error("+ manager[Mary]==John", "Left-hand side of equality must be a symbol or function, not an expression.") assert_error("manager[X]==Y <= (X==Y)", "Syntax error: please verify parenthesis around \(in\)equalities") assert_error("p(X) <= (Y==2)", "Can't create clause") assert_error("p(X) <= X==1 & X==2", "Syntax error: please verify parenthesis around \(in\)equalities") assert_error("p(X) <= (manager[X]== min(X))", "Error: argument missing in aggregate") assert_error("p(X) <= (manager[X]== max(X, order_by=X))", "Aggregation cannot appear in the body of a clause") assert_error("q(min(X, order_by=X)) <= p(X)", "Syntax error: Incorrect use of aggregation\.") assert_error("manager[X]== min(X, order_by=X) <= manager(X)", "Syntax error: please verify parenthesis around \(in\)equalities") assert_error("(manager[X]== min(X, order_by=X+2)) <= manager(X)", "order_by argument of aggregate must be variable\(s\), not expression\(s\).") assert_error("ask(X<1)", 'Error: left hand side of comparison must be bound: =X<1/1') assert_error("ask(X<Y)", 'Error: left hand side of comparison must be bound: =X<Y/2') assert_error("ask(1<Y)", 'Error: left hand side of comparison must be bound: =Y>1/1') assert_error("ask( (A.c[X]==Y) & (Z.c[X]==Y))", "TypeError: First argument of Z.c\[1\]==\('.','.'\) must be a Z, not a A ") assert_ask("A.u[X]==Y", "Predicate without definition \(or error in resolver\): A.u\[1\]==/2") assert_ask("A.u[X,Y]==Z", "Predicate without definition \(or error in resolver\): A.u\[2\]==/3") assert_error('(a_sum[X] == sum(Y, key=Y)) <= p(X, Z, Y)', "Error: Duplicate definition of aggregate function.") assert_error('(two(X)==Z) <= (Z==X+(lambda X: X))', 'Syntax error near equality: consider using brackets. two\(X\)') assert_error('p(X) <= sum(X, key=X)', 'Invalid body for clause') assert_error('ask(- manager[X]==1)', "Left-hand side of equality must be a symbol or function, not an expression.") assert_error("p(X) <= (X=={})", "unhashable type: 'dict'") """ SQL Alchemy """ from sqlalchemy import create_engine from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship engine = create_engine('sqlite:///:memory:', echo=False) # create database in memory Session = sessionmaker(bind=engine) session = Session() Base = declarative_base(cls=pyDatalog.Mixin, metaclass=pyDatalog.sqlMetaMixin) Base.session = session class Employee(Base): # --> Employee inherits from the Base class __tablename__ = 'employee' name = Column(String, primary_key=True) manager_name = Column(String, ForeignKey('employee.name')) salary = Column(Integer) def __init__(self, name, manager_name, salary): super(Employee, self).__init__() self.name = name self.manager_name = manager_name # direct manager of the employee, or None self.salary = salary # monthly salary of the employee def __repr__(self): # specifies how to display the employee return "Employee: %s" % self.name @pyDatalog.program() # --> the following function contains pyDatalog clauses def Employee(): (Employee.manager[X]==Y) <= (Employee.manager_name[X]==Z) & (Z==Employee.name[Y]) # the salary class of employee X is computed as a function of his/her salary # this statement is a logic equality, not an assignment ! Employee.salary_class[X] = Employee.salary[X]//1000 # all the indirect managers of employee X are derived from his manager, recursively Employee.indirect_manager(X,Y) <= (Employee.manager[X]==Y) & (Y != None) Employee.indirect_manager(X,Y) <= (Employee.manager[X]==Z) & Employee.indirect_manager(Z,Y) & (Y != None) # count the number of reports of X (Employee.report_count[X] == len(Y)) <= Employee.indirect_manager(Y,X) Employee.p(X,Y) <= (Y <= Employee.salary[X] + 1) Base.metadata.create_all(engine) John = Employee('John', None, 6800) Mary = Employee('Mary', 'John', 6300) Sam = Employee('Sam', 'Mary', 5900) session.add(John) session.add(Mary) session.add(Sam) session.commit() assert (John.salary_class ==6) X = pyDatalog.Variable() result = (Employee.salary[X] == 6300) # notice the similarity to a pyDatalog query assert result == [(Mary,), ] assert (X._value() == [Mary,]) # prints [Employee: Mary] assert (X.v() == Mary) # prints Employee:Mary result = (Employee.indirect_manager(Mary, X)) assert result == [(John,), ] assert (X.v() == John) # prints [Employee: John] Mary.salary_class = ((Employee.salary_class[Mary]==X) >= X) Mary.salary = 10000 assert Mary.salary_class != ((Employee.salary_class[Mary]==X) >= X) X, Y, N = pyDatalog.variables(3) result = (Employee.salary[X]==6800) & (Employee.name[X]==N) assert result == [(John,'John'), ] assert N.v() == 'John' result = (Employee.salary[X]==Employee.salary[X]) assert result == [(John,), (Mary,), (Sam,)] result = (Employee.p(X,1)) assert result == [(John,), (Mary,), (Sam,)] result = (Employee.salary[X]<Employee.salary[X]+1) assert result == [(John,), (Mary,), (Sam,)] result = (Employee.salary[John]==N) & Employee.p(John, N) assert result == [(6800,)] result = (Employee.salary[X]==6800) & (Employee.salary[X]==N) & Employee.p(X, N) assert result == [(John, 6800)] """
else: new_source = source try: code.InteractiveConsole.runsource(self, new_source, filename, symbol) except Exception as e: print(e) pyEngine.Auto_print = True if __name__ == "__main__": parser = argparse.ArgumentParser(description='FoundationDB Query Console') parser.add_argument('-p', '--python', help='''Python module to be imported. pyDatalog.create_atoms must be called for any Datalog included.''') parser.add_argument('-d', '--datalog', help='''File with Datalog statements (only) to be loaded. Atoms will be automatically created.''') args = parser.parse_args() if args.python: import_all_from(args.python) if args.datalog: with open(args.datalog, 'r') as f: dl_defs = f.read() f.closed pyDatalog.load(dl_defs) globalize_atoms(compile(dl_defs, '<string>', 'exec')) console = fdbqueryConsole(locals=locals()) console.set_mode('query') console.interact('')
from pyDatalog import pyDatalog pyDatalog.create_terms('croakes, eatflies, frog, chrips, sings, canary, green, yellow, P, X') pyDatalog.load(""" frog(X) <= croakes(X) & eatflies(X) canary(X) <= sings(X) & chrips(X) green(X) <= frog(X) yellow(X) <= canary(X) """) pyDatalog.assert_fact('croakes', 'Fritz') pyDatalog.assert_fact('eatflies', 'Fritz') pyDatalog.assert_fact('sings', 'Paul') pyDatalog.assert_fact('chrips', 'Paul') query = 'yellow(X)' answers = pyDatalog.ask(query).answers print(answers) print(pyDatalog.ask('green(X)'))
Employee.indirect_manager(Mary, X) print(X) # prints [John] # Who are the employees of John with a salary below 6000 ? result = (Employee.salary[X] < 6000) & Employee.indirect_manager(X, John) print(result) # prints [(Sam,)] print(X) # prints [Sam] print((Employee.salary_class[X] == 5) & Employee.indirect_manager(X, John) >= X) # Sam # verify that the manager of Mary is John assert Employee.manager[Mary]==John # who is his own indirect manager ? Employee.indirect_manager(X, X) print(X) # prints [] # who has 2 reports ? Employee.report_count[X] == 2 print(X) # prints [John] # what is the total salary of the employees of John ? # note : it is better to place aggregation clauses in the class definition pyDatalog.load("(Employee.budget[X] == sum(N, for_each=Y)) <= (Employee.indirect_manager(Y, X)) & (Employee.salary[Y]==N)") Employee.budget[John]==X print(X) # prints [12200] # who has the lowest salary ? pyDatalog.load("(lowest[1] == min(X, order_by=N)) <= (Employee.salary[X]==N)") # must use ask() because inline queries cannot use unprefixed literals print(pyDatalog.ask("lowest[1]==X")) # prints set([(1, 'Sam')])
pdl.load(''' + male(daniel) + male(nicolas) + male(alain) + male(luigi) + male(johnny) + male(sacha) + male(ernest) + male(robert) + male(gilbert) + female(suzanne) + female(christine) + female(keiko) + female(rose_marie) + female(sylvie) + female(muriel) + female(magali) + female(maya) + female(nana) + female(suzanne_madeleine) + female(violette) + female(jacqueline) + husband(nicolas, keiko) + husband(johnny, luigi) + husband(maurice, jacqueline) + husband(gilbert, rose_marie) + father(gilbert, muriel) + father(gilbert, sylvie) + mother(rose_marie, muriel) + mother(rose_marie, sylvie) + father(ernest, suzanne) + father(ernest, jacqueline) + mother(suzanne_madeleine, suzanne) + mother(suzanne_madeleine, jacqueline) + father(robert, daniel) + father(robert, gilbert) + mother(violette, daniel) + mother(violette, gilbert) + father(daniel, nicolas) + father(daniel, alain) + father(daniel, christine) + mother(suzanne, nicolas) + mother(suzanne, alain) + mother(suzanne, christine) + father(johnny, luigi) + father(johnny, magali) + mother(christine, luigi) + mother(christine, magali) + father(nicolas, sacha) + father(nicolas, maya) + father(nicolas, nana) + mother(keiko, sacha) + mother(keiko, maya) + mother(keiko, nana) parent(X, Y) <= (father(X, Y)) parent(X, Y) <= (mother(X, Y)) print(parent(Parent, Child) & (Child == nicolas)) print() grand_parent(X, Y) <= (parent(X, Z) & parent(Z, Y)) grand_father(X, Y) <= (grand_parent(X, Y) & male(X)) grand_mother(X, Y) <= (grand_parent(X, Y) & female(X)) print(grand_parent(GrandParent, GrandChild) & (GrandChild == nicolas)) print() print(grand_father(GrandFather, GrandChild) & (GrandChild == nicolas)) print() print(grand_mother(GrandMother, GrandChild) & (GrandChild == nicolas)) print() sibling(X, Y) <= (parent(Z, X) & parent(Z, Y) & (X != Y)) brother(X, Y) <= (male(X) & sibling(X, Y)) sister(X, Y) <= (female(X) & sibling(X, Y)) print(sibling(Sibling, X) & (X == nicolas)) print() print(brother(Brother, X) & (X == nicolas)) print() print(sister(Sister, X) & (X == nicolas)) print() uncle(X, Y) <= (parent(Z, Y) & brother(X, Z)) uncle(X, Y) <= (parent(Z, Y) & sibling(A, Z) & husband(X, A)) aunt(X, Y) <= (parent(Z, Y) & sister(X, Z)) aunt(X, Y) <= (parent(Z, Y) & sibling(A, Z) & husband(A, X)) print(uncle(Uncle, X) & (X == nicolas)) print() print(aunt(Aunt, X) & (X == nicolas)) print() ancestor(X, Y) <= (parent(X, Y)) ancestor(X, Y) <= (parent(X, Z) & ancestor(Z, Y)) print(ancestor(MaleAncestor, X) & (X == nicolas) & male(MaleAncestor)) print() descendant(X, Y) <= (ancestor(Y, X)) print(descendant(FemaleDescendant, X) & (X == daniel) & female(FemaleDescendant)) print() ''')
return self.statements def asDatacode(self): datacode = "\n".join(self.statements) print datacode return datacode def asTerms(self): allterms = ",".join(set(self.terms)) #print allterms return allterms csvToDatalog = CsvToDatalog() csvToDatalog.load() pyDatalog.create_terms(csvToDatalog.asTerms()) pyDatalog.load(csvToDatalog.asDatacode()) pyDatalog.create_terms('SC', 'NAME', 'FRONT', 'HORIZ', 'VERT', 'VP') #print shapes(SC,NAME,FRONT,HORIZ,VERT,VP) pyDatalog.create_terms('nextShape','startShape') shape_brothers = defaultdict(list) for shape in shapes(SC,NAME,FRONT,HORIZ,VERT,VP).data: new_conf = (shape[2],shape[3],shape[4],shape[5]) shape_brothers[new_conf].append(shape[1]) for shape in shape_brothers.items(): items = shape[1] items.sort() + startShape(items[0])
from pyDatalog.pyDatalog import create_terms, ask, load, assert_fact, clear if __name__ == "__main__": clear() create_terms('X, frog, canary, green, yellow, chirps, sings, croakes, eatFlies') load(""" frog(X) <= croakes(X) & eatFlies(X) canary(X) <= chirps(X) & sings(X) green(X) <= frog(X) yellow(X) <= canary(X) """) assert_fact('croakes', 'fritz') assert_fact('eatFlies', 'fritz') print("frog: ", ask('frog(X)')) print("green: ", ask('green(X)')) print("green: ", ask("green('cuitcuit')"))
# print(indirect_manager('Sam', Y)) #print(indirect_manager(X,'John')) indirect_manager('Sam', Y) resultado = Y.data[1] print("resultado", resultado) # + parent(bill, 'John Adams') pyDatalog.assert_fact('parent', 'bill', 'John Adams') print(pyDatalog.ask('parent(bill,X)')) # specify what an ancestor is pyDatalog.load(""" ancestor(X,Y) <= parent(X,Y) ancestor(X,Y) <= parent(X,Z) & ancestor(Z,Y) """) # prints a set with one element : the ('bill', 'John Adams') tuple W = pyDatalog.ask('parent(bill,X)') print(W.answers[0][0]) # W = pyDatalog.ask('ancestor(bill,X)') print('Bill es ancestro de:', W.answers[0][0]) # - parent(bill, 'John Adams') pyDatalog.retract_fact('parent', 'bill', 'John Adams') W = pyDatalog.ask('parent(bill,X)') if (W.__str__() != 'None'): print(W.__str__())
# Who are the employees of John with a salary below 6000 ? result = (Employee.salary[X] < 6000) & Employee.indirect_manager(X, John) print(result) # prints [(Sam,)] print(X) # prints [Sam] print((Employee.salary_class[X] == 5) & Employee.indirect_manager(X, John) >= X) # Sam # verify that the manager of Mary is John assert Employee.manager[Mary] == John # who is his own indirect manager ? Employee.indirect_manager(X, X) print(X) # prints [] # who has 2 reports ? Employee.report_count[X] == 2 print(X) # prints [John] # what is the total salary of the employees of John ? # note : it is better to place aggregation clauses in the class definition pyDatalog.load( "(Employee.budget[X] == sum(N, for_each=Y)) <= (Employee.indirect_manager(Y, X)) & (Employee.salary[Y]==N)" ) Employee.budget[John] == X print(X) # prints [12200] # who has the lowest salary ? pyDatalog.load("(lowest[1] == min(X, order_by=N)) <= (Employee.salary[X]==N)") # must use ask() because inline queries cannot use unprefixed literals print(pyDatalog.ask("lowest[1]==X")) # prints set([(1, 'Sam')])
def loadBigString(string, cnt): try: load(string) except Exception: import traceback print(traceback.format_exc())
#>> Terms of Dimension #Person pd.create_terms("person, specialty, contract, division, all_persons") pd.create_terms("personSpec, personContract, specDiv") #Drug pd.create_terms("drug, drtype, all_drugs") pd.create_terms("drugType") #>> Terms for Facts pd.create_terms("admDrug, bills") #>> Reading Dimension and Facts dim = open("Dimension.txt", 'r').read() pd.load(dim) facts = open("Facts.txt", 'r').read() pd.load(facts) print(facts) print("==========================================================================") #>>Rule pd.create_terms("Date, Specialist, DrType, Patient, Amount, Age, Drug, PrescribedBy, Gen, billsT, admDrug1, admDrugT") admDrug1(Date, PrescribedBy, Drug, Patient) <= bills(Date, Specialist, DrType, Patient, Amount) & personSpec(PrescribedBy, Specialist) & drugType(Drug, DrType) admDrugT(Date, PrescribedBy, Drug, Patient, Age) <= admDrug(Date, PrescribedBy, Drug, Patient, Age) & ~(admDrug1(Date, PrescribedBy, Drug, Patient)) #>> Generation (Rule ID: G_01) billsT(Date, Specialist, DrType, Patient, "G_01", Gen) <= (admDrugT(Date, PrescribedBy, Drug, Patient, Age) & personSpec(PrescribedBy, Specialist) & drugType(Drug, DrType) & (Gen=="G_01"))
from pyDatalog.pyDatalog import create_terms, load, ask, assert_fact create_terms( 'X, croakes, eatFlies, green, frog, sings, chirps, yellow, canary') load(""" """) frog(X) <= croakes(X) & eatFlies(X) canary(X) <= sings(X) & chirps(X) green(X) <= frog(X) yellow(X) <= canary(X) assert_fact('croakes', 'fritz') assert_fact('eatFlies', 'fritz') +sings('titi') +chirps('titi') +frog('Toto') # assert_fact('sings','Jean' ) # assert_fact('chirps','Jean' ) query = 'yellow(X)' answers = ask(query).answers print(answers) print(ask('frog(X)')) print(ask("frog('fritz')"))
# -*- coding: utf-8 -*- """ Created on Fri Nov 29 14:34:10 2019 @author: Margot """ from pyDatalog import pyDatalog pyDatalog.clear() pyDatalog.create_terms( 'X, P, rectangle, angleDroit, quelconque, equilateral, deuxcote, troiscote, isocele, rectangleIsocele, triangle' ) pyDatalog.load(""" """) rectangle(X) <= angleDroit(X) isocele(X) <= deuxcote(X) rectangleIsocele(X) <= angleDroit(X) & deuxcote(X) equilateral(X) <= troiscote(X) pyDatalog.assert_fact('deuxcote', 'triangle') pyDatalog.assert_fact('angleDroit', 'triangle') query = 'isocele(X)' answers = pyDatalog.ask(query).answers print(answers)