Exemple #1
0
    def testInductList(self):
        Ta = TVar("a")
        Tlista = Type("list", Ta)
        list_ext = induct.add_induct_type(
            "list", ["a"], [("nil", Tlista, []), ("cons", TFun(Ta, Tlista, Tlista), ["x", "xs"])])

        nil = Const("nil", Tlista)
        cons = Const("cons", TFun(Ta, Tlista, Tlista))
        x = Var("x", Ta)
        xs = Var("xs", Tlista)
        x2 = Var("x'", Ta)
        xs2 = Var("xs'", Tlista)
        P = Var("P", TFun(Tlista, boolT))
        xlist = Var("x", Tlista)

        res = [
            AxType("list", 1),
            AxConstant("nil", Tlista),
            AxConstant("cons", TFun(Ta, Tlista, Tlista)),
            Theorem("list_nil_cons_neq", Thm([], logic.neg(eq(nil, cons(x, xs))))),
            Theorem("list_cons_inject", Thm([], imp(eq(cons(x, xs), cons(x2, xs2)), conj(eq(x, x2), eq(xs, xs2))))),
            Theorem("list_induct", Thm([], imp(P(nil), all(x, all(xs, imp(P(xs), P(cons(x, xs))))), P(xlist)))),
            Attribute("list_induct", "var_induct")
        ]
        self.assertEqual(list_ext.data, res)
Exemple #2
0
    def testCheckedExtend(self):
        """Checked extension: adding an axiom."""
        thy = Theory.EmptyTheory()
        thy_ext = TheoryExtension()

        id_simps = Term.mk_equals(Comb(Const("id", TFun(Ta,Ta)),x), x)
        thy_ext.add_extension(Theorem("id.simps", Thm([], id_simps)))

        ext_report = thy.checked_extend(thy_ext)
        self.assertEqual(thy.get_theorem("id.simps"), Thm([], id_simps))
        self.assertEqual(ext_report.get_axioms(), [("id.simps", Thm([], id_simps))])
Exemple #3
0
def add_induct_predicate(name, T, props):
    """Add the given inductive predicate.

    The inductive predicate is specified by the name and type of
    the predicate, and a list of introduction rules, where each
    introduction rule must be given a name.

    """
    exts = TheoryExtension()
    exts.add_extension(AxConstant(name, T))

    for th_name, prop in props:
        exts.add_extension(Theorem(th_name, Thm([], prop)))
        exts.add_extension(Attribute(th_name, "hint_backward"))

    # Case rule
    Targs, _ = T.strip_type()
    vars = []
    for i, Targ in enumerate(Targs):
        vars.append(Var("_a" + str(i + 1), Targ))

    P = Var("P", boolT)
    pred = Const(name, T)
    assum0 = pred(*vars)
    assums = []
    for th_name, prop in props:
        As, C = prop.strip_implies()
        assert C.head == pred, "add_induct_predicate: wrong form of prop."
        eq_assums = [
            Term.mk_equals(var, arg) for var, arg in zip(vars, C.args)
        ]
        assum = Term.mk_implies(*(eq_assums + As), P)
        prop_vars = term.get_vars(prop)
        for var in reversed(term.get_vars(prop)):
            assum = Term.mk_all(var, assum)
        assums.append(assum)

    prop = Term.mk_implies(*([assum0] + assums + [P]))
    exts.add_extension(Theorem(name + "_cases", Thm([], prop)))

    return exts
Exemple #4
0
    def testInductAdd(self):
        nat = Type("nat")
        plus = Const("plus", TFun(nat, nat, nat))
        zero = Const("zero", nat)
        S = Const("Suc", TFun(nat, nat))
        m = Var("m", nat)
        n = Var("n", nat)

        ext = induct.add_induct_def(
            'plus', TFun(nat, nat, nat), [
                eq(plus(zero, n), n),
                eq(plus(S(m), n), S(plus(m, n)))])
        
        res = [
            AxConstant("plus", TFun(nat, nat, nat)),
            Theorem("plus_def_1", Thm([], eq(plus(zero, n), n))),
            Attribute("plus_def_1", "hint_rewrite"),
            Theorem("plus_def_2", Thm([], eq(plus(S(m), n), S(plus(m, n))))),
            Attribute("plus_def_2", "hint_rewrite"),
        ]
        self.assertEqual(ext.data, res)
Exemple #5
0
    def testInductPredicate(self):
        nat = Type("nat")
        even = Const("even", TFun(nat, boolT))
        zero = Const("zero", nat)
        Suc = Const("Suc", TFun(nat, nat))
        n = Var("n", nat)
        prop_zero = even(zero)
        prop_Suc = Term.mk_implies(even(n), even(Suc(Suc(n))))
        data = [("even_zero", prop_zero), ("even_Suc", prop_Suc)]
        even_ext = induct.add_induct_predicate("even", TFun(nat, boolT), data)
        a1 = Var("_a1", nat)
        P = Var("P", boolT)

        res = [
            AxConstant("even", TFun(nat, boolT)),
            Theorem("even_zero", Thm([], even(zero))),
            Attribute("even_zero", "hint_backward"),
            Theorem("even_Suc", Thm.mk_implies(even(n), even(Suc(Suc(n))))),
            Attribute("even_Suc", "hint_backward"),
            Theorem("even_cases", Thm.mk_implies(even(a1), imp(eq(a1,zero), P), all(n, imp(eq(a1,Suc(Suc(n))), even(n), P)), P))
        ]
        self.assertEqual(even_ext.data, res)
Exemple #6
0
    def testPrintTheoryExtension(self):
        thy_ext = TheoryExtension()

        id_const = Const("id", TFun(Ta, Ta))
        id_def = Abs("x", Ta, Bound(0))
        id_simps = Term.mk_equals(id_const(x), x)

        thy_ext.add_extension(Constant("id", id_def))
        thy_ext.add_extension(Theorem("id.simps", Thm([], id_simps)))

        str_thy_ext = "\n".join(
            ["Constant id = %x. x", "Theorem id.simps: |- equals (id x) x"])

        self.assertEqual(str(thy_ext), str_thy_ext)
Exemple #7
0
    def testInductProd(self):
        Ta = TVar("a")
        Tb = TVar("b")
        Tab = Type("prod", Ta, Tb)
        prod_ext = induct.add_induct_type(
            "prod", ["a", "b"], [("Pair", TFun(Ta, Tb, Tab), ["a", "b"])])

        a = Var("a", Ta)
        b = Var("b", Tb)
        a2 = Var("a'", Ta)
        b2 = Var("b'", Tb)
        pair = Const("Pair", TFun(Ta, Tb, Tab))
        P = Var("P", TFun(Tab, boolT))
        x = Var("x", Tab)

        res = [
            AxType("prod", 2),
            AxConstant("Pair", TFun(Ta, Tb, Tab)),
            Theorem("prod_Pair_inject", Thm([], imp(eq(pair(a, b), pair(a2, b2)), conj(eq(a, a2), eq(b, b2))))),
            Theorem("prod_induct", Thm([], imp(all(a, all(b, P(pair(a, b)))), P(x)))),
            Attribute("prod_induct", "var_induct")
        ]
        self.assertEqual(prod_ext.data, res)
Exemple #8
0
    def testInductNat(self):
        nat = Type("nat")
        nat_ext = induct.add_induct_type(
            "nat", [], [("zero", nat, []), ("Suc", TFun(nat, nat), ["n"])])
        
        zero = Const("zero", nat)
        S = Const("Suc", TFun(nat, nat))
        n = Var("n", nat)
        n2 = Var("n'", nat)
        x = Var("x", nat)
        P = Var("P", TFun(nat, boolT))

        res = [
            AxType("nat", 0),
            AxConstant("zero", nat),
            AxConstant("Suc", TFun(nat, nat)),
            Theorem("nat_zero_Suc_neq", Thm([], logic.neg(eq(zero, S(n))))),
            Theorem("nat_Suc_inject", Thm([], imp(eq(S(n), S(n2)), eq(n, n2)))),
            Theorem("nat_induct", Thm([], imp(P(zero), all(n, imp(P(n), P(S(n)))), P(x)))),
            Attribute("nat_induct", "var_induct")
        ]

        self.assertEqual(nat_ext.data, res)
Exemple #9
0
    def testUncheckedExtend(self):
        """Unchecked extension."""
        thy = Theory.EmptyTheory()
        thy_ext = TheoryExtension()

        id_const = Const("id", TFun(Ta,Ta))
        id_def = Abs("x", Ta, Bound(0))
        id_simps = Term.mk_equals(id_const(x), x)

        thy_ext.add_extension(Constant("id", id_def))        
        thy_ext.add_extension(Theorem("id.simps", Thm([], id_simps)))

        self.assertEqual(thy.unchecked_extend(thy_ext), None)
        self.assertEqual(thy.get_term_sig("id"), TFun(Ta, Ta))
        self.assertEqual(thy.get_theorem("id_def"), Thm.mk_equals(id_const, id_def))
        self.assertEqual(thy.get_theorem("id.simps"), Thm([], id_simps))
Exemple #10
0
    def testCheckedExtend2(self):
        """Checked extension: proved theorem."""
        thy = Theory.EmptyTheory()
        thy_ext = TheoryExtension()

        id_const = Const("id", TFun(Ta,Ta))
        id_def = Abs("x", Ta, Bound(0))
        id_simps = Term.mk_equals(id_const(x), x)

        # Proof of |- id x = x from |- id = (%x. x)
        prf = Proof()
        prf.add_item(0, "theorem", args="id_def")  # id = (%x. x)
        prf.add_item(1, "reflexive", args=x)  # x = x
        prf.add_item(2, "combination", prevs=[0, 1])  # id x = (%x. x) x
        prf.add_item(3, "beta_conv", args=id_def(x))  # (%x. x) x = x
        prf.add_item(4, "transitive", prevs=[2, 3])  # id x = x

        thy_ext.add_extension(Constant("id", id_def))
        thy_ext.add_extension(Theorem("id.simps", Thm([], id_simps), prf))

        ext_report = thy.checked_extend(thy_ext)
        self.assertEqual(thy.get_theorem("id.simps"), Thm([], id_simps))
        self.assertEqual(ext_report.get_axioms(), [])
Exemple #11
0
def add_induct_def(name, T, eqs):
    """Add the given inductive definition.

    The inductive definition is specified by the name and type of
    the constant, and a list of equations.

    For example, addition on natural numbers is specified by:
    ('plus', nat => nat => nat,
     [(plus(0,n) = n, plus(Suc(m), n) = Suc(plus(m, n)))]).

    Multiplication on natural numbers is specified by:
    ('times', nat => nat => nat,
    [(times(0,n) = 0, times(Suc(m), n) = plus(n, times(m,n)))]).

    """
    exts = TheoryExtension()
    exts.add_extension(AxConstant(name, T))

    for i, prop in enumerate(eqs):
        th_name = name + "_def_" + str(i + 1)
        exts.add_extension(Theorem(th_name, Thm([], prop)))
        exts.add_extension(Attribute(th_name, "hint_rewrite"))

    return exts
Exemple #12
0
def add_induct_type(name, targs, constrs):
    """Add the given inductive type to the theory.
    
    The inductive type is specified by name, arity (as list of default
    names of type arguments), and a list of constructors (triple
    consisting of name of the constant, type of the constant, and a
    list of suggested names of the arguments).

    For example, the natural numbers is specified by:
    (nat, [], [(0, nat, []), (Suc, nat => nat, ["n"])]).

    List type is specified by:
    (list, ["a"], [(nil, 'a list, []), (cons, 'a => 'a list => 'a list, ["x", "xs"])]).

    """
    exts = TheoryExtension()

    # Add to type and term signature.
    exts.add_extension(AxType(name, len(targs)))
    for cname, cT, _ in constrs:
        exts.add_extension(AxConstant(cname, cT))

    # Add non-equality theorems.
    for (cname1, cT1, vars1), (cname2, cT2,
                               vars2) in itertools.combinations(constrs, 2):
        # For each A x_1 ... x_m and B y_1 ... y_n, get the theorem
        # ~ A x_1 ... x_m = B y_1 ... y_n.
        argT1, _ = cT1.strip_type()
        argT2, _ = cT2.strip_type()
        lhs_vars = [Var(nm, T) for nm, T in zip(vars1, argT1)]
        rhs_vars = [Var(nm, T) for nm, T in zip(vars2, argT2)]
        A = Const(cname1, cT1)
        B = Const(cname2, cT2)
        lhs = A(*lhs_vars)
        rhs = B(*rhs_vars)
        neq = logic.neg(Term.mk_equals(lhs, rhs))
        th_name = name + "_" + cname1 + "_" + cname2 + "_neq"
        exts.add_extension(Theorem(th_name, Thm([], neq)))

    # Add injectivity theorems.
    for cname, cT, vars in constrs:
        # For each A x_1 ... x_m with m > 0, get the theorem
        # A x_1 ... x_m = A x_1' ... x_m' --> x_1 = x_1' & ... & x_m = x_m'
        if vars:
            argT, _ = cT.strip_type()
            lhs_vars = [Var(nm, T) for nm, T in zip(vars, argT)]
            rhs_vars = [Var(nm + "'", T) for nm, T in zip(vars, argT)]
            A = Const(cname, cT)
            assum = Term.mk_equals(A(*lhs_vars), A(*rhs_vars))
            concls = [
                Term.mk_equals(var1, var2)
                for var1, var2 in zip(lhs_vars, rhs_vars)
            ]
            concl = logic.mk_conj(*concls) if len(concls) > 1 else concls[0]
            th_name = name + "_" + cname + "_inject"
            exts.add_extension(Theorem(th_name, Thm.mk_implies(assum, concl)))

    # Add the inductive theorem.
    tvars = [TVar(targ) for targ in targs]
    T = Type(name, *tvars)
    var_P = Var("P", TFun(T, boolT))
    ind_assums = []
    for cname, cT, vars in constrs:
        A = Const(cname, cT)
        argT, _ = cT.strip_type()
        args = [Var(nm, T2) for nm, T2 in zip(vars, argT)]
        C = var_P(A(*args))
        As = [var_P(Var(nm, T2)) for nm, T2 in zip(vars, argT) if T2 == T]
        ind_assum = Term.mk_implies(*(As + [C]))
        for arg in reversed(args):
            ind_assum = Term.mk_all(arg, ind_assum)
        ind_assums.append(ind_assum)
    ind_concl = var_P(Var("x", T))
    th_name = name + "_induct"
    exts.add_extension(
        Theorem(th_name, Thm.mk_implies(*(ind_assums + [ind_concl]))))
    exts.add_extension(Attribute(th_name, "var_induct"))

    return exts