[
Introduction
]
[
File Structure
]
[
#check PROP
]
[
#check PRED
]
[
#check PREDTYPES
]
[
#check SEM (etc)
]
[
#check TP
]
[
#check ND
]
[
#check ST
]
[
Arithmetic
]
[
Sets
]
[
#check Z
]
[
#check PC
]
[
Contributions by Students
]
[
Credits
]
[
Keywords
]
Thanks to Jane Zeng for some of the documentation below.
Arithmetic theory (a term used generically in SE212) is a theory of predicate logic in which functions and predicates on numbers can be used in predicate logic expressions and proofs. Below is the syntax for these operators, many of which are infix operators. These can be used in any predicate logic formula.
"nat" and "int" are keywords in george for the natural number and integer types respectively. Arithmetic operators are parsed following BEDMAS and are left associative except for exponent which is right associative.
| Syntax in george | Meaning | Syntax in george | Meaning |
|---|---|---|---|
| a + b | addition | a - b | subtraction |
| a * b | multiplication | a / b | division |
| a^b | exponentiation | ||
| a > b | greater than | a < b | less than |
| a >= b | greater than or equal to | a <= b | less than or equal to |
| max(a,b) | maximum | min(a,b) | minimum |
| fact(a) | factorial |
These operators can be used in any predicate logic formula. For example:
#check PRED // Every number that is less than 5 is also less than 10. forall x. x < 5 => x <10
In proofs, we use the rule by arith on .. to justify any transformations on arithmetic formulas (see below). In addition, in natural deduction we have a special rule by induction on ..., which combines the universal introduction and implication introduction subproofs needed for induction (explained in lecture). Here are two examples that use induction and arithmetic reasoning:
#check ND
|- forall n:nat . 3^n >= 2^n
bc) 3^0 >= 2^0 by arith
ih) inductionstep 3^ng >= 2^ng {
2) 3^ng * 3 >= 2^ng * 2 by arith on ih
3) 3^(ng+1) >= 2^(ng+1) by arith on 2
}
4) forall n. 3^n >= 2^n by induction on bc,ih-3
#check ND
f(0) = 0,
f(1) = 1,
forall n:nat . n >= 2 => f(n) = f(n-1) + f(n-2)
|-
forall n:nat . exists y . n >= 0 & f(3*n) = 2*y
p1) f(0) = 0 premise
p2) f(1) = 1 premise
p3) forall n:nat. n >= 2 => f(n) = f(n-1) + f(n-2) premise
1) f(3*0) = f(0) by arith
3) f(3*0) = 0 by arith on 1, p1
4) f(3*0) = 2*0 by arith on 3
5) 0 >= 0 by arith
55) 0 >= 0 & f(3*0) = 2*0 by and_i on 4, 5
bc) exists y:nat . 0 >= 0 & f(3*0) = 2 * y by exists_i on 55
ih) inductionstep exists y . ng >= 0 & f(3*ng) = 2 * y {
6) for some yu assume ng >= 0 & f(3*ng) = 2*yu {
64) ng >= 0 by and_e on 6
65) f(3*ng) = 2 * yu by and_e on 6
7) 3*(ng+ 1) >= 2 => f(3*(ng+1)) = f(3*(ng+1)-1) + f(3*(ng+1)-2) by forall_e on p3
8) 3*(ng + 1) >= 2 by arith on 64
9) f(3*(ng+1)) = f(3*(ng + 1)-1) + f(3*(ng+1)-2) by imp_e on 7,8
10) f(3*(ng+1)) = f(3*ng + 2) + f(3*ng+1) by arith on 9
11) 3*ng +2 >= 2 => f(3*ng+2) = f(3*ng+2-1) + f(3*ng+2-2) by forall_e on p3
12) 3*ng+2 >= 2 by arith on 64
13) f(3*ng+2) = f(3*ng+2-1) + f(3*ng+2-2) by arith on 11, 12
15) f(3*ng+2) = f(3*ng+1) + f(3*ng) by arith on 13
17) f(3*(ng+1)) = f(3*ng+1) + f(3*ng) + f(3*ng+1) by eq_e on 10,15
20) f(3*(ng+1)) = 2*f(3*ng+1) + f(3*ng) by arith on 17
21) f(3*(ng+1)) = 2*f(3*ng+1) + 2*yu by eq_e on 65, 20
25) f(3*(ng+1)) = 2*(f(3*ng+1) + yu) by arith on 21
26) ng+1 >= 0 by arith on 64
27) ng+1 >= 0 & f(3*(ng+1)) = 2*(f(3*ng+1) + yu) by and_i on 26,25
30) exists y. ng+1 >= 0 & f(3*(ng+1)) = 2*y by exists_i on 27
}
35) exists y . ng+1 >= 0 & f(3*(ng+1)) = 2 * y by exists_e on ih, 6-30
}
40) forall n:nat . exists y . n >=0 & f(3*n) = 2*y by induction on bc, ih-35
The `by arith` rule is applicable only to arithmetic reasoning. The following describes the criteria for what constitutes an arithmetic formula (in george). All formulas (premises and conclusion) of a step must be arithmetic formulas to use a `by arith` step in george. A numeric operand is one of type nat or int.
An arithmetic formula is defined as any of the following:
In addition, quantifiers are not permitted anywhere in arithmetic formulas, as these can be unsolvable problems.
A logical operator (other than a quantifier) may appear in parameters to functions or predicates (which occurs rarely).
Examples of arithmetic formulas: x
Examples of formulas that are not arithmetic formulas:
a & b,
forall x . p(x),
f(x) = g(x) (if f and g don't return a numeric value).
If all the premises and conclusion of a step are arithmetic formulas, george will attempt to check the correctness of a `by arith` step using an SMT solver. It can determine the step is valid, invalid, or unknown (warning).
George only supports the int and nat types, not reals.
Exponents are indicated by the ^ symbol, such as a ^ b. SMT solvers, however, does not support the rule a^(m + n) = a^m * a^n. The use of exponents in an arithmetic formulas almost always yields unknown.
fact(n) is a built-in function that returns the factorial of integer n. The function is recursively axiomatized as follows:
Using fact(n) on a negative number will result in an unknown result, as `fact` is not defined for negative integers.
However, sometimes even with these axioms SMT solvers cannot solve problems that look obvious to us, such as:
fact(), min(), and max() have their function definitions built into George. But sometimes, we want to declare and axiomatize our own functions. To do this, place the function axioms as premises. Otherwise, George will not know how to interpret the function and the `by arith` steps will get unknown results.
A pitfall to watch out for is to ensure function definitions are quantified correctly. For example,
george checks some of the arith rules but if it cannot conclude that the arith steps are correct then it treats them as magic rules. Induction rules are treated as magic rules
and does not check the correctness of these, therefore george gives you a warning that
these rules have been used and not checked, but for the other TP/ND rules, it checks that
they have been used correctly.
fact(0) = 1
forall x . x >= 0 => fact(x) >= 0
forall x . x >= 1 => fact(x) = x * fact(x - 1)
x >= 0, y >= 0, max(x, y) = x|- fact(x) >= fact(y)
1) x >= 0 premise
2) y >= 0 premise
3) max(x, y) = x premise
4) fact(x) >= fact(y) by arith on 1,2,3
// incorrect version
#check ND
f(x)= 3*x + 6, g(x) = 4*x^2 |- f(5) + g(1) = 25
1) f(x)= 3*x + 6 premise // unquantified x so it thinks x is some value
2) g(x) = 4*x^2 premise
3) f(5) + g(1) = 25 by arith on 1,2 // George will report this step as invalid
// Correct version
#check ND
forall x . f(x)= 3*x + 6, forall x . g(x) = 4*x^2 |- f(5) + g(1) = 25
1) forall x . f(x)= 3*x + 6 premise
2) forall x . g(x) = 4*x^2 premise
3) f(5) = 3*5 + 6 by forall_e on 1
4) g(1) = 4*1^2 by forall_e on 2
5) f(5) = 21 by arith on 3
6) g(1) = 4 by arith on 4
7) f(5) + g(1) = 25 by arith on 5,6
What does george check?