def test_check_consistency(): a = LogicParser().parse('man(j)') b = LogicParser().parse('-man(j)') print '%s, %s: %s' % (a, b, RTEInferenceTagger().check_consistency([a, b], True)) print '%s, %s: %s' % (a, a, RTEInferenceTagger().check_consistency([a, a], True))
def demo(): from nltk_contrib.drt import DRT DRT.testTp_equals() print '\n' lp = LogicParser() a = lp.parse(r'some x.((man x) and (walks x))') b = lp.parse(r'some x.((walks x) and (man x))') bicond = ApplicationExpression(ApplicationExpression(Operator('iff'), a), b) print "Trying to prove:\n '%s <-> %s'" % (a.infixify(), b.infixify()) print 'tableau: %s' % get_prover(bicond, prover_name='tableau').prove() print 'Prover9: %s' % get_prover(bicond, prover_name='Prover9').prove() print '\n' demo_drt_glue_remove_duplicates() lp = LogicParser() a = lp.parse(r'all x.((man x) implies (mortal x))') b = lp.parse(r'(man socrates)') c1 = lp.parse(r'(mortal socrates)') c2 = lp.parse(r'(not (mortal socrates))') print get_prover(c1, [a,b], 'prover9').prove() print get_prover(c2, [a,b], 'prover9').prove() print get_model_builder(c1, [a,b], 'mace').build_model() print get_model_builder(c2, [a,b], 'mace').build_model()
def test_config(): a = LogicParser().parse('(walk(j) & sing(j))') g = LogicParser().parse('walk(j)') p = Prover9Command(g, assumptions=[a]) p._executable_path = None p.prover9_search = [] p.prove() #config_prover9('/usr/local/bin') print p.prove() print p.proof()
def test_prove(arguments): """ Try some proofs and exhibit the results. """ for (goal, assumptions) in arguments: g = LogicParser().parse(goal) alist = [LogicParser().parse(a) for a in assumptions] p = Prover9Command(g, assumptions=alist).prove() for a in alist: print ' %s' % a print '|- %s: %s\n' % (g, p)
def testResolutionProver(): resolution_test(r'man(x)') resolution_test(r'(man(x) -> man(x))') resolution_test(r'(man(x) -> --man(x))') resolution_test(r'-(man(x) and -man(x))') resolution_test(r'(man(x) or -man(x))') resolution_test(r'(man(x) -> man(x))') resolution_test(r'-(man(x) and -man(x))') resolution_test(r'(man(x) or -man(x))') resolution_test(r'(man(x) -> man(x))') resolution_test(r'(man(x) iff man(x))') resolution_test(r'-(man(x) iff -man(x))') resolution_test('all x.man(x)') resolution_test('-all x.some y.F(x,y) & some x.all y.(-F(x,y))') resolution_test('some x.all y.sees(x,y)') p1 = LogicParser().parse(r'all x.(man(x) -> mortal(x))') p2 = LogicParser().parse(r'man(Socrates)') c = LogicParser().parse(r'mortal(Socrates)') print('%s, %s |- %s: %s' % (p1, p2, c, ResolutionProver().prove(c, [p1, p2]))) p1 = LogicParser().parse(r'all x.(man(x) -> walks(x))') p2 = LogicParser().parse(r'man(John)') c = LogicParser().parse(r'some y.walks(y)') print('%s, %s |- %s: %s' % (p1, p2, c, ResolutionProver().prove(c, [p1, p2]))) p = LogicParser().parse( r'some e1.some e2.(believe(e1,john,e2) & walk(e2,mary))') c = LogicParser().parse(r'some e0.walk(e0,mary)') print('%s |- %s: %s' % (p, c, ResolutionProver().prove(c, [p])))
def default_reasoning_demo(): lp = LogicParser() premises = [] #define taxonomy premises.append(lp.parse(r'all x.(elephant(x) -> animal(x))')) premises.append(lp.parse(r'all x.(bird(x) -> animal(x))')) premises.append(lp.parse(r'all x.(dove(x) -> bird(x))')) premises.append(lp.parse(r'all x.(ostrich(x) -> bird(x))')) premises.append(lp.parse(r'all x.(flying_ostrich(x) -> ostrich(x))')) #default properties premises.append(lp.parse(r'all x.((animal(x) & -Ab1(x)) -> -fly(x))')) #normal animals don't fly premises.append(lp.parse(r'all x.((bird(x) & -Ab2(x)) -> fly(x))')) #normal birds fly premises.append(lp.parse(r'all x.((ostrich(x) & -Ab3(x)) -> -fly(x))')) #normal ostriches don't fly #specify abnormal entities premises.append(lp.parse(r'all x.(bird(x) -> Ab1(x))')) #flight premises.append(lp.parse(r'all x.(ostrich(x) -> Ab2(x))')) #non-flying bird premises.append(lp.parse(r'all x.(flying_ostrich(x) -> Ab3(x))')) #flying ostrich #define entities premises.append(lp.parse(r'elephant(E)')) premises.append(lp.parse(r'dove(D)')) premises.append(lp.parse(r'ostrich(O)')) #print the assumptions prover = Prover9Command(None, premises) command = UniqueNamesProver(ClosedWorldProver(prover)) for a in command.assumptions(): print(a) print_proof('-fly(E)', premises) print_proof('fly(D)', premises) print_proof('-fly(O)', premises)
def unique_names_demo(): lp = LogicParser() p1 = lp.parse(r'man(Socrates)') p2 = lp.parse(r'man(Bill)') c = lp.parse(r'exists x.exists y.(x != y)') prover = Prover9Command(c, [p1, p2]) print(prover.prove()) unp = UniqueNamesProver(prover) print('assumptions:') for a in unp.assumptions(): print(' ', a) print('goal:', unp.goal()) print(unp.prove()) p1 = lp.parse(r'all x.(walk(x) -> (x = Socrates))') p2 = lp.parse(r'Bill = William') p3 = lp.parse(r'Bill = Billy') c = lp.parse(r'-walk(William)') prover = Prover9Command(c, [p1, p2, p3]) print(prover.prove()) unp = UniqueNamesProver(prover) print('assumptions:') for a in unp.assumptions(): print(' ', a) print('goal:', unp.goal()) print(unp.prove())
def test_clausify(): lp = LogicParser() print(clausify(lp.parse('P(x) | Q(x)'))) print(clausify(lp.parse('(P(x) & Q(x)) | R(x)'))) print(clausify(lp.parse('P(x) | (Q(x) & R(x))'))) print(clausify(lp.parse('(P(x) & Q(x)) | (R(x) & S(x))'))) print(clausify(lp.parse('P(x) | Q(x) | R(x)'))) print(clausify(lp.parse('P(x) | (Q(x) & R(x)) | S(x)'))) print(clausify(lp.parse('exists x.P(x) | Q(x)'))) print(clausify(lp.parse('-(-P(x) & Q(x))'))) print(clausify(lp.parse('P(x) <-> Q(x)'))) print(clausify(lp.parse('-(P(x) <-> Q(x))'))) print(clausify(lp.parse('-(all x.P(x))'))) print(clausify(lp.parse('-(some x.P(x))'))) print(clausify(lp.parse('some x.P(x)'))) print(clausify(lp.parse('some x.all y.P(x,y)'))) print(clausify(lp.parse('all y.some x.P(x,y)'))) print(clausify(lp.parse('all z.all y.some x.P(x,y,z)'))) print( clausify( lp.parse('all x.(all y.P(x,y) -> -all y.(Q(x,y) -> R(x,y)))')))
def tableau_test(c, ps=None, verbose=False): lp = LogicParser() pc = lp.parse(c) pps = ([lp.parse(p) for p in ps] if ps else []) if not ps: ps = [] print('%s |- %s: %s' % (', '.join(ps), pc, TableauProver().prove(pc, pps, verbose=verbose)))
def test_convert_to_prover9(expr): """ Test that parsing works OK. """ for t in expr: e = LogicParser().parse(t) print convert_to_prover9(e)
def demo(): test_clausify() print() testResolutionProver() print() p = LogicParser().parse('man(x)') print(ResolutionProverCommand(p, [p]).prove())
def _create_axiom(self, word_text, word_synset, nym_text, pos, operator): nym_text = nym_text.split('(')[0] nym_word = pos[nym_text] dist = 1 #min([word_synset.shortest_path_distance(nym_synset) for nym_synset in nym_word]) word_text = word_text.replace('.', '') nym_text = nym_text.replace('.', '') exp_text = 'all x.(%s(x) %s %s(x))' % (word_text, operator, nym_text) return (LogicParser().parse(exp_text), dist)
def combination_prover_demo(): lp = LogicParser() p1 = lp.parse(r'see(Socrates, John)') p2 = lp.parse(r'see(John, Mary)') c = lp.parse(r'-see(Socrates, Mary)') prover = Prover9Command(c, [p1, p2]) print(prover.prove()) command = ClosedDomainProver(UniqueNamesProver(ClosedWorldProver(prover))) for a in command.assumptions(): print(a) print(command.prove())
def process(SEM): # parse string object to TLP type tlp = LogicParser(True) SEM = tlp.parse(SEM) expression_list = [] # extract individual logic statements while type(SEM) is nltk.sem.logic.AndExpression: # parse unique entity expression_list.append(parse(SEM.second)) SEM = SEM.first # process trailing logic statement expression_list.append(parse(SEM)) return ([expression for expression in expression_list])
def _create_axiom_synset_sisters(self, text1, word1_synset, text2, word2_synset, pos): """ Return an expression of the form 'all x.(word(x) -> (not sister(x)))'. The reverse is not needed because it is equal to 'all x.((not word(x)) or (not sister(x)))' """ text2 = text2.split('(')[0] dist = 1 #word1_synset.shortest_path_distance(word2_synset) text1 = text1.replace('.', '') text2 = text2.replace('.', '') exp_text = 'all x.(%s(x) -> (not %s(x)))' % (text1, text2) return (LogicParser().parse(exp_text), dist)
def testTableauProver(): tableau_test('P | -P') tableau_test('P & -P') tableau_test('Q', ['P', '(P -> Q)']) tableau_test('man(x)') tableau_test('(man(x) -> man(x))') tableau_test('(man(x) -> --man(x))') tableau_test('-(man(x) and -man(x))') tableau_test('(man(x) or -man(x))') tableau_test('(man(x) -> man(x))') tableau_test('-(man(x) and -man(x))') tableau_test('(man(x) or -man(x))') tableau_test('(man(x) -> man(x))') tableau_test('(man(x) iff man(x))') tableau_test('-(man(x) iff -man(x))') tableau_test('all x.man(x)') tableau_test('all x.all y.((x = y) -> (y = x))') tableau_test('all x.all y.all z.(((x = y) & (y = z)) -> (x = z))') # tableau_test('-all x.some y.F(x,y) & some x.all y.(-F(x,y))') # tableau_test('some x.all y.sees(x,y)') parse = LogicParser().parse p1 = 'all x.(man(x) -> mortal(x))' p2 = 'man(Socrates)' c = 'mortal(Socrates)' tableau_test(c, [p1, p2]) p1 = 'all x.(man(x) -> walks(x))' p2 = 'man(John)' c = 'some y.walks(y)' tableau_test(c, [p1, p2]) p = '((x = y) & walks(y))' c = 'walks(x)' tableau_test(c, [p]) p = '((x = y) & ((y = z) & (z = w)))' c = '(x = w)' tableau_test(c, [p]) p = 'some e1.some e2.(believe(e1,john,e2) & walk(e2,mary))' c = 'some e0.walk(e0,mary)' tableau_test(c, [p]) c = '(exists x.exists z3.((x = Mary) & ((z3 = John) & sees(z3,x))) <-> exists x.exists z4.((x = John) & ((z4 = Mary) & sees(x,z4))))' tableau_test(c)
def satdemo(trace=None): """Satisfiers of an open formula in a first order model.""" print print '*' * mult print "Satisfiers Demo" print '*' * mult folmodel(quiet=True) formulas = [ 'boy(x)', '(x = x)', '(boy(x) | girl(x))', '(boy(x) & girl(x))', 'love(adam, x)', 'love(x, adam)', '-(x = adam)', 'exists z22. love(x, z22)', 'exists y. love(y, x)', 'all y. (girl(y) -> love(x, y))', 'all y. (girl(y) -> love(y, x))', 'all y. (girl(y) -> (boy(x) & love(y, x)))', '(boy(x) & all y. (girl(y) -> love(x, y)))', '(boy(x) & all y. (girl(y) -> love(y, x)))', '(boy(x) & exists y. (girl(y) & love(y, x)))', '(girl(x) -> dog(x))', 'all y. (dog(y) -> (x = y))', 'exists y. love(y, x)', 'exists y. (love(adam, y) & love(y, x))' ] if trace: print m2 lp = LogicParser() for fmla in formulas: print fmla lp.parse(fmla) parsed = [lp.parse(fmla) for fmla in formulas] for p in parsed: g2.purge() print "The satisfiers of '%s' are: %s" % (p, m2.satisfiers(p, 'x', g2, trace))
def folmodel(quiet=False, trace=None): """Example of a first-order model.""" global val2, v2, dom2, m2, g2 v2 = [('adam', 'b1'), ('betty', 'g1'), ('fido', 'd1'),\ ('girl', set(['g1', 'g2'])), ('boy', set(['b1', 'b2'])), ('dog', set(['d1'])), ('love', set([('b1', 'g1'), ('b2', 'g2'), ('g1', 'b1'), ('g2', 'b1')]))] val2 = Valuation(v2) dom2 = val2.domain m2 = Model(dom2, val2) g2 = Assignment(dom2, [('x', 'b1'), ('y', 'g2')]) if not quiet: print() print('*' * mult) print("Models Demo") print("*" * mult) print("Model m2:\n", "-" * 14, "\n", m2) print("Variable assignment = ", g2) exprs = ['adam', 'boy', 'love', 'walks', 'x', 'y', 'z'] lp = LogicParser() parsed_exprs = [lp.parse(e) for e in exprs] print() for parsed in parsed_exprs: try: print("The interpretation of '%s' in m2 is %s" % (parsed, m2.i(parsed, g2))) except Undefined: print("The interpretation of '%s' in m2 is Undefined" % parsed) applications = [('boy', ('adam')), ('walks', ('adam', )), ('love', ('adam', 'y')), ('love', ('y', 'adam'))] for (fun, args) in applications: try: funval = m2.i(lp.parse(fun), g2) argsval = tuple(m2.i(lp.parse(arg), g2) for arg in args) print("%s(%s) evaluates to %s" % (fun, args, argsval in funval)) except Undefined: print("%s(%s) evaluates to Undefined" % (fun, args))
def __init__(self, meaning, glue, indices=None): if not indices: indices = set() if isinstance(meaning, string_types): self.meaning = LogicParser().parse(meaning) elif isinstance(meaning, Expression): self.meaning = meaning else: raise RuntimeError('Meaning term neither string or expression: %s, %s' % (meaning, meaning.__class__)) if isinstance(glue, string_types): self.glue = linearlogic.LinearLogicParser().parse(glue) elif isinstance(glue, linearlogic.Expression): self.glue = glue else: raise RuntimeError('Glue term neither string or expression: %s, %s' % (glue, glue.__class__)) self.indices = indices
def _common_BK(): # From Recognising Textual Entailment by Bos&Markert return [ LogicParser().parse('all x y z.((in(x,y) & in(y,z)) -> in(x,z))'), LogicParser().parse( 'all e x y.((event(e) & subj(e,x) & in(e,y)) -> in(x,y))'), LogicParser().parse( 'all e x y.((event(e) & obj(e,x) & in(e,y)) -> in(x,y))'), LogicParser().parse( 'all e x y.((event(e) & theme(e,x) & in(e,y)) -> in(x,y))'), LogicParser().parse( 'all x y.(in(x,y) -> some e.(locate(e) & obj(e,x) & in(e,y)))' ), LogicParser().parse( 'all x y.(of(x,y) -> some e.(have(e) & subj(e,y) & obj(e,x)))' ), LogicParser().parse('all e y.((event(e) & subj(e,x)) -> by(e,x))') ]
def closed_world_demo(): lp = LogicParser() p1 = lp.parse(r'walk(Socrates)') p2 = lp.parse(r'(Socrates != Bill)') c = lp.parse(r'-walk(Bill)') prover = Prover9Command(c, [p1, p2]) print(prover.prove()) cwp = ClosedWorldProver(prover) print('assumptions:') for a in cwp.assumptions(): print(' ', a) print('goal:', cwp.goal()) print(cwp.prove()) p1 = lp.parse(r'see(Socrates, John)') p2 = lp.parse(r'see(John, Mary)') p3 = lp.parse(r'(Socrates != John)') p4 = lp.parse(r'(John != Mary)') c = lp.parse(r'-see(Socrates, Mary)') prover = Prover9Command(c, [p1, p2, p3, p4]) print(prover.prove()) cwp = ClosedWorldProver(prover) print('assumptions:') for a in cwp.assumptions(): print(' ', a) print('goal:', cwp.goal()) print(cwp.prove()) p1 = lp.parse(r'all x.(ostrich(x) -> bird(x))') p2 = lp.parse(r'bird(Tweety)') p3 = lp.parse(r'-ostrich(Sam)') p4 = lp.parse(r'Sam != Tweety') c = lp.parse(r'-bird(Sam)') prover = Prover9Command(c, [p1, p2, p3, p4]) print(prover.prove()) cwp = ClosedWorldProver(prover) print('assumptions:') for a in cwp.assumptions(): print(' ', a) print('goal:', cwp.goal()) print(cwp.prove())
def evaluate(self, expr, g, trace=None): """ Call the ``LogicParser`` to parse input expressions, and provide a handler for ``satisfy`` that blocks further propagation of the ``Undefined`` error. :param expr: An ``Expression`` of ``logic``. :type g: Assignment :param g: an assignment to individual variables. :rtype: bool or 'Undefined' """ try: lp = LogicParser() parsed = lp.parse(expr) value = self.satisfy(parsed, g, trace=trace) if trace: print() print("'%s' evaluates to %s under M, %s" % (expr, value, g)) return value except Undefined: if trace: print() print("'%s' is undefined under M, %s" % (expr, g)) return 'Undefined'
def __init__(self): self.lp = LogicParser() self.lx = Lexicon() self.fb = FactBase()
def resolution_test(e): f = LogicParser().parse(e) t = ResolutionProver().prove(f) print('|- %s: %s' % (f, t))
#!/usr/bin/python # -*- coding: utf-8 -*- from nltk.sem.logic import LogicParser tlp = LogicParser(True) print(tlp.parse(r'man(x)').type) print(tlp.parse(r'walk(angus)').type) print(tlp.parse(r'-man(x)').type) print(tlp.parse(r'(man(x) <-> tall(x))').type) print(tlp.parse(r'exists x.(man(x) & tall(x))').type) print(tlp.parse(r'\x.man(x)').type) print(tlp.parse(r'john').type) print(tlp.parse(r'\x y.sees(x,y)').type) print(tlp.parse(r'\x.man(x)(john)').type) print(tlp.parse(r'\x.\y.sees(x,y)(john)').type) print(tlp.parse(r'\x.\y.sees(x,y)(john)(mary)').type) print(tlp.parse(r'\P.\Q.exists x.(P(x) & Q(x))').type) print(tlp.parse(r'\x.y').type) print(tlp.parse(r'\P.P(x)').type) parsed = tlp.parse('see(john,mary)') print(parsed.type) print(parsed.function) print(parsed.function.type) print(parsed.function.function) print(parsed.function.function.type) parsed = tlp.parse('P(x,y)') print(parsed) print(parsed.type) print(parsed.function) print(parsed.function.type) print(parsed.function.function)
return '(\\x.(' + sem(tr[1]) + '(x) & ' + sem(tr[2]) + '(x)))' elif (rule == 'QP -> VP'): return '(\\x.(' + sem(tr[0]) + '(x)))' elif (rule == 'NP -> P'): return '\\x.(y=' + sem(tr[0]) + ')(x)' elif ((rule == 'Nom -> AN Rel') or (rule == 'AN -> A AN')): return '(\\x.(' + sem(tr[0]) + '(x) & ' + sem(tr[1]) + '(x)))' elif (rule == 'Rel -> NP T'): return '(\\x.(exists y.((' + sem(tr[0]) + '(y)) & ' + sem( tr[1]) + '(y,x))))' # Logic parser for lambda expressions from nltk.sem.logic import LogicParser lp = LogicParser() # Lambda expressions can now be checked and simplified as follows: # A = lp.parse('(\\x.((\\P.P(x,x))(loves)))(John)') # B = lp.parse(sem(tr)) # for some tree tr # A.simplify() # B.simplify() # Model checker from nltk.sem.logic import * # Can use: A.variable, A.term, A.term.first, A.term.second, A.function, A.args
def closed_domain_demo(): lp = LogicParser() p1 = lp.parse(r'exists x.walk(x)') p2 = lp.parse(r'man(Socrates)') c = lp.parse(r'walk(Socrates)') prover = Prover9Command(c, [p1, p2]) print(prover.prove()) cdp = ClosedDomainProver(prover) print('assumptions:') for a in cdp.assumptions(): print(' ', a) print('goal:', cdp.goal()) print(cdp.prove()) p1 = lp.parse(r'exists x.walk(x)') p2 = lp.parse(r'man(Socrates)') p3 = lp.parse(r'-walk(Bill)') c = lp.parse(r'walk(Socrates)') prover = Prover9Command(c, [p1, p2, p3]) print(prover.prove()) cdp = ClosedDomainProver(prover) print('assumptions:') for a in cdp.assumptions(): print(' ', a) print('goal:', cdp.goal()) print(cdp.prove()) p1 = lp.parse(r'exists x.walk(x)') p2 = lp.parse(r'man(Socrates)') p3 = lp.parse(r'-walk(Bill)') c = lp.parse(r'walk(Socrates)') prover = Prover9Command(c, [p1, p2, p3]) print(prover.prove()) cdp = ClosedDomainProver(prover) print('assumptions:') for a in cdp.assumptions(): print(' ', a) print('goal:', cdp.goal()) print(cdp.prove()) p1 = lp.parse(r'walk(Socrates)') p2 = lp.parse(r'walk(Bill)') c = lp.parse(r'all x.walk(x)') prover = Prover9Command(c, [p1, p2]) print(prover.prove()) cdp = ClosedDomainProver(prover) print('assumptions:') for a in cdp.assumptions(): print(' ', a) print('goal:', cdp.goal()) print(cdp.prove()) p1 = lp.parse(r'girl(mary)') p2 = lp.parse(r'dog(rover)') p3 = lp.parse(r'all x.(girl(x) -> -dog(x))') p4 = lp.parse(r'all x.(dog(x) -> -girl(x))') p5 = lp.parse(r'chase(mary, rover)') c = lp.parse(r'exists y.(dog(y) & all x.(girl(x) -> chase(x,y)))') prover = Prover9Command(c, [p1, p2, p3, p4, p5]) print(prover.prove()) cdp = ClosedDomainProver(prover) print('assumptions:') for a in cdp.assumptions(): print(' ', a) print('goal:', cdp.goal()) print(cdp.prove())
def print_proof(goal, premises): lp = LogicParser() prover = Prover9Command(lp.parse(goal), premises) command = UniqueNamesProver(ClosedWorldProver(prover)) print(goal, prover.prove(), command.prove())
# -*- coding: utf-8 -*- # # Copyright 2015 Pascual Martinez-Gomez # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from nltk.sem.logic import LogicParser logic_parser = LogicParser(type_check=False) def lexpr(formula_str): return logic_parser.parse(formula_str)
set([('Kenneth Lay', 'Jeff Skillings', 'Richard Shapiro', 'Tana Jones', 'Kay Mann', 'Mark Taylor', 'Chris G', 'Kate Syemmes', 'Davis Pete', 'Steven Kean', 'Sara Shackleton', 'James Steffes', 'Jeff Dasovich') ])) ] val2 = nltk.sem.Valuation(v) val3 = nltk.sem.Valuation(v1) print(val2) print(val3) from nltk.sem.logic import LogicParser from nltk.inference import TableauProver dom3 = val3.domain m3 = nltk.sem.Model(dom3, val3) g = nltk.sem.Assignment(dom3) lpq = LogicParser() fmla1 = lpq.parse('(POI(x) -> exists y.(CEO(y) and chase(x, y)))') m3 = m3.satisfiers(fmla1, 'x', g) print(m3) from nltk.sem.drt import * dexpr = DrtExpression.fromstring CEO_a1 = dexpr('CEO(a1)') EMPLOYEES_d1 = dexpr('EMPLOYEES(d1)') x = dexpr('x') print(DRS([x], [CEO_a1, EMPLOYEES_d1])) drs1 = dexpr('([x],[CEO(a1),EMPLOYEES(d1)])') print(drs1) #merge attributes to nodes