예제 #1
0
    def test_cnf_negation(self):
        '''
        Ensure we can get into conjunctive normal form
        '''

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        delta = Predicate('D', ['z'])

        s = ~(Universal(['x', 'y', 'z'], (~(alpha | beta) & delta)))
        self.assertEqual(repr(s.push_complete()),
                         "∃(x,y,z)[(A(x) | B(y) | ~D(z))]")
        s = ~(Universal(['x', 'y', 'z'], ~((alpha | beta) & delta)))
        self.assertEqual(repr(s.push_complete()),
                         "∃(x,y,z)[((A(x) | B(y)) & D(z))]")

        s = ~((~alpha | ~beta) & ~delta)
        self.assertEqual(repr(s.push_complete()), "((A(x) & B(y)) | D(z))")

        ## Test to make sure the recursino into nested stuff actually work
        s = (~~~~~~~~~alpha).push_complete()
        self.assertEqual(repr(s), '~A(x)')

        s = (~~~~~~~~alpha).push_complete()
        self.assertEqual(repr(s), 'A(x)')
예제 #2
0
    def test_distribution(self):
        '''
        Ensure that distribution over conjunctions work
        '''
        #(b & (a | (c & b)))

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        charlie = Predicate('C', ['t'])
        delta = Predicate('D', ['z'])

        s = delta | (alpha & beta)
        ret = s.distribute(s.terms[0], s.terms[1])
        self.assertEqual(repr(ret), '((D(z) | A(x)) & (D(z) | B(y)))')

        s = (alpha | beta) & delta
        ret = s.distribute(s.terms[0], s.terms[1])
        self.assertEqual(repr(ret), '((D(z) & A(x)) | (D(z) & B(y)))')

        s = (alpha | beta) & (beta | delta)
        ret = s.distribute(s.terms[0], s.terms[1])
        self.assertEqual(repr(ret),
                         '(((A(x) | B(y)) & B(y)) | ((A(x) | B(y)) & D(z)))')

        # Simple case - single distribute
        s = beta | (alpha & (delta | charlie))
        ret = s.distribute(s.terms[0], s.terms[1])
        self.assertEqual('((B(y) | A(x)) & (B(y) | D(z) | C(t)))', repr(ret))

        # Slightly more complex
        s = (beta & charlie) | (alpha & (delta | charlie))
        ret = s.distribute(s.terms[0], s.terms[1])
        self.assertEqual(
            '(((B(y) & C(t)) | A(x)) & ((B(y) & C(t)) | D(z) | C(t)))',
            repr(ret))
예제 #3
0
    def test_connective_to_onf(self):

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        charlie = Predicate('C', ['u'])
        delta = Predicate('D', ['z'])

        # Trivial case -- already in CNF
        two = (beta | alpha) & (delta)
        self.assertEqual(repr(two.to_onf()), '((B(y) | A(x)) & D(z))')

        two = (beta & alpha) | (delta)
        self.assertEqual(repr(two.to_onf()), '((D(z) | B(y)) & (D(z) | A(x)))')

        # Reversed case
        two = (delta) | (beta & alpha)
        self.assertEqual(repr(two.to_onf()), '((D(z) | B(y)) & (D(z) | A(x)))')

        # Nested distribution
        one = (alpha & beta) | (charlie & delta)
        self.assertEqual(
            repr(one.to_onf()),
            '((A(x) | C(u)) & (A(x) | D(z)) & (B(y) | C(u)) & (B(y) | D(z)))')

        # Nested distribution
        one = (alpha | (beta & (charlie | (delta & alpha))))
        self.assertEqual(
            repr(one.to_onf()),
            '((A(x) | B(y)) & (C(u) | A(x) | D(z)) & (C(u) | A(x) | A(x)))')
예제 #4
0
    def test_axiom_to_pcnf(self):
        a = Predicate('A', ['x'])
        b = Predicate('B', ['y'])
        c = Predicate('C', ['z'])

        # Simple test of disjunction over conjunction
        axi_one = Axiom(Universal(['x', 'y', 'z'], a | b & c))
        axi_one = axi_one.ff_pcnf()
        self.assertEqual('∀(z,y,x)[((A(z) | B(y)) & (A(z) | C(x)))]',
                         repr(axi_one))

        # Test recursive distribution

        #axi_one = Axiom(Universal(['x','y','z'], a | (b & (a | (c & b)))))
        #print(repr(axi_one))
        #self.assertEqual('', repr(axi_one.to_pcnf()))

        # Simple sanity check, it's already FF-PCNF
        axi_two = Axiom(Universal(['x', 'y', 'z'], (a | b) & c))
        axi_two = axi_two.ff_pcnf()
        self.assertEqual('∀(z,y,x)[(C(x) & (A(z) | B(y)))]', repr(axi_two))

        # Sanity check we remove functions
        c = Predicate('C', ['z', Function('F', ['z'])])
        axi_three = Axiom(Universal(['x', 'y', 'z'], a | b & c))
        axi_three = axi_three.ff_pcnf()
        self.assertEqual(
            '∀(z,y,x,w)[((A(z) | C(x,w) | ~F(x,w)) & (A(z) | B(y)))]',
            repr(axi_three))
예제 #5
0
    def test_axiom_connecive_rescoping(self):

        a = Predicate('A', ['x'])
        b = Predicate('B', ['y'])

        universal = Universal(['x'], a)
        existential = Existential(['y'], b)

        conjunction = universal & existential
        disjunction = universal | existential

        # Ensure we handle single quantifier case
        self.assertEqual(repr((universal & b).rescope()),
                         '∀(x)[(A(x) & B(y))]')
        self.assertEqual(repr((existential & a).rescope()),
                         '∃(y)[(B(y) & A(x))]')
        self.assertEqual(repr((universal | b).rescope()),
                         '∀(x)[(A(x) | B(y))]')
        self.assertEqual(repr((existential | a).rescope()),
                         '∃(y)[(B(y) | A(x))]')

        # Ensure we catch error condition where lookahead is needed
        self.assertRaises(ValueError, (existential | universal).rescope)

        # Ensure that we can promote Universals when a conjunction lives above us
        top = a & disjunction
        self.assertEqual(repr(disjunction.rescope(top)),
                         '∀(x)[∃(y)[(A(x) | B(y))]]')

        # Ensure that we can promote Existentials when a conjunction lives above us
        top = a | conjunction
        self.assertEqual(repr(conjunction.rescope(top)),
                         '∃(y)[∀(x)[(B(y) & A(x))]]')
예제 #6
0
    def test_axiom_function_replacement(self):
        f = Function('f', ['x'])
        t = Function('t', ['y'])
        a = Predicate('A', [f])
        b = Predicate('B', [f, t])

        axi = Axiom(Universal(['x'], a | a & a))
        self.assertEqual(repr(axi), '∀(x)[(A(f(x)) | (A(f(x)) & A(f(x))))]')

        axi = Axiom(Universal(['x', 'y'], b))
예제 #7
0
    def test_owl_subclass(self):
        a = Predicate('A', ['x'])
        b = Predicate('B', ['x'])
        c = Predicate('C', ['x'])
        d = Predicate('D', ['x'])
        subclass_relation = Axiom(Universal(['x'],  ~d | b | c))

        onto = Ontology("Derp")
        onto.axioms.append(subclass_relation)
        print(onto.to_owl())
예제 #8
0
    def test_conjunction_form(self):
        """
        Ensure basic & operator overloading is working
        """

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['x', 'y'])
        delta = Predicate('D', ['z'])

        self.assertEqual(repr(alpha & beta), '(A(x) & B(x,y))')
        self.assertEqual(repr(alpha & beta & delta), '(A(x) & B(x,y) & D(z))')
예제 #9
0
    def test_disjunction_form(self):
        '''
        Ensure basic | operator overloading is working
        '''

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['x', 'y'])
        delta = Predicate('D', ['z'])

        self.assertEqual(repr(alpha | beta), '(A(x) | B(x,y))')
        self.assertEqual(repr(alpha | beta | delta), '(A(x) | B(x,y) | D(z))')
예제 #10
0
    def test_axion_to_tptp(self):
        a = Predicate('A', ['x'])
        b = Predicate('B', ['y'])
        c = Predicate('C', ['z'])
        d = Predicate('D', ['u'])

        axiom_one = Axiom(Universal(['x', 'y', 'z', 'u'], ~a | ~d | b | c))
        axiom_two = Axiom(Universal(['x', 'y', 'z', 'u'], ~a | ~d | b | c))

        print()
        print(axiom_one.to_tptp())
        print(axiom_two.to_tptp())
예제 #11
0
    def test_can_filter_axioms(self):

        a = Predicate('A', ['x'])
        b = Predicate('B', ['x'])

        simple_subclass = Axiom(Universal(['x'], ~a | b))
        simple_disjoint = Axiom(Universal(['x'], ~a | ~b))

        matching_patterns = Filter.filter_axiom(simple_subclass)
        self.assertTrue(Pattern.subclass_relation in matching_patterns)
        not_matching = Filter.filter_axiom(simple_disjoint)
        self.assertFalse(Pattern.subclass_relation in not_matching)
예제 #12
0
    def test_cnf_quantifier_simplfy(self):

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])

        uni_one = Universal(['x'], alpha)
        mixer = uni_one | beta
        uni_two = Universal(['y'], mixer)

        uni_nested = Universal(['z'], alpha & (beta | (alpha & uni_one)))
        self.assertEqual('∀(z)[(A(x) & (B(y) | (A(x) & ∀(x)[A(x)])))]',
                         repr(uni_nested))
        self.assertEqual('∀(z,x)[(A(x) & (B(y) | (A(x) & A(x))))]',
                         repr(uni_nested.simplify()))

        self.assertEqual(repr(uni_two), "∀(y)[(∀(x)[A(x)] | B(y))]")
        self.assertEqual(repr(uni_two.simplify()), "∀(y,x)[(B(y) | A(x))]")
예제 #13
0
    def test_axiom_variable_standardize(self):

        a = Predicate('A', ['x'])
        b = Predicate('B', ['y', 'x'])
        c = Predicate('C', ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])

        axi = Axiom(Universal(['x'], a | a & a))
        self.assertEqual(repr(axi.standardize_variables()),
                         '∀(z)[(A(z) | (A(z) & A(z)))]')

        axi = Axiom(Universal(['x', 'y'], b))
        self.assertEqual(repr(axi.standardize_variables()), '∀(z,y)[B(y,z)]')

        axi = Axiom(
            Existential(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], c))
        self.assertEqual(repr(axi.standardize_variables()),
                         '∃(z,y,x,w,v,u,t,s,r)[C(z,y,x,w,v,u,t,s,r)]')
예제 #14
0
    def test_axiom_simple_function_replacement(self):
        f = Function('f', ['x'])
        t = Function('t', ['y'])
        p = Function('p', ['z'])
        a = Predicate('A', [f, t, p])
        b = Predicate('B', [f, t])
        c = Predicate('C', [f])

        axi = Axiom(Universal(['x', 'y', 'z'], a))
        #self.assertEqual(repr(axi.substitute_functions()), '∀(x,y,z)[∀(f2,t3,p4)[(A(f2,t3,p4) | ~(f(x,f2) & t(y,t3) & p(z,p4)))]]')

        axi = Axiom(Universal([
            'x',
        ], ~c))
        #self.assertEqual(repr(axi.substitute_functions()), '∀(x)[~~∀(f5)[(C(f5) | ~f(x,f5))]]')

        #c = Predicate('C', [Function('f', [Function('g', [Function('h', ['x'])])])])
        axi = Axiom(Universal(['x'], c))
예제 #15
0
    def test_mixed_form(self):
        '''
        Ensure that the &  and | operators work when chained
        '''

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['x', 'y'])
        delta = Predicate('D', ['z'])

        self.assertEqual(repr((alpha & beta) | delta),
                         '((A(x) & B(x,y)) | D(z))')
        self.assertEqual(repr(alpha & (beta | delta)),
                         '(A(x) & (B(x,y) | D(z)))')

        self.assertEqual(repr((alpha & beta) | (alpha & delta)),
                         '((A(x) & B(x,y)) | (A(x) & D(z)))')
        self.assertEqual(repr((alpha | beta) & (alpha | delta)),
                         '((A(x) | B(x,y)) & (A(x) | D(z)))')
예제 #16
0
    def test_quantifiers(self):

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        delta = Predicate('D', ['z'])

        uni = Universal(['x', 'y', 'z'], alpha | beta | delta)
        exi = Existential(['x', 'y', 'z'], alpha & beta & delta)

        self.assertEqual(repr(uni), "∀(x,y,z)[(A(x) | B(y) | D(z))]")
        self.assertEqual(repr(exi), "∃(x,y,z)[(A(x) & B(y) & D(z))]")

        self.assertEqual(repr(~uni), "~∀(x,y,z)[(A(x) | B(y) | D(z))]")
        self.assertEqual(repr(~exi), "~∃(x,y,z)[(A(x) & B(y) & D(z))]")

        self.assertEqual(repr((~uni).push()),
                         "∃(x,y,z)[~(A(x) | B(y) | D(z))]")
        self.assertEqual(repr((~exi).push()),
                         "∀(x,y,z)[~(A(x) & B(y) & D(z))]")
예제 #17
0
    def test_axiom_quantifier_coalesence(self):

        a = Predicate('A', ['x'])
        b = Predicate('B', ['y'])

        universal = Universal(['x'], a)
        universal_two = Universal(['y'], b)
        existential = Existential(['y'], b)
        existential_two = Existential(['x'], a)

        # Reduce over conjunction should coalesce Universals and merge existentials
        conjunction = universal & universal_two & existential & existential_two
        self.assertEqual(repr(conjunction.coalesce()),
                         '(∀(x)[(B(x) & A(x))] & ∃(y,x)[(B(y) & A(x))])')

        # Reduce over disjunction should coealesce Existentials and merge Universals
        disjunction = universal | universal_two | existential | existential_two
        self.assertEqual(repr(disjunction.coalesce()),
                         '(∃(y)[(A(y) | B(y))] | ∀(x,y)[(A(x) | B(y))])')
예제 #18
0
    def test_cnf_quantifier_scoping(self):

        a = Predicate('A', ['x'])
        b = Predicate('B', ['y'])
        c = Predicate('C', ['z'])

        e = Existential(['x'], a)
        u = Universal(['y'], b)

        # Test the effect over an OR
        self.assertEqual('∃(x)[(A(x) | B(y))]', repr((e | b).rescope()))
        self.assertEqual('∀(y)[(B(y) | A(x))]', repr((u | a).rescope()))

        # Test the effect over an AND
        self.assertEqual('∃(x)[(A(x) & B(y))]', repr((e & b).rescope()))
        self.assertEqual('∀(y)[(B(y) & A(x))]', repr((u & a).rescope()))

        # Test with more than two to make sure things aren't dropped
        self.assertEqual('∀(y)[(B(y) & (A(x) | C(z) | B(y)))]',
                         repr((u & (a | c | b)).rescope()))
예제 #19
0
    def test_negation(self):
        '''
        Ensure we can get into conjunctive normal form
        '''

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        delta = Predicate('D', ['z'])

        s = alpha | beta
        self.assertEqual(repr(~s), "~(A(x) | B(y))")

        s = alpha & beta
        self.assertEqual(repr(~s), "~(A(x) & B(y))")

        s = alpha & beta
        self.assertEqual(repr((~s).push()), "(~A(x) | ~B(y))")

        s = alpha | beta
        self.assertEqual(repr((~s).push()), "(~A(x) & ~B(y))")

        s = (alpha | beta) & delta
        self.assertEqual(repr((~s).push()), "(~(A(x) | B(y)) | ~D(z))")
예제 #20
0
    def substitute_functions(self):
        """
        Recurse over the contained logical replacing any nested functions with
        new predicates.
        """

        functions = []
        ret_object = copy.deepcopy(self.sentence)
        axiom = Axiom(Util.dfs_functions(ret_object, functions, None))

        # Form explicit function declaration to keep tight logical equivalence
        declarations = []
        unique_functions = {f.name for f in functions if len(f.variables) == 2}

        for function in unique_functions:
            LOGGER.debug('Adding function declaration on: {}'.format(function))
            term_one = ~(Predicate(function, ['a', 'b']))
            term_two = ~(Predicate(function, ['a', 'c']))
            equality = Predicate('=', ['c', 'b'])
            sentence = Universal(['a', 'b', 'c'],
                                 term_one | term_two | equality)
            declarations.append(Axiom(sentence))

        return axiom, declarations
예제 #21
0
    def test_onf_detection(self):

        alpha = Predicate('A', ['x'])
        beta = Predicate('B', ['y'])
        delta = Predicate('D', ['z'])

        uni = Universal(['x', 'y', 'z'], alpha | beta | delta)
        exi = Existential(['x', 'y', 'z'], alpha & beta | delta)

        self.assertEqual(alpha.is_onf(), True)
        self.assertEqual((alpha | beta).is_onf(), True)
        self.assertEqual((alpha & beta).is_onf(), True)
        self.assertEqual((alpha | (beta & delta)).is_onf(), False)
        self.assertEqual((alpha & (beta | delta)).is_onf(), True)
        self.assertEqual((~(alpha | beta)).is_onf(), False)
        self.assertEqual((~(alpha & beta)).is_onf(), False)

        self.assertEqual(uni.is_onf(), True)
        self.assertEqual(exi.is_onf(), False)

        # Note that is_onf() is not a recursive call, it's a top level feature
        # If will actually if you need an ONF axiom then create a Logical.Axiom and to_onf()
        self.assertEqual((alpha & (alpha | (beta & delta)) & delta).is_onf(),
                         False)
예제 #22
0
파일: utilities.py 프로젝트: Fxhnd/macleod
def prenex_parser(logical, prenex, parent):
    """
    DFS through a prenex accumulating each quantifier in the [prenex] list.
    Order is important.
    """

    if isinstance(logical, Quantifier):
        LOGGER.debug("Adding to the quantifier")

        prenex.append(logical)
        prenex_parser(logical.get_term()[0], prenex, logical)

    else:

        # Hit the bottom of the prenex, insert a dummy Predicate
        null = Predicate("Null", ['null'])

        if parent is not None:
            parent.set_term(null)

        return
예제 #23
0
    def test_can_match_subclass_pattern(self):

        # Simple sanity check
        a = Predicate('A', ['x'])
        b = Predicate('B', ['x'])

        simple = Axiom(Universal(['x'], ~a | b))
        match = Pattern.subclass_relation(simple)
        self.assertIsNotNone(match)
        self.assertEqual(match[1].pop(), a)
        self.assertEqual(match[2].pop(), b)

        # Check against longer disjunctions
        a = Predicate('A', ['x'])
        b = Predicate('B', ['x'])
        c = Predicate('C', ['x'])
        d = Predicate('D', ['x'])

        ext = Axiom(Universal(['x'], ~a | ~b | c | d))
        match = Pattern.subclass_relation(ext)
        self.assertIsNotNone(match)
        self.assertEqual(match[1], [a, b])
        self.assertEqual(match[2], [c, d])
예제 #24
0
def p_predicate(p):
    """
    predicate : LPAREN NONLOGICAL parameter RPAREN
    """

    p[0] = Predicate(p[2], p[3])