예제 #1
0
    def _process_rule(self, a, b):
        # right part first
        if isinstance(b, Logic):
            # a -> b & c    -->  a -> b  ;  a -> c
            # (?) FIXME this is only correct when b & c != null !
            if b.op == '&':
                for barg in b.args:
                    self.process_rule(a, barg)

            # a -> b | c    -->  !b & !c -> !a
            #               -->   a & !b -> c & !b
            #               -->   a & !c -> b & !c
            #
            # NB: the last two rewrites add 1 term, so the rule *grows* in size.
            # NB: without catching terminating conditions this could continue infinitely
            elif b.op == '|':
                # detect tautology first
                if not isinstance(a, Logic):  # Atom
                    # tautology:  a -> a|c|...
                    if a in b.args:
                        raise TautologyDetected(a, b, 'a -> a|c|...')
                self.process_rule(And(*[Not(barg) for barg in b.args]), Not(a))

                for bidx in range(len(b.args)):
                    barg = b.args[bidx]
                    brest = b.args[:bidx] + b.args[bidx + 1:]
                    self.process_rule(And(a, Not(barg)),
                                      And(b.__class__(*brest), Not(barg)))
            else:
                raise ValueError('unknown b.op %r' % b.op)

        # left part
        elif isinstance(a, Logic):
            # a & b -> c    -->  IRREDUCIBLE CASE -- WE STORE IT AS IS
            #                    (this will be the basis of beta-network)
            if a.op == '&':
                assert not isinstance(b, Logic)
                if b in a.args:
                    raise TautologyDetected(a, b, 'a & b -> a')
                self.proved_rules.append((a, b))
                # XXX NOTE at present we ignore  !c -> !a | !b

            elif a.op == '|':
                if b in a.args:
                    raise TautologyDetected(a, b, 'a | b -> a')
                for aarg in a.args:
                    self.process_rule(aarg, b)
            else:
                raise ValueError('unknown a.op %r' % a.op)
        else:
            # both `a` and `b` are atoms
            na, nb = name_not(a), name_not(b)
            self.proved_rules.append((a, b))  # a  -> b
            self.proved_rules.append((nb, na))  # !b -> !a
예제 #2
0
def exclusivity(sort,variants):
    # partial funciton 
    def pto(s):
        return Symbol('*>',RelationSort([sort,s]))
    excs = [partial_function(pto(s)) for s in variants]
    for s in enumerate(variants):
        x,y,z = [Variable(n,s) for n,s in [('X',sort),('Y',sort),('Z',s)]]
        excs.append(Implies(And(pto(s)(x,z),pto(s)(y,z)),Equals(x,y)))
    for i1,s1 in enumerate(variants):
        for s2 in variants[:i1]:
            x,y,z = [Variable(n,s) for n,s in [('X',sort),('Y',s1),('Z',s2)]]
            excs.append(Not(And(pto(s1)(x,y),pto(s2)(x,z))))
    return And(*excs)
예제 #3
0
 def to_constraint(self):
     if isinstance(self.args[1],Some):
         if self.args[1].if_value() != None:
             return And(Implies(self.args[1].args[1],
                                lg.Exists([self.args[1].args[0]],
                                          And(self.args[1].args[1],Equals(self.args[0],self.args[1].if_value())))),
                        Or(lg.Exists([self.args[1].args[0]],self.args[1].args[1]),
                           Equals(self.args[0],self.args[1].else_value())))
         return lg.ForAll([self.args[1].args[0]],
                          Implies(self.args[1].args[1],
                                  lu.substitute(self.args[1].args[1],{self.args[1].args[0]:self.args[0]})))
     if is_individual(self.args[0]):
         return Equals(*self.args)
     return Iff(*self.args)
예제 #4
0
def simp_not(x):
    if isinstance(x, Not):
        return x.args[0]
    if is_true(x):
        return Or()
    if is_false(x):
        return And()
    return Not(x)
예제 #5
0
파일: facts.py 프로젝트: vperic/sympy
    def _process_rule(self, a, b):
        # right part first

        # a -> b & c    -->  a -> b  ;  a -> c
        # (?) FIXME this is only correct when b & c != null !
        if isinstance(b, And):
            for barg in b.args:
                self.process_rule(a, barg)

        # a -> b | c    -->  !b & !c -> !a
        #               -->   a & !b -> c
        #               -->   a & !c -> b
        elif isinstance(b, Or):
            # detect tautology first
            if not isinstance(a, Logic):    # Atom
                # tautology:  a -> a|c|...
                if a in b.args:
                    raise TautologyDetected(a,b, 'a -> a|c|...')
            self.process_rule(And(*[Not(barg) for barg in b.args]), Not(a))

            for bidx in range(len(b.args)):
                barg = b.args[bidx]
                brest= b.args[:bidx] + b.args[bidx+1:]
                self.process_rule(And(a, Not(barg)), Or(*brest))

        # left part

        # a & b -> c    -->  IRREDUCIBLE CASE -- WE STORE IT AS IS
        #                    (this will be the basis of beta-network)
        elif isinstance(a, And):
            if b in a.args:
                raise TautologyDetected(a,b, 'a & b -> a')
            self.proved_rules.append((a,b))
            # XXX NOTE at present we ignore  !c -> !a | !b

        elif isinstance(a, Or):
            if b in a.args:
                raise TautologyDetected(a,b, 'a | b -> a')
            for aarg in a.args:
                self.process_rule(aarg, b)

        else:
            # both `a` and `b` are atoms
            self.proved_rules.append((a,b))     # a  -> b
            self.proved_rules.append((Not(b), Not(a)))   # !b -> !a
예제 #6
0
파일: concept.py 프로젝트: simudream/ivy
    def split(self, concept, split_by):
        """
        concept and split_by are concept names.

        This splits concept into 2 concepts:
        (concept+split_by) and (concept-split_by)
        """
        c1 = self.concepts[concept]
        c2 = self.concepts[split_by]
        variables = c1.variables
        formula_plus = And(c1(*variables), c2(*variables))
        formula_minus = And(c1(*variables), Not(c2(*variables)))
        new_names = '({}+{})'.format(concept, split_by), '({}-{})'.format(concept, split_by)
        new_concepts = Concept(variables, formula_plus), Concept(variables, formula_minus)
        names = self.concepts.keys()
        self.concepts.update(zip(new_names, new_concepts))
        self.concepts = OrderedDict((k, self.concepts[k]) for k in _replace_name(names, concept, new_names))
        self.replace_concept(concept, new_names)
예제 #7
0
def simp_and(x, y):
    if is_true(x):
        return y
    if is_false(x):
        return x
    if is_true(y):
        return x
    if is_false(y):
        return y
    return And(x, y)
예제 #8
0
파일: ivy_logic.py 프로젝트: appcoreopc/ivy
def extensionality(destrs):
    if not destrs:
        return Or()
    c = []
    sort = destrs[0].sort.dom[0]
    x, y = Variable("X", sort), Variable("Y", sort)
    for d in destrs:
        vs = variables(d.sort.dom[1:])
        eqn = Equals(d(*([x] + vs)), d(*([y] + vs)))
        if vs:
            eqn = lg.ForAll(vs, eqn)
        c.append(eqn)
    res = Implies(And(*c), Equals(x, y))
    return res
예제 #9
0
def parse(value):
    class FieldDict(object):
        def __init__(self, e):
            self.e = e

        def __getitem__(self, item):
            return self.e.get(item, Key(item))

    env = {
        'Text': Text,
        'Key': Key,
        'And': And,
        'Or': Or,
        'pytz': pytz,
        'datetime': datetime,
        '_': _
    }
    result = eval(value, env, FieldDict(env))
    if isinstance(result, (tuple, list)):
        result = And(*result)
    return result
예제 #10
0
    def split(self, concept, split_by):
        """
        concept and split_by are concept names.

        This splits concept into 2 concepts:
        (concept+split_by) and (concept-split_by)
        """
        c1 = self.concepts[concept]
        c2 = self.concepts[split_by]
        variables = c1.variables

        if isinstance(c2,ConceptSet):
            formulas = [self.concepts[n](*variables) for n in c2]
            new_names = ['({}+{})'.format(concept,n) for n in c2]
        else:
            formulas = [c2(*variables),Not(c2(*variables))]
            new_names = ['({}+{})'.format(concept, split_by), '({}-{})'.format(concept, split_by)]
        new_concepts = [Concept(n,variables,And(c1.formula,f)) for n,f in zip(new_names,formulas)]
        names = self.concepts.keys()
        self.concepts.update(zip(new_names, new_concepts))
        self.concepts = ConceptDict((k, self.concepts[k]) for k in _replace_name(names, concept, new_names))
        self.replace_concept(concept, new_names)
예제 #11
0
# Enter characters, weapons and rooms
characters = ["Mostarda", "Black", "Violeta", "Marinho", "Rosa", "Branca"]

weapons = ["faca", "castical", "revolver", "corda", "cano", "chave"]

rooms = [
    "hall", "estar", "cozinha", "jantar", "festas", "musica", "jogos",
    "biblioteca", "escritorio"
]

cards = characters + weapons + rooms

# Initialize symbols list and knowledge base
symbols = []

knowledge = And()

# Enter number of players
n_players = 4

# Add another player, the cards of player 0 will be the answer
n_players += 1

# Add cards to symbols list
for card in cards:
    for index in range(n_players):
        symbols.append(Symbol(f"{card}{index}"))

# The answer must contain one person, room, and weapon
knowledge = And(
    Or(Symbol("Mostarda0"), Symbol("Black0"), Symbol("Violeta0"),
예제 #12
0
AKnight = Symbol("A is a Knight")
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

# Puzzle 0
# A says "I am both a knight and a knave."
knowledge0 = And(
    # Structure of the generic problem
    Or(AKnight, AKnave),
    Not(And(AKnight, AKnave)),

    # Information about what the characters said
    Implication(AKnight, And(AKnight, AKnave)),
    Implication(AKnave, Not(And(AKnight, AKnave)))
)

# Puzzle 1
# A says "We are both knaves."
# B says nothing.
knowledge1 = And(
    # Structure of the generic problem
    Or(AKnight, AKnave),
    Or(BKnight, BKnave),
    Not(And(AKnight, AKnave)),
    Not(And(BKnight, BKnave)),
예제 #13
0
from logic import Symbol, And, Or, Implication, Biconditional, Not, model_check

AKnight = Symbol("A is a Knight")
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

OnlyOneKindForEach = And(Or(AKnave, AKnight), Or(BKnight, BKnave),
                         Or(CKnave, CKnight))

# Puzzle 0
# A says "I am both a knight and a knave."
knowledge0 = And(OnlyOneKindForEach, Implication(AKnight, And(AKnight,
                                                              AKnave)))

# Puzzle 1
# A says "We are both knaves."
# B says nothing.

WereBothKnaves = And(BKnave, AKnave)
knowledge1 = And(
    OnlyOneKindForEach,
    Implication(AKnight, WereBothKnaves),
    Implication(AKnave, Not(WereBothKnaves)),
)

# Puzzle 2
예제 #14
0
파일: concept.py 프로젝트: simudream/ivy
def get_standard_combiners():
    T = TopSort()
    UnaryRelation = FunctionSort(T, Boolean)
    BinaryRelation = FunctionSort(T, T, Boolean)
    X, Y, Z = (Var(n, T) for n in ['X', 'Y', 'Z'])
    U = Var('U', UnaryRelation)
    U1 = Var('U1', UnaryRelation)
    U2 = Var('U2', UnaryRelation)
    B = Var('B', BinaryRelation)
    B1 = Var('B1', BinaryRelation)
    B2 = Var('B2', BinaryRelation)
    result = OrderedDict()

    result['none'] = ConceptCombiner([U], Not(Exists([X], U(X))))
    result['at_least_one'] = ConceptCombiner([U], Exists([X], U(X)))
    result['at_most_one'] = ConceptCombiner([U], ForAll([X,Y], Implies(And(U(X), U(Y)), Eq(X,Y))))

    result['node_necessarily'] = ConceptCombiner(
        [U1, U2],
        ForAll([X], Implies(U1(X), U2(X))),
    )
    result['node_necessarily_not'] = ConceptCombiner(
        [U1, U2],
        ForAll([X], Implies(U1(X), Not(U2(X)))),
    )


    result['mutually_exclusive'] = ConceptCombiner(
        [U1, U2],
        ForAll([X, Y], Not(And(U1(X), U2(Y))))
    )

    result['all_to_all'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([X,Y], Implies(And(U1(X), U2(Y)), B(X,Y)))
    )
    result['none_to_none'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([X,Y], Implies(And(U1(X), U2(Y)), Not(B(X,Y))))
    )
    result['total'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([X], Implies(U1(X), Exists([Y], And(U2(Y), B(X,Y)))))
    )
    result['functional'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([X, Y, Z], Implies(And(U1(X), U2(Y), U2(Z), B(X,Y), B(X,Z)), Eq(Y,Z)))
    )
    result['surjective'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([Y], Implies(U2(Y), Exists([X], And(U1(X), B(X,Y)))))
    )
    result['injective'] = ConceptCombiner(
        [B, U1, U2],
        ForAll([X, Y, Z], Implies(And(U1(X), U1(Y), U2(Z), B(X,Z), B(Y,Z)), Eq(X,Y)))
    )

    result['node_info'] = ['none', 'at_least_one', 'at_most_one']
    if False:
        # this just slows us down, and it's not clear it's needed
        # later this should be made customizable by the user
        result['edge_info'] = ['all_to_all', 'none_to_none', 'total',
                               'functional', 'surjective', 'injective']
    else:
        result['edge_info'] = ['all_to_all', 'none_to_none']

    result['node_label'] = ['node_necessarily', 'node_necessarily_not']

    return result
    UnaryRelation = FunctionSort(S, Boolean)
    BinaryRelation = FunctionSort(S, S, Boolean)

    X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z'])
    U = Var('U', UnaryRelation)
    U1 = Var('U1', UnaryRelation)
    U2 = Var('U2', UnaryRelation)
    B = Var('B', BinaryRelation)
    B1 = Var('B1', BinaryRelation)
    B2 = Var('B2', BinaryRelation)

    nstar = Const('nstar', BinaryRelation)
    x = Const('x', S)
    y = Const('y', S)

    c11 = Concept('xy', [X], And(Eq(x, X), Eq(y, X)))
    c10 = Concept('x', [X], And(Eq(x, X), Not(Eq(y, X))))
    c01 = Concept('y', [X], And(Not(Eq(x, X)), Eq(y, X)))
    c00 = Concept('other', [X], And(Not(Eq(x, X)), Not(Eq(y, X))))

    cnstar = Concept('nstar', [X, Y], nstar(X, Y))
    cnplus = Concept('nplus', [X, Y], And(nstar(X, Y), Not(Eq(X, Y))))

    notexists = ConceptCombiner([U], Not(Exists([X], U(X))))
    exists = ConceptCombiner([U], Exists([X], U(X)))
    singleton = ConceptCombiner([U],
                                ForAll([X, Y],
                                       Implies(And(U(X), U(Y)), Eq(X, Y))))
    all_to_all = ConceptCombiner([U1, U2, B],
                                 ForAll([X, Y],
                                        Implies(And(U1(X), U2(Y)), B(X, Y))))
예제 #16
0
파일: concept.py 프로젝트: simudream/ivy
    T = TopSort()
    UnaryRelationS = FunctionSort(S, Boolean)
    BinaryRelationS = FunctionSort(S, S, Boolean)
    UnaryRelationT = FunctionSort(T, Boolean)
    BinaryRelationT = FunctionSort(T, T, Boolean)


    X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z'])

    r = Const('r', BinaryRelationS)
    n = Const('n', BinaryRelationS)
    p = Const('p', UnaryRelationS)
    q = Const('q', UnaryRelationS)
    u = Const('u', UnaryRelationS)

    c11 = Concept([X], And(p(X), q(X)))
    c10 = Concept([X], And(p(X), Not(q(X))))
    c01 = Concept([X], And(Not(p(X)), q(X)))
    c00 = Concept([X], And(Not(p(X)), Not(q(X))))
    cu = Concept([X], u(X))

    crn = Concept([X, Y], Or(r(X,Y), n(X,Y)))

    combiners = get_standard_combiners()
    combinations = get_standard_combinations()

    test('c11')
    test('c10')
    test('c01')
    test('c00')
    test('cu')
예제 #17
0
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

# Puzzle 0
# A says "I am both a knight and a knave."
knowledge0 = And(
    # info from problem
    Or(AKnight, AKnave),
    Not(And(AKnight, AKnight)),
    Not(BKnight),
    Or(BKnight, BKnave),
    And(AKnight, AKnight),
    And(AKnight, Not(AKnave)),
    And(AKnave, Not(AKnight)),
    Not(And(AKnave, AKnight)),
    Implication(AKnight, And(AKnight, AKnave)),
    Implication(AKnave, Not(And(AKnight, AKnave))))

print(knowledge0.formula())

# Puzzle 1
# A says "We are both knaves."
# B says nothing.
knowledge1 = And(
    # info from problem
    Or(AKnight, AKnave),
    Not(And(AKnight, AKnight)),
예제 #18
0
musica = Symbol("musica")
jogos = Symbol("jogos")
biblioteca = Symbol("biblioteca")
escritorio = Symbol("escritorio")

rooms = [
    hall, estar, cozinha, jantar, festas, musica, jogos, biblioteca, escritorio
]

# Initialize symbols list and knowledge base
symbols = characters + weapons + rooms

# The answer must contain one person, room, and weapon
knowledge = And(
    Or(Mostarda, Black, Violeta, Marinho, Rosa, Branca),
    Or(faca, castical, revolver, corda, cano, chave),
    Or(hall, estar, cozinha, jantar, festas, musica, jogos, biblioteca,
       escritorio))

# If one person, room or weapon is in the answer,
# it implicates that the others aren't
"""
for character1 in characters:
    for character2 in characters:
        if character1 != character2:
            knowledge.add(Implication(character1,
                          Not(character2)))

for weapon1 in weapons:
    for weapon2 in weapons:
        if weapon1 != weapon2:
예제 #19
0
def _normalize_facts(facts):
    facts = normalize_quantifiers(And(*facts))
    assert type(facts) is And
    return [f for f in facts if not is_tautology_equality(f)]
예제 #20
0
파일: type_inference.py 프로젝트: e42s/ivy
    BinaryRelationT = FunctionSort(T, T, Boolean)

    XS, YS = (Var(n, S) for n in ['X', 'Y'])
    XT, YT = (Var(n, T) for n in ['X', 'Y'])

    xs, ys = (Const(n, S) for n in ['x', 'y'])
    xt, yt = (Const(n, T) for n in ['x', 'y'])

    rs = Const('r', BinaryRelationS)
    ps = Const('p', UnaryRelationS)
    rt = Const('r', BinaryRelationT)
    pt = Const('p', UnaryRelationT)
    tt = Const('tt', T)
    TT = Var('TT', T)

    f1 = And(ps(XS), ps(xs))
    cf1 = concretize_sorts(f1)
    print repr(f1)
    print repr(cf1)
    assert f1 == cf1
    print

    f2 = And(ps(XT), pt(xs))
    cf2 = concretize_sorts(f2)
    print repr(f2)
    print repr(cf2)
    print

    f3 = Exists([TT], And(ps(XT), TT(xs)))
    cf3 = concretize_sorts(f3)
    print repr(f3)
예제 #21
0
from logic import And, Or, Symbol, Biconditional, Implication, Not, model_check

AKnight = Symbol("A is a Knight")
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

# Puzzle 0
# A says "I am both a knight and a knave."
knowledge0 = And(Or(AKnight, AKnave), Implication(AKnight, Not(AKnave)),
                 Implication(AKnave, Not(AKnight)),
                 Biconditional(AKnight, And(AKnight, AKnave)))

# Puzzle 1
# A says "We are both knaves."
# B says nothing.
knowledge1 = And(Or(AKnight, AKnave), Implication(AKnight, Not(AKnave)),
                 Implication(AKnave, Not(AKnight)), Or(BKnight, BKnave),
                 Implication(BKnight, Not(BKnave)),
                 Implication(BKnave, Not(BKnight)),
                 Biconditional(AKnight, And(AKnave, BKnave)))

# Puzzle 2
# A says "We are the same kind."
# B says "We are of different kinds."
knowledge2 = And(
    Or(AKnight, AKnave), Implication(AKnight, Not(AKnave)),
예제 #22
0
    T = TopSort()
    UnaryRelationS = FunctionSort(S, Boolean)
    BinaryRelationS = FunctionSort(S, S, Boolean)
    UnaryRelationT = FunctionSort(T, Boolean)
    BinaryRelationT = FunctionSort(T, T, Boolean)


    X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z'])

    r = Const('r', BinaryRelationS)
    n = Const('n', BinaryRelationS)
    p = Const('p', UnaryRelationS)
    q = Const('q', UnaryRelationS)
    u = Const('u', UnaryRelationS)

    c11 = Concept('both',[X], And(p(X), q(X)))
    c10 = Concept('onlyp',[X], And(p(X), Not(q(X))))
    c01 = Concept('onlyq',[X], And(Not(p(X)), q(X)))
    c00 = Concept('none',[X], And(Not(p(X)), Not(q(X))))
    cu = Concept('u',[X], u(X))

    crn = Concept('r_or_n',[X, Y], Or(r(X,Y), n(X,Y)))

    combiners = get_standard_combiners()
    combinations = get_standard_combinations()

    test('c11')
    test('c10')
    test('c01')
    test('c00')
    test('cu')
예제 #23
0
 def _to_formula(self):
     return And(self.state, self.axioms,
                *(self.goal_constraints + self.suppose_constraints))
예제 #24
0
def partial_function(rel):
    lsort, rsort = rel.sort.dom
    x, y, z = [
        Variable(n, s) for n, s in [('X', lsort), ('Y', rsort), ('Z', rsort)]
    ]
    return ForAll([x, y, z], Implies(And(rel(x, y), rel(x, z)), Equals(y, z)))
예제 #25
0
                result.append(True)
            else:
                # no caching of unknown results
                print "z3 returned: {}".format(res)
                assert False
                result.append(None)
    return result


if __name__ == '__main__':
    S = UninterpretedSort('S')
    X, Y, Z = (Var(n, S) for n in ['X', 'Y', 'Z'])
    BinRel = FunctionSort(S, S, Boolean)
    leq = Const('leq', BinRel)
    transitive1 = ForAll((X, Y, Z),
                         Implies(And(leq(X, Y), leq(Y, Z)), leq(X, Z)))
    transitive2 = ForAll((X, Y, Z),
                         Or(Not(leq(X, Y)), Not(leq(Y, Z)), leq(X, Z)))
    transitive3 = Not(
        Exists((X, Y, Z), And(leq(X, Y), leq(Y, Z), Not(leq(X, Z)))))
    antisymmetric = ForAll((X, Y),
                           Implies(And(leq(X, Y), leq(Y, X), true), Eq(Y, X)))

    print z3_implies(transitive1, transitive2)
    print z3_implies(transitive2, transitive3)
    print z3_implies(transitive3, transitive1)
    print z3_implies(transitive3, antisymmetric)
    print

    print z3_implies(true, Iff(transitive1, transitive2))
    print
예제 #26
0
AKnight = Symbol("A is a Knight")
AKnave = Symbol("A is a Knave")

BKnight = Symbol("B is a Knight")
BKnave = Symbol("B is a Knave")

CKnight = Symbol("C is a Knight")
CKnave = Symbol("C is a Knave")

# Puzzle 0
# A says "I am both a knight and a knave."
knowledge0 = And(
    #Puzzle constraints, a person must be either a Knigh or a Knave, not both
    And(Or(AKnight, AKnave), Not(And(AKnight, AKnave))),

    #Suposing that A is Knight
    Implication(AKnight, And(AKnight, AKnave)),
    #Suposing that A is Knave
    Implication(AKnave, Or(Not(AKnight), Not(AKnave))))

# Puzzle 1
# A says "We are both knaves."
# B says nothing.
knowledge1 = And(And(Or(AKnight, AKnave), Not(And(AKnight, AKnave))),
                 And(Or(BKnight, BKnave), Not(And(BKnight, BKnave))),
                 Implication(AKnight, And(AKnave, BKnave)),
                 Implication(AKnave, Not(And(AKnave, BKnave))))

# Puzzle 2
# A says "We are the same kind."
# B says "We are of different kinds."