From 391b2fe739dcd98ba64652d9e33dd433e385e447 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 15 May 2014 15:56:28 -0700 Subject: [PATCH] refactor(builtin): remove old library, we will build a new one for Lean 0.2 Signed-off-by: Leonardo de Moura --- src/CMakeLists.txt | 1 - src/builtin/CMakeLists.txt | 104 --- src/builtin/Int.lean | 68 -- src/builtin/Nat.lean | 361 ----------- src/builtin/README.md | 12 - src/builtin/Real.lean | 44 -- src/builtin/bin.lean | 74 --- src/builtin/builtin.cpp | 10 - src/builtin/dia.lean | 43 -- src/builtin/find.lua | 27 - src/builtin/kernel.lean | 1083 ------------------------------- src/builtin/lean2cpp.lean | 32 - src/builtin/lean2cpp.sh | 13 - src/builtin/lean2h.lean | 71 -- src/builtin/lean2h.sh | 13 - src/builtin/list.lean | 195 ------ src/builtin/macros.lua | 142 ---- src/builtin/name_conv.lua | 44 -- src/builtin/num.lean | 711 -------------------- src/builtin/obj/Int.olean | Bin 1429 -> 0 bytes src/builtin/obj/Nat.olean | Bin 22935 -> 0 bytes src/builtin/obj/Real.olean | Bin 1032 -> 0 bytes src/builtin/obj/kernel.olean | Bin 52554 -> 0 bytes src/builtin/obj/num.olean | Bin 49075 -> 0 bytes src/builtin/obj/optional.olean | Bin 6795 -> 0 bytes src/builtin/obj/specialfn.olean | Bin 768 -> 0 bytes src/builtin/obj/subtype.olean | Bin 3027 -> 0 bytes src/builtin/obj/sum.olean | Bin 8874 -> 0 bytes src/builtin/optional.lean | 125 ---- src/builtin/proof_irrel.lean | 64 -- src/builtin/quotient.lean | 118 ---- src/builtin/repl.lua | 36 - src/builtin/specialfn.lean | 19 - src/builtin/subtype.lean | 52 -- src/builtin/sum.lean | 137 ---- src/builtin/sum2.lean | 91 --- src/builtin/tactic.lua | 59 -- src/builtin/template.lua | 31 - src/builtin/util.lua | 16 - 39 files changed, 3796 deletions(-) delete mode 100644 src/builtin/CMakeLists.txt delete mode 100644 src/builtin/Int.lean delete mode 100644 src/builtin/Nat.lean delete mode 100644 src/builtin/README.md delete mode 100644 src/builtin/Real.lean delete mode 100644 src/builtin/bin.lean delete mode 100644 src/builtin/builtin.cpp delete mode 100644 src/builtin/dia.lean delete mode 100644 src/builtin/find.lua delete mode 100644 src/builtin/kernel.lean delete mode 100644 src/builtin/lean2cpp.lean delete mode 100755 src/builtin/lean2cpp.sh delete mode 100644 src/builtin/lean2h.lean delete mode 100755 src/builtin/lean2h.sh delete mode 100644 src/builtin/list.lean delete mode 100644 src/builtin/macros.lua delete mode 100644 src/builtin/name_conv.lua delete mode 100644 src/builtin/num.lean delete mode 100644 src/builtin/obj/Int.olean delete mode 100644 src/builtin/obj/Nat.olean delete mode 100644 src/builtin/obj/Real.olean delete mode 100644 src/builtin/obj/kernel.olean delete mode 100644 src/builtin/obj/num.olean delete mode 100644 src/builtin/obj/optional.olean delete mode 100644 src/builtin/obj/specialfn.olean delete mode 100644 src/builtin/obj/subtype.olean delete mode 100644 src/builtin/obj/sum.olean delete mode 100644 src/builtin/optional.lean delete mode 100644 src/builtin/proof_irrel.lean delete mode 100644 src/builtin/quotient.lean delete mode 100644 src/builtin/repl.lua delete mode 100644 src/builtin/specialfn.lean delete mode 100644 src/builtin/subtype.lean delete mode 100644 src/builtin/sum.lean delete mode 100644 src/builtin/sum2.lean delete mode 100644 src/builtin/tactic.lua delete mode 100644 src/builtin/template.lua delete mode 100644 src/builtin/util.lua diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7efd69f9e4..8c3c3c5067 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -237,7 +237,6 @@ endif() set(CMAKE_EXE_LINKER_FLAGS_TESTCOV "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") set(EXTRA_LIBS ${LEAN_LIBS} ${EXTRA_LIBS}) add_subdirectory(shell) -# add_subdirectory(builtin) add_subdirectory(emacs) add_subdirectory(tests/util) diff --git a/src/builtin/CMakeLists.txt b/src/builtin/CMakeLists.txt deleted file mode 100644 index 6e6c97b625..0000000000 --- a/src/builtin/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ -# This directory contains Lean builtin libraries and Lua scripts -# needed to run Lean. The builtin Lean libraries are compiled -# using ${LEAN_BINARY_DIR}/shell/lean -# The library builtin is not a real library. -# It is just a hack to force CMake to consider our custom targets -add_library(builtin builtin.cpp) - -# We copy files to the shell directory, to make sure we can test lean -# without installing it. -set(SHELL_DIR ${LEAN_BINARY_DIR}/shell) - -file(GLOB LEANLIB "*.lua") -FOREACH(FILE ${LEANLIB}) - get_filename_component(FNAME ${FILE} NAME) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} - COMMAND ${CMAKE_COMMAND} -E copy ${FILE} ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} - COMMAND ${CMAKE_COMMAND} -E copy ${FILE} ${SHELL_DIR}/${FNAME} - DEPENDS ${FILE}) - add_custom_target("${FNAME}_builtin" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FNAME}) - add_dependencies(builtin "${FNAME}_builtin") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} DESTINATION library) -ENDFOREACH(FILE) - -# The following command invokes the lean binary. -# So, it CANNOT be executed if we are cross-compiling. -function(add_theory_core FILE ARG) - set(EXTRA_DEPS ${ARGN}) - get_filename_component(BASENAME ${FILE} NAME_WE) - set(FNAME "${BASENAME}.olean") - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} - COMMAND ${SHELL_DIR}/lean.sh ${ARG} -q -o ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} ${SHELL_DIR}/${FNAME} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} ${CMAKE_CURRENT_SOURCE_DIR}/obj/${FNAME} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} lean_sh ${EXTRA_DEPS}) - add_custom_target("${BASENAME}_builtin" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} ${EXTRA_DEPS}) - add_dependencies(builtin ${BASENAME}_builtin) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} DESTINATION library) - add_test("${BASENAME}_builtin_test" ${SHELL_DIR}/lean -o ${CMAKE_CURRENT_BINARY_DIR}/${FNAME}_test ${ARG} ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) -endfunction() - -# When cross compiling, we cannot execute lean during the build. -# So, we just copy the precompiled .olean files. -function(copy_olean FILE) - get_filename_component(BASENAME ${FILE} NAME_WE) - set(FNAME "${BASENAME}.olean") - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/obj/${FNAME} ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/obj/${FNAME} ${SHELL_DIR}/${FNAME} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/obj/${FNAME}) - add_custom_target("${BASENAME}_builtin" DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FNAME}) - add_dependencies(builtin ${BASENAME}_builtin) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${FNAME} DESTINATION library) -endfunction() - -function(add_kernel_theory FILE) - if(CMAKE_CROSSCOMPILING) - copy_olean(${FILE}) - else() - add_theory_core(${FILE} "-n" ${ARGN}) - endif() -endfunction() - -function(add_theory FILE) - if(CMAKE_CROSSCOMPILING) - copy_olean(${FILE}) - else() - add_theory_core(${FILE} "" ${ARGN}) - endif() -endfunction() - -# The following command invokes the lean binary to update .cpp/.h interface files -# associated with a .lean file. -function(update_interface FILE DEST ARG) - get_filename_component(BASENAME ${FILE} NAME_WE) - set(CPPFILE "${LEAN_SOURCE_DIR}/${DEST}/${BASENAME}_decls.cpp") - set(HFILE "${LEAN_SOURCE_DIR}/${DEST}/${BASENAME}_decls.h") - # We also create a fake .h file, it serves as the output for the following - # custom command. We don't use CPPFILE and HFILE as the output to avoid - # a cyclic dependency. - set(HFILE_fake "${LEAN_BINARY_DIR}/${DEST}/${BASENAME}_fake.h") - add_custom_command(OUTPUT ${HFILE_fake} - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lean2cpp.sh "${SHELL_DIR}/lean.sh" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/${FILE}" "${CPPFILE}" "${ARG}$" - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lean2h.sh "${SHELL_DIR}/lean.sh" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/${FILE}" "${HFILE}" "${ARG}$" - COMMAND ${CMAKE_COMMAND} -E copy ${HFILE} ${HFILE_fake} - DEPENDS ${FILE} lean_sh) - add_custom_target("${BASENAME}_decls" DEPENDS ${HFILE_fake}) - add_dependencies(builtin ${BASENAME}_decls) -endfunction() - -add_kernel_theory("kernel.lean" ${CMAKE_CURRENT_BINARY_DIR}/macros.lua ${CMAKE_CURRENT_BINARY_DIR}/tactic.lua) -add_kernel_theory("Nat.lean" ${CMAKE_CURRENT_BINARY_DIR}/kernel.olean) - -add_theory("Int.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean") -add_theory("Real.lean" "${CMAKE_CURRENT_BINARY_DIR}/Int.olean") -add_theory("specialfn.lean" "${CMAKE_CURRENT_BINARY_DIR}/Real.olean") -add_theory("subtype.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean") -add_theory("optional.lean" "${CMAKE_CURRENT_BINARY_DIR}/subtype.olean") -add_theory("sum.lean" "${CMAKE_CURRENT_BINARY_DIR}/optional.olean") -add_theory("num.lean" "${CMAKE_CURRENT_BINARY_DIR}/subtype.olean") - -update_interface("kernel.olean" "kernel" "-n") -update_interface("Nat.olean" "library/arith" "-n") -update_interface("Int.olean" "library/arith" "") -update_interface("Real.olean" "library/arith" "") diff --git a/src/builtin/Int.lean b/src/builtin/Int.lean deleted file mode 100644 index fe533c68ef..0000000000 --- a/src/builtin/Int.lean +++ /dev/null @@ -1,68 +0,0 @@ -import Nat - -variable Int : Type -alias ℤ : Int -builtin nat_to_int : Nat → Int -coercion nat_to_int - -namespace Int -builtin numeral - -builtin add : Int → Int → Int -infixl 65 + : add - -builtin mul : Int → Int → Int -infixl 70 * : mul - -builtin div : Int → Int → Int -infixl 70 div : div - -builtin le : Int → Int → Bool -infix 50 <= : le -infix 50 ≤ : le - -definition ge (a b : Int) : Bool := b ≤ a -infix 50 >= : ge -infix 50 ≥ : ge - -definition lt (a b : Int) : Bool := ¬ (a ≥ b) -infix 50 < : lt - -definition gt (a b : Int) : Bool := ¬ (a ≤ b) -infix 50 > : gt - -definition sub (a b : Int) : Int := a + -1 * b -infixl 65 - : sub - -definition neg (a : Int) : Int := -1 * a -notation 75 - _ : neg - -definition mod (a b : Int) : Int := a - b * (a div b) -infixl 70 mod : mod - -definition divides (a b : Int) : Bool := (b mod a) = 0 -infix 50 | : divides - -definition abs (a : Int) : Int := if (0 ≤ a) then a else (- a) -notation 55 | _ | : abs - -set_opaque sub true -set_opaque neg true -set_opaque mod true -set_opaque divides true -set_opaque abs true -set_opaque ge true -set_opaque lt true -set_opaque gt true -end - -namespace Nat -definition sub (a b : Nat) : Int := nat_to_int a - nat_to_int b -infixl 65 - : sub - -definition neg (a : Nat) : Int := - (nat_to_int a) -notation 75 - _ : neg - -set_opaque sub true -set_opaque neg true -end \ No newline at end of file diff --git a/src/builtin/Nat.lean b/src/builtin/Nat.lean deleted file mode 100644 index 94c540df30..0000000000 --- a/src/builtin/Nat.lean +++ /dev/null @@ -1,361 +0,0 @@ -import kernel -import macros - -variable Nat : Type -alias ℕ : Nat - -namespace Nat -builtin numeral - -builtin add : Nat → Nat → Nat -infixl 65 + : add - -builtin mul : Nat → Nat → Nat -infixl 70 * : mul - -builtin le : Nat → Nat → Bool -infix 50 <= : le -infix 50 ≤ : le - -definition ge (a b : Nat) := b ≤ a -infix 50 >= : ge -infix 50 ≥ : ge - -definition lt (a b : Nat) := a + 1 ≤ b -infix 50 < : lt - -definition gt (a b : Nat) := b < a -infix 50 > : gt - -definition id (a : Nat) := a -notation 55 | _ | : id - -axiom succ_nz (a : Nat) : a + 1 ≠ 0 -axiom succ_inj {a b : Nat} (H : a + 1 = b + 1) : a = b -axiom add_zeror (a : Nat) : a + 0 = a -axiom add_succr (a b : Nat) : a + (b + 1) = (a + b) + 1 -axiom mul_zeror (a : Nat) : a * 0 = 0 -axiom mul_succr (a b : Nat) : a * (b + 1) = a * b + a -axiom le_def (a b : Nat) : a ≤ b ↔ ∃ c, a + c = b -axiom induction {P : Nat → Bool} (H1 : P 0) (H2 : ∀ (n : Nat) (iH : P n), P (n + 1)) : ∀ a, P a - -theorem induction_on {P : Nat → Bool} (a : Nat) (H1 : P 0) (H2 : ∀ (n : Nat) (iH : P n), P (n + 1)) : P a -:= induction H1 H2 a - -theorem pred_nz {a : Nat} : a ≠ 0 → ∃ b, b + 1 = a -:= induction_on a - (λ H : 0 ≠ 0, false_elim (∃ b, b + 1 = 0) (a_neq_a_elim H)) - (λ (n : Nat) (iH : n ≠ 0 → ∃ b, b + 1 = n) (H : n + 1 ≠ 0), - or_elim (em (n = 0)) - (λ Heq0 : n = 0, exists_intro 0 (calc 0 + 1 = n + 1 : { symm Heq0 })) - (λ Hne0 : n ≠ 0, - obtain (w : Nat) (Hw : w + 1 = n), from (iH Hne0), - exists_intro (w + 1) (calc w + 1 + 1 = n + 1 : { Hw }))) - -theorem discriminate {B : Bool} {a : Nat} (H1: a = 0 → B) (H2 : ∀ n, a = n + 1 → B) : B -:= or_elim (em (a = 0)) - (λ Heq0 : a = 0, H1 Heq0) - (λ Hne0 : a ≠ 0, obtain (w : Nat) (Hw : w + 1 = a), from (pred_nz Hne0), - H2 w (symm Hw)) - -theorem add_zerol (a : Nat) : 0 + a = a -:= induction_on a - (show 0 + 0 = 0, from add_zeror 0) - (λ (n : Nat) (iH : 0 + n = n), - calc 0 + (n + 1) = (0 + n) + 1 : add_succr 0 n - ... = n + 1 : { iH }) - -theorem add_succl (a b : Nat) : (a + 1) + b = (a + b) + 1 -:= induction_on b - (calc (a + 1) + 0 = a + 1 : add_zeror (a + 1) - ... = (a + 0) + 1 : { symm (add_zeror a) }) - (λ (n : Nat) (iH : (a + 1) + n = (a + n) + 1), - calc (a + 1) + (n + 1) = ((a + 1) + n) + 1 : add_succr (a + 1) n - ... = ((a + n) + 1) + 1 : { iH } - ... = (a + (n + 1)) + 1 : { show (a + n) + 1 = a + (n + 1), from symm (add_succr a n) }) - -theorem add_comm (a b : Nat) : a + b = b + a -:= induction_on b - (calc a + 0 = a : add_zeror a - ... = 0 + a : symm (add_zerol a)) - (λ (n : Nat) (iH : a + n = n + a), - calc a + (n + 1) = (a + n) + 1 : add_succr a n - ... = (n + a) + 1 : { iH } - ... = (n + 1) + a : symm (add_succl n a)) - -theorem add_assoc (a b c : Nat) : (a + b) + c = a + (b + c) -:= symm (induction_on a - (calc 0 + (b + c) = b + c : add_zerol (b + c) - ... = (0 + b) + c : { symm (add_zerol b) }) - (λ (n : Nat) (iH : n + (b + c) = (n + b) + c), - calc (n + 1) + (b + c) = (n + (b + c)) + 1 : add_succl n (b + c) - ... = ((n + b) + c) + 1 : { iH } - ... = ((n + b) + 1) + c : symm (add_succl (n + b) c) - ... = ((n + 1) + b) + c : { show (n + b) + 1 = (n + 1) + b, from symm (add_succl n b) })) - -theorem mul_zerol (a : Nat) : 0 * a = 0 -:= induction_on a - (show 0 * 0 = 0, from mul_zeror 0) - (λ (n : Nat) (iH : 0 * n = 0), - calc 0 * (n + 1) = (0 * n) + 0 : mul_succr 0 n - ... = 0 + 0 : { iH } - ... = 0 : add_zerol 0) - -theorem mul_succl (a b : Nat) : (a + 1) * b = a * b + b -:= induction_on b - (calc (a + 1) * 0 = 0 : mul_zeror (a + 1) - ... = a * 0 : symm (mul_zeror a) - ... = a * 0 + 0 : symm (add_zeror (a * 0))) - (λ (n : Nat) (iH : (a + 1) * n = a * n + n), - calc (a + 1) * (n + 1) = (a + 1) * n + (a + 1) : mul_succr (a + 1) n - ... = a * n + n + (a + 1) : { iH } - ... = a * n + n + a + 1 : symm (add_assoc (a * n + n) a 1) - ... = a * n + (n + a) + 1 : { show a * n + n + a = a * n + (n + a), - from add_assoc (a * n) n a } - ... = a * n + (a + n) + 1 : { add_comm n a } - ... = a * n + a + n + 1 : { symm (add_assoc (a * n) a n) } - ... = a * (n + 1) + n + 1 : { symm (mul_succr a n) } - ... = a * (n + 1) + (n + 1) : add_assoc (a * (n + 1)) n 1) - -theorem mul_onel (a : Nat) : 1 * a = a -:= induction_on a - (show 1 * 0 = 0, from mul_zeror 1) - (λ (n : Nat) (iH : 1 * n = n), - calc 1 * (n + 1) = 1 * n + 1 : mul_succr 1 n - ... = n + 1 : { iH }) - -theorem mul_oner (a : Nat) : a * 1 = a -:= induction_on a - (show 0 * 1 = 0, from mul_zeror 1) - (λ (n : Nat) (iH : n * 1 = n), - calc (n + 1) * 1 = n * 1 + 1 : mul_succl n 1 - ... = n + 1 : { iH }) - -theorem mul_comm (a b : Nat) : a * b = b * a -:= induction_on b - (calc a * 0 = 0 : mul_zeror a - ... = 0 * a : symm (mul_zerol a)) - (λ (n : Nat) (iH : a * n = n * a), - calc a * (n + 1) = a * n + a : mul_succr a n - ... = n * a + a : { iH } - ... = (n + 1) * a : symm (mul_succl n a)) - -theorem distributer (a b c : Nat) : a * (b + c) = a * b + a * c -:= induction_on a - (calc 0 * (b + c) = 0 : mul_zerol (b + c) - ... = 0 + 0 : add_zeror 0 - ... = 0 * b + 0 : { symm (mul_zerol b) } - ... = 0 * b + 0 * c : { symm (mul_zerol c) }) - (λ (n : Nat) (iH : n * (b + c) = n * b + n * c), - calc (n + 1) * (b + c) = n * (b + c) + (b + c) : mul_succl n (b + c) - ... = n * b + n * c + (b + c) : { iH } - ... = n * b + n * c + b + c : symm (add_assoc (n * b + n * c) b c) - ... = n * b + (n * c + b) + c : { add_assoc (n * b) (n * c) b } - ... = n * b + (b + n * c) + c : { add_comm (n * c) b } - ... = n * b + b + n * c + c : { symm (add_assoc (n * b) b (n * c)) } - ... = (n + 1) * b + n * c + c : { symm (mul_succl n b) } - ... = (n + 1) * b + (n * c + c) : add_assoc ((n + 1) * b) (n * c) c - ... = (n + 1) * b + (n + 1) * c : { symm (mul_succl n c) }) - -theorem distributel (a b c : Nat) : (a + b) * c = a * c + b * c -:= calc (a + b) * c = c * (a + b) : mul_comm (a + b) c - ... = c * a + c * b : distributer c a b - ... = a * c + c * b : { mul_comm c a } - ... = a * c + b * c : { mul_comm c b } - -theorem mul_assoc (a b c : Nat) : (a * b) * c = a * (b * c) -:= symm (induction_on a - (calc 0 * (b * c) = 0 : mul_zerol (b * c) - ... = 0 * c : symm (mul_zerol c) - ... = (0 * b) * c : { symm (mul_zerol b) }) - (λ (n : Nat) (iH : n * (b * c) = n * b * c), - calc (n + 1) * (b * c) = n * (b * c) + (b * c) : mul_succl n (b * c) - ... = n * b * c + (b * c) : { iH } - ... = (n * b + b) * c : symm (distributel (n * b) b c) - ... = (n + 1) * b * c : { symm (mul_succl n b) })) - -theorem add_left_comm (a b c : Nat) : a + (b + c) = b + (a + c) -:= left_comm add_comm add_assoc a b c - -theorem mul_left_comm (a b c : Nat) : a * (b * c) = b * (a * c) -:= left_comm mul_comm mul_assoc a b c - -theorem add_injr {a b c : Nat} : a + b = a + c → b = c -:= induction_on a - (λ H : 0 + b = 0 + c, - calc b = 0 + b : symm (add_zerol b) - ... = 0 + c : H - ... = c : add_zerol c) - (λ (n : Nat) (iH : n + b = n + c → b = c) (H : n + 1 + b = n + 1 + c), - let L1 : n + b + 1 = n + c + 1 - := (calc n + b + 1 = n + (b + 1) : add_assoc n b 1 - ... = n + (1 + b) : { add_comm b 1 } - ... = n + 1 + b : symm (add_assoc n 1 b) - ... = n + 1 + c : H - ... = n + (1 + c) : add_assoc n 1 c - ... = n + (c + 1) : { add_comm 1 c } - ... = n + c + 1 : symm (add_assoc n c 1)), - L2 : n + b = n + c := succ_inj L1 - in iH L2) - -theorem add_injl {a b c : Nat} (H : a + b = c + b) : a = c -:= add_injr (calc b + a = a + b : add_comm _ _ - ... = c + b : H - ... = b + c : add_comm _ _) - -theorem add_eqz {a b : Nat} (H : a + b = 0) : a = 0 -:= discriminate - (λ H1 : a = 0, H1) - (λ (n : Nat) (H1 : a = n + 1), - absurd_elim (a = 0) - H (calc a + b = n + 1 + b : { H1 } - ... = n + (1 + b) : add_assoc n 1 b - ... = n + (b + 1) : { add_comm 1 b } - ... = n + b + 1 : symm (add_assoc n b 1) - ... ≠ 0 : succ_nz (n + b))) - -theorem le_intro {a b c : Nat} (H : a + c = b) : a ≤ b -:= (symm (le_def a b)) ◂ (show (∃ x, a + x = b), from exists_intro c H) - -theorem le_elim {a b : Nat} (H : a ≤ b) : ∃ x, a + x = b -:= (le_def a b) ◂ H - -theorem le_refl (a : Nat) : a ≤ a := le_intro (add_zeror a) - -theorem le_zero (a : Nat) : 0 ≤ a := le_intro (add_zerol a) - -theorem le_trans {a b c : Nat} (H1 : a ≤ b) (H2 : b ≤ c) : a ≤ c -:= obtain (w1 : Nat) (Hw1 : a + w1 = b), from (le_elim H1), - obtain (w2 : Nat) (Hw2 : b + w2 = c), from (le_elim H2), - le_intro (calc a + (w1 + w2) = a + w1 + w2 : symm (add_assoc a w1 w2) - ... = b + w2 : { Hw1 } - ... = c : Hw2) - -theorem le_add {a b : Nat} (H : a ≤ b) (c : Nat) : a + c ≤ b + c -:= obtain (w : Nat) (Hw : a + w = b), from (le_elim H), - le_intro (calc a + c + w = a + (c + w) : add_assoc a c w - ... = a + (w + c) : { add_comm c w } - ... = a + w + c : symm (add_assoc a w c) - ... = b + c : { Hw }) - -theorem le_antisym {a b : Nat} (H1 : a ≤ b) (H2 : b ≤ a) : a = b -:= obtain (w1 : Nat) (Hw1 : a + w1 = b), from (le_elim H1), - obtain (w2 : Nat) (Hw2 : b + w2 = a), from (le_elim H2), - let L1 : w1 + w2 = 0 - := add_injr (calc a + (w1 + w2) = a + w1 + w2 : { symm (add_assoc a w1 w2) } - ... = b + w2 : { Hw1 } - ... = a : Hw2 - ... = a + 0 : symm (add_zeror a)), - L2 : w1 = 0 := add_eqz L1 - in calc a = a + 0 : symm (add_zeror a) - ... = a + w1 : { symm L2 } - ... = b : Hw1 - -theorem not_lt_0 (a : Nat) : ¬ a < 0 -:= not_intro (λ H : a + 1 ≤ 0, - obtain (w : Nat) (Hw1 : a + 1 + w = 0), from (le_elim H), - absurd - (calc a + w + 1 = a + (w + 1) : add_assoc _ _ _ - ... = a + (1 + w) : { add_comm _ _ } - ... = a + 1 + w : symm (add_assoc _ _ _) - ... = 0 : Hw1) - (succ_nz (a + w))) - -theorem lt_intro {a b c : Nat} (H : a + 1 + c = b) : a < b -:= le_intro H - -theorem lt_elim {a b : Nat} (H : a < b) : ∃ x, a + 1 + x = b -:= le_elim H - -theorem lt_le {a b : Nat} (H : a < b) : a ≤ b -:= obtain (w : Nat) (Hw : a + 1 + w = b), from (le_elim H), - le_intro (calc a + (1 + w) = a + 1 + w : symm (add_assoc _ _ _) - ... = b : Hw) - -theorem lt_ne {a b : Nat} (H : a < b) : a ≠ b -:= not_intro (λ H1 : a = b, - obtain (w : Nat) (Hw : a + 1 + w = b), from (lt_elim H), - absurd (calc w + 1 = 1 + w : add_comm _ _ - ... = 0 : - add_injr (calc b + (1 + w) = b + 1 + w : symm (add_assoc b 1 w) - ... = a + 1 + w : { symm H1 } - ... = b : Hw - ... = b + 0 : symm (add_zeror b))) - (succ_nz w)) - -theorem lt_nrefl (a : Nat) : ¬ a < a -:= not_intro (λ H : a < a, - absurd (refl a) (lt_ne H)) - -theorem lt_trans {a b c : Nat} (H1 : a < b) (H2 : b < c) : a < c -:= obtain (w1 : Nat) (Hw1 : a + 1 + w1 = b), from (lt_elim H1), - obtain (w2 : Nat) (Hw2 : b + 1 + w2 = c), from (lt_elim H2), - lt_intro (calc a + 1 + (w1 + 1 + w2) = a + 1 + (w1 + (1 + w2)) : { add_assoc w1 1 w2 } - ... = (a + 1 + w1) + (1 + w2) : symm (add_assoc _ _ _) - ... = b + (1 + w2) : { Hw1 } - ... = b + 1 + w2 : symm (add_assoc _ _ _) - ... = c : Hw2) - -theorem lt_le_trans {a b c : Nat} (H1 : a < b) (H2 : b ≤ c) : a < c -:= obtain (w1 : Nat) (Hw1 : a + 1 + w1 = b), from (lt_elim H1), - obtain (w2 : Nat) (Hw2 : b + w2 = c), from (le_elim H2), - lt_intro (calc a + 1 + (w1 + w2) = a + 1 + w1 + w2 : symm (add_assoc _ _ _) - ... = b + w2 : { Hw1 } - ... = c : Hw2) - -theorem le_lt_trans {a b c : Nat} (H1 : a ≤ b) (H2 : b < c) : a < c -:= obtain (w1 : Nat) (Hw1 : a + w1 = b), from (le_elim H1), - obtain (w2 : Nat) (Hw2 : b + 1 + w2 = c), from (lt_elim H2), - lt_intro (calc a + 1 + (w1 + w2) = a + 1 + w1 + w2 : symm (add_assoc _ _ _) - ... = a + (1 + w1) + w2 : { add_assoc a 1 w1 } - ... = a + (w1 + 1) + w2 : { add_comm 1 w1 } - ... = a + w1 + 1 + w2 : { symm (add_assoc a w1 1) } - ... = b + 1 + w2 : { Hw1 } - ... = c : Hw2) - -theorem ne_lt_succ {a b : Nat} (H1 : a ≠ b) (H2 : a < b + 1) : a < b -:= obtain (w : Nat) (Hw : a + 1 + w = b + 1), from (lt_elim H2), - let L : a + w = b := add_injl (calc a + w + 1 = a + (w + 1) : add_assoc _ _ _ - ... = a + (1 + w) : { add_comm _ _ } - ... = a + 1 + w : symm (add_assoc _ _ _) - ... = b + 1 : Hw) - in discriminate (λ Hz : w = 0, absurd_elim (a < b) (calc a = a + 0 : symm (add_zeror _) - ... = a + w : { symm Hz } - ... = b : L) - H1) - (λ (p : Nat) (Hp : w = p + 1), lt_intro (calc a + 1 + p = a + (1 + p) : add_assoc _ _ _ - ... = a + (p + 1) : { add_comm _ _ } - ... = a + w : { symm Hp } - ... = b : L)) - -theorem strong_induction {P : Nat → Bool} (H : ∀ n, (∀ m, m < n → P m) → P n) : ∀ a, P a -:= take a, - let stronger : P a ∧ ∀ m, m < a → P m := - -- we prove a stronger result by regular induction on a - induction_on a - (show P 0 ∧ ∀ m, m < 0 → P m, from - let c2 : ∀ m, m < 0 → P m := λ (m : Nat) (Hlt : m < 0), absurd_elim (P m) Hlt (not_lt_0 m), - c1 : P 0 := H 0 c2 - in and_intro c1 c2) - (λ (n : Nat) (iH : P n ∧ ∀ m, m < n → P m), - show P (n + 1) ∧ ∀ m, m < n + 1 → P m, from - let iH1 : P n := and_eliml iH, - iH2 : ∀ m, m < n → P m := and_elimr iH, - c2 : ∀ m, m < n + 1 → P m := λ (m : Nat) (Hlt : m < n + 1), - or_elim (em (m = n)) - (λ Heq : m = n, subst iH1 (symm Heq)) - (λ Hne : m ≠ n, iH2 m (ne_lt_succ Hne Hlt)), - c1 : P (n + 1) := H (n + 1) c2 - in and_intro c1 c2) - in and_eliml stronger - -set_opaque add true -set_opaque mul true -set_opaque le true -set_opaque id true --- We should only mark constants as opaque after we proved the theorems/properties we need. --- set_opaque ge true --- set_opaque lt true --- set_opaque gt true --- set_opaque id true -end \ No newline at end of file diff --git a/src/builtin/README.md b/src/builtin/README.md deleted file mode 100644 index c5ab6025cc..0000000000 --- a/src/builtin/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Builtin libraries and scripts ------------------------------- - -This directory contains builtin Lean theories and additional Lua -scripts that are distributed with Lean. Some of the theories (e.g., -`kernel.lean`) are automatically loaded when we start Lean. Others -must be imported using the `import` command. - -Several Lean components rely on these libraries. For example, they use -the axioms and theorems defined in these libraries to build proofs. - - diff --git a/src/builtin/Real.lean b/src/builtin/Real.lean deleted file mode 100644 index 45981271f5..0000000000 --- a/src/builtin/Real.lean +++ /dev/null @@ -1,44 +0,0 @@ -import Int - -variable Real : Type -alias ℝ : Real -builtin int_to_real : Int → Real -coercion int_to_real -definition nat_to_real (a : Nat) : Real := int_to_real (nat_to_int a) -coercion nat_to_real - -namespace Real -builtin numeral - -builtin add : Real → Real → Real -infixl 65 + : add - -builtin mul : Real → Real → Real -infixl 70 * : mul - -builtin div : Real → Real → Real -infixl 70 / : div - -builtin le : Real → Real → Bool -infix 50 <= : le -infix 50 ≤ : le - -definition ge (a b : Real) : Bool := b ≤ a -infix 50 >= : ge -infix 50 ≥ : ge - -definition lt (a b : Real) : Bool := ¬ (a ≥ b) -infix 50 < : lt - -definition gt (a b : Real) : Bool := ¬ (a ≤ b) -infix 50 > : gt - -definition sub (a b : Real) : Real := a + -1.0 * b -infixl 65 - : sub - -definition neg (a : Real) : Real := -1.0 * a -notation 75 - _ : neg - -definition abs (a : Real) : Real := if (0.0 ≤ a) then a else (- a) -notation 55 | _ | : abs -end diff --git a/src/builtin/bin.lean b/src/builtin/bin.lean deleted file mode 100644 index a2fbb8edb5..0000000000 --- a/src/builtin/bin.lean +++ /dev/null @@ -1,74 +0,0 @@ -import num tactic macros - -namespace num -definition z := zero -definition d (x : num) := x + x - -set_option simplifier::unfold true - -theorem add_d_d (x y : num) : d x + d y = d (x + y) -:= by simp - -theorem ssd (x : num) : succ (succ (d x)) = d (succ x) -:= by simp - -theorem add_sd_d (x y : num) : succ (d x) + d y = succ (d (x + y)) -:= by simp - -theorem add_d_sd (x y : num) : d x + succ (d y) = succ (d (x + y)) -:= by simp - -theorem add_sd_sd (x y : num) : succ (d x) + succ (d y) = d (succ (x + y)) -:= by simp - -theorem d_z : d zero = zero -:= by simp - -theorem s_s_z : succ (succ zero) = d (succ zero) -:= by simp - -definition d1 (x : num) := succ (d x) - -theorem d1_def (x : num) : d1 x = succ (d x) -:= refl _ - -set_opaque d true - -add_rewrite s_s_z d_z add_d_d ssd add_sd_d add_d_sd add_sd_sd d1_def - -scope -theorem test1 : d1 z = one -:= by simp - -theorem test2 : d1 one = one + one + one -:= by simp - -theorem test3 : d (d1 one) = one + one + one + one + one + one -:= by simp - -theorem test4 : d (d1 (d (d1 one))) = - d (d (d (d (d1 z)))) + d (d (d (d1 z))) + succ (succ z) -:= by simp - -theorem test5 : d (succ (succ (succ (succ (succ zero))))) = d (d1 (d one)) -:= by simp - -(* -local s = parse_lean("num::succ") -local z = parse_lean("num::zero") -local d = parse_lean("num::d") -local d1 = parse_lean("num::d1") -local add = parse_lean("num::add") -local t1 = s(s(s(s(s(s(s(s(s(s(z)))))))))) -local t2, pr = simplify(t1) -print(t2) -print(pr) - -local t1 = add(d(d(d(d(d(d(s(z))))))), d(d(d(d(s(z)))))) -local t2, pr = simplify(t1) -print(t2) -print(pr) -*) -pop_scope - -end diff --git a/src/builtin/builtin.cpp b/src/builtin/builtin.cpp deleted file mode 100644 index 0fc8b1a7c0..0000000000 --- a/src/builtin/builtin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/* -Copyright (c) 2013 Microsoft Corporation. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. - -Author: Leonardo de Moura -*/ -namespace lean { -// this is just a placeholder for forcing CMake to build the olean files -void open_extra() {} -} diff --git a/src/builtin/dia.lean b/src/builtin/dia.lean deleted file mode 100644 index 5d22841ed1..0000000000 --- a/src/builtin/dia.lean +++ /dev/null @@ -1,43 +0,0 @@ -import macros - -theorem bool_inhab : inhabited Bool -:= inhabited_intro true - --- Excluded middle from eps_ax, boolext, funext, and subst -theorem em_new (p : Bool) : p ∨ ¬ p -:= let u := @eps Bool bool_inhab (λ x, x = true ∨ p), - v := @eps Bool bool_inhab (λ x, x = false ∨ p) in - have Hu : u = true ∨ p, - from @eps_ax Bool bool_inhab (λ x, x = true ∨ p) true (or_introl (refl true) p), - have Hv : v = false ∨ p, - from @eps_ax Bool bool_inhab (λ x, x = false ∨ p) false (or_introl (refl false) p), - have H1 : u ≠ v ∨ p, - from or_elim Hu - (assume Hut : u = true, - or_elim Hv - (assume Hvf : v = false, - have Hne : u ≠ v, - from subst (subst true_ne_false (symm Hut)) (symm Hvf), - or_introl Hne p) - (assume Hp : p, or_intror (u ≠ v) Hp)) - (assume Hp : p, or_intror (u ≠ v) Hp), - have H2 : p → u = v, - from assume Hp : p, - have Hpred : (λ x, x = true ∨ p) = (λ x, x = false ∨ p), - from funext (take x : Bool, - have Hl : (x = true ∨ p) → (x = false ∨ p), - from assume A, or_intror (x = false) Hp, - have Hr : (x = false ∨ p) → (x = true ∨ p), - from assume A, or_intror (x = true) Hp, - show (x = true ∨ p) = (x = false ∨ p), - from boolext Hl Hr), - show u = v, - from @subst (Bool → Bool) (λ x : Bool, (@eq Bool x true) ∨ p) (λ x : Bool, (@eq Bool x false) ∨ p) - (λ q : Bool → Bool, @eps Bool bool_inhab (λ x : Bool, (@eq Bool x true) ∨ p) = @eps Bool bool_inhab q) - (@refl Bool (@eps Bool bool_inhab (λ x : Bool, (@eq Bool x true) ∨ p))) - Hpred, - have H3 : u ≠ v → ¬ p, - from contrapos H2, - or_elim H1 - (assume Hne : u ≠ v, or_intror p (H3 Hne)) - (assume Hp : p, or_introl Hp (¬ p)) \ No newline at end of file diff --git a/src/builtin/find.lua b/src/builtin/find.lua deleted file mode 100644 index 8814ec37e6..0000000000 --- a/src/builtin/find.lua +++ /dev/null @@ -1,27 +0,0 @@ --- Define the command --- --- Find [regex] --- --- It displays objects in the environment whose name match the given regular expression. --- Example: the command --- Find "^[cC]on" --- Displays all objects that start with the string "con" or "Con" -cmd_macro("find", - { macro_arg.String }, - function(env, pattern) - local opts = get_options() - -- Do not display the definition value - opts = opts:update({"lean", "pp", "definition_value"}, false) - local fmt = get_formatter() - local found = false - for obj in env:objects() do - if obj:has_name() and obj:has_type() and string.match(tostring(obj:get_name()), pattern) then - print(fmt(obj, opts)) - found = true - end - end - if not found then - error("no object name in the environment matches the regular expression '" .. pattern .. "'") - end - end -) diff --git a/src/builtin/kernel.lean b/src/builtin/kernel.lean deleted file mode 100644 index 7e06e7a939..0000000000 --- a/src/builtin/kernel.lean +++ /dev/null @@ -1,1083 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros tactic - -universe U ≥ 1 -definition TypeU := (Type U) - --- create default rewrite rule set -(* mk_rewrite_rule_set() *) - -variable Bool : Type - --- Reflexivity for heterogeneous equality --- We use universe U+1 in heterogeneous equality axioms because we want to be able --- to state the equality between A and B of (Type U) -axiom hrefl {A : (Type U+1)} (a : A) : a == a - --- Homogeneous equality -definition eq {A : (Type U)} (a b : A) := a == b -infix 50 = : eq - -theorem refl {A : (Type U)} (a : A) : a = a -:= hrefl a - -theorem heq_eq {A : (Type U)} (a b : A) : (a == b) = (a = b) -:= refl (a == b) - -definition true : Bool -:= (λ x : Bool, x) = (λ x : Bool, x) - -theorem trivial : true -:= refl (λ x : Bool, x) - -set_opaque true true - -definition false : Bool -:= ∀ x : Bool, x - -alias ⊤ : true -alias ⊥ : false - -definition not (a : Bool) := a → false -notation 40 ¬ _ : not - -definition or (a b : Bool) -:= ∀ c : Bool, (a → c) → (b → c) → c -infixr 30 || : or -infixr 30 \/ : or -infixr 30 ∨ : or - -definition and (a b : Bool) -:= ∀ c : Bool, (a → b → c) → c -infixr 35 && : and -infixr 35 /\ : and -infixr 35 ∧ : and - -definition implies (a b : Bool) := a → b - -definition neq {A : (Type U)} (a b : A) := ¬ (a = b) -infix 50 ≠ : neq - -theorem a_neq_a_elim {A : (Type U)} {a : A} (H : a ≠ a) : false -:= H (refl a) - -definition iff (a b : Bool) := a = b -infixr 25 <-> : iff -infixr 25 ↔ : iff - -theorem not_intro {a : Bool} (H : a → false) : ¬ a -:= H - -theorem absurd {a : Bool} (H1 : a) (H2 : ¬ a) : false -:= H2 H1 - --- The Lean parser has special treatment for the constant exists. --- It allows us to write --- exists x y : A, P x y and ∃ x y : A, P x y --- as syntax sugar for --- exists A (fun x : A, exists A (fun y : A, P x y)) --- That is, it treats the exists as an extra binder such as fun and forall. --- It also provides an alias (Exists) that should be used when we --- want to treat exists as a constant. -definition Exists (A : (Type U)) (P : A → Bool) -:= ¬ (∀ x, ¬ (P x)) - -definition exists_unique {A : (Type U)} (p : A → Bool) -:= ∃ x, p x ∧ ∀ y, y ≠ x → ¬ p y - -theorem false_elim (a : Bool) (H : false) : a -:= H a - -set_opaque false true - -theorem mt {a b : Bool} (H1 : a → b) (H2 : ¬ b) : ¬ a -:= assume Ha : a, absurd (H1 Ha) H2 - -theorem contrapos {a b : Bool} (H : a → b) : ¬ b → ¬ a -:= assume Hnb : ¬ b, mt H Hnb - -theorem absurd_elim {a : Bool} (b : Bool) (H1 : a) (H2 : ¬ a) : b -:= false_elim b (absurd H1 H2) - -theorem or_introl {a : Bool} (H : a) (b : Bool) : a ∨ b -:= take c : Bool, - assume (H1 : a → c) (H2 : b → c), - H1 H - -theorem or_intror {b : Bool} (a : Bool) (H : b) : a ∨ b -:= take c : Bool, - assume (H1 : a → c) (H2 : b → c), - H2 H - -theorem or_elim {a b c : Bool} (H1 : a ∨ b) (H2 : a → c) (H3 : b → c) : c -:= H1 c H2 H3 - -theorem resolve1 {a b : Bool} (H1 : a ∨ b) (H2 : ¬ a) : b -:= H1 b (assume Ha : a, absurd_elim b Ha H2) (assume Hb : b, Hb) - -theorem resolve2 {a b : Bool} (H1 : a ∨ b) (H2 : ¬ b) : a -:= H1 a (assume Ha : a, Ha) (assume Hb : b, absurd_elim a Hb H2) - -theorem or_flip {a b : Bool} (H : a ∨ b) : b ∨ a -:= take c : Bool, - assume (H1 : b → c) (H2 : a → c), - H c H2 H1 - -theorem and_intro {a b : Bool} (H1 : a) (H2 : b) : a ∧ b -:= take c : Bool, - assume H : a → b → c, - H H1 H2 - -theorem and_eliml {a b : Bool} (H : a ∧ b) : a -:= H a (assume (Ha : a) (Hb : b), Ha) - -theorem and_elimr {a b : Bool} (H : a ∧ b) : b -:= H b (assume (Ha : a) (Hb : b), Hb) - -axiom subst {A : (Type U)} {a b : A} {P : A → Bool} (H1 : P a) (H2 : a = b) : P b - --- Alias for subst where we provide P explicitly, but keep A,a,b implicit -theorem substp {A : (Type U)} {a b : A} (P : A → Bool) (H1 : P a) (H2 : a = b) : P b -:= subst H1 H2 - -theorem symm {A : (Type U)} {a b : A} (H : a = b) : b = a -:= subst (refl a) H - -theorem trans {A : (Type U)} {a b c : A} (H1 : a = b) (H2 : b = c) : a = c -:= subst H1 H2 - -theorem hcongr1 {A : (Type U)} {B : A → (Type U)} {f g : ∀ x, B x} (H : f = g) (a : A) : f a = g a -:= substp (fun h, f a = h a) (refl (f a)) H - -theorem congr1 {A B : (Type U)} {f g : A → B} (H : f = g) (a : A) : f a = g a -:= hcongr1 H a - -theorem congr2 {A B : (Type U)} {a b : A} (f : A → B) (H : a = b) : f a = f b -:= substp (fun x : A, f a = f x) (refl (f a)) H - -theorem congr {A B : (Type U)} {f g : A → B} {a b : A} (H1 : f = g) (H2 : a = b) : f a = g b -:= subst (congr2 f H2) (congr1 H1 b) - -theorem true_ne_false : ¬ true = false -:= assume H : true = false, - subst trivial H - -theorem absurd_not_true (H : ¬ true) : false -:= absurd trivial H - -theorem not_false_trivial : ¬ false -:= assume H : false, H - --- "equality modus pones" -theorem eqmp {a b : Bool} (H1 : a = b) (H2 : a) : b -:= subst H2 H1 - -infixl 100 <| : eqmp -infixl 100 ◂ : eqmp - -theorem eqmpr {a b : Bool} (H1 : a = b) (H2 : b) : a -:= (symm H1) ◂ H2 - -theorem imp_trans {a b c : Bool} (H1 : a → b) (H2 : b → c) : a → c -:= assume Ha, H2 (H1 Ha) - -theorem imp_eq_trans {a b c : Bool} (H1 : a → b) (H2 : b = c) : a → c -:= assume Ha, H2 ◂ (H1 Ha) - -theorem eq_imp_trans {a b c : Bool} (H1 : a = b) (H2 : b → c) : a → c -:= assume Ha, H2 (H1 ◂ Ha) - -theorem to_eq {A : (Type U)} {a b : A} (H : a == b) : a = b -:= (heq_eq a b) ◂ H - -theorem to_heq {A : (Type U)} {a b : A} (H : a = b) : a == b -:= (symm (heq_eq a b)) ◂ H - -theorem iff_eliml {a b : Bool} (H : a ↔ b) : a → b -:= (λ Ha : a, eqmp H Ha) - -theorem iff_elimr {a b : Bool} (H : a ↔ b) : b → a -:= (λ Hb : b, eqmpr H Hb) - -theorem ne_symm {A : (Type U)} {a b : A} (H : a ≠ b) : b ≠ a -:= assume H1 : b = a, H (symm H1) - -theorem eq_ne_trans {A : (Type U)} {a b c : A} (H1 : a = b) (H2 : b ≠ c) : a ≠ c -:= subst H2 (symm H1) - -theorem ne_eq_trans {A : (Type U)} {a b c : A} (H1 : a ≠ b) (H2 : b = c) : a ≠ c -:= subst H1 H2 - -theorem eqt_elim {a : Bool} (H : a = true) : a -:= (symm H) ◂ trivial - -theorem eqf_elim {a : Bool} (H : a = false) : ¬ a -:= not_intro (λ Ha : a, H ◂ Ha) - -theorem heqt_elim {a : Bool} (H : a == true) : a -:= eqt_elim (to_eq H) - -axiom boolcomplete (a : Bool) : a = true ∨ a = false - -theorem case (P : Bool → Bool) (H1 : P true) (H2 : P false) (a : Bool) : P a -:= or_elim (boolcomplete a) - (assume Ht : a = true, subst H1 (symm Ht)) - (assume Hf : a = false, subst H2 (symm Hf)) - -theorem em (a : Bool) : a ∨ ¬ a -:= or_elim (boolcomplete a) - (assume Ht : a = true, or_introl (eqt_elim Ht) (¬ a)) - (assume Hf : a = false, or_intror a (eqf_elim Hf)) - -theorem boolcomplete_swapped (a : Bool) : a = false ∨ a = true -:= case (λ x, x = false ∨ x = true) - (or_intror (true = false) (refl true)) - (or_introl (refl false) (false = true)) - a - -theorem not_true : (¬ true) = false -:= let aux : ¬ (¬ true) = true - := assume H : (¬ true) = true, - absurd_not_true (subst trivial (symm H)) - in resolve1 (boolcomplete (¬ true)) aux - -theorem not_false : (¬ false) = true -:= let aux : ¬ (¬ false) = false - := assume H : (¬ false) = false, - subst not_false_trivial H - in resolve1 (boolcomplete_swapped (¬ false)) aux - -add_rewrite not_true not_false - -theorem not_not_eq (a : Bool) : (¬ ¬ a) = a -:= case (λ x, (¬ ¬ x) = x) - (calc (¬ ¬ true) = (¬ false) : { not_true } - ... = true : not_false) - (calc (¬ ¬ false) = (¬ true) : { not_false } - ... = false : not_true) - a - -add_rewrite not_not_eq - -theorem not_neq {A : (Type U)} (a b : A) : ¬ (a ≠ b) ↔ a = b -:= not_not_eq (a = b) - -add_rewrite not_neq - -theorem not_neq_elim {A : (Type U)} {a b : A} (H : ¬ (a ≠ b)) : a = b -:= (not_neq a b) ◂ H - -theorem not_not_elim {a : Bool} (H : ¬ ¬ a) : a -:= (not_not_eq a) ◂ H - -theorem not_imp_eliml {a b : Bool} (Hnab : ¬ (a → b)) : a -:= not_not_elim - (show ¬ ¬ a, - from assume Hna : ¬ a, absurd (assume Ha : a, absurd_elim b Ha Hna) - Hnab) - -theorem not_imp_elimr {a b : Bool} (H : ¬ (a → b)) : ¬ b -:= assume Hb : b, absurd (assume Ha : a, Hb) - H - -theorem boolext {a b : Bool} (Hab : a → b) (Hba : b → a) : a = b -:= or_elim (boolcomplete a) - (λ Hat : a = true, or_elim (boolcomplete b) - (λ Hbt : b = true, trans Hat (symm Hbt)) - (λ Hbf : b = false, false_elim (a = b) (subst (Hab (eqt_elim Hat)) Hbf))) - (λ Haf : a = false, or_elim (boolcomplete b) - (λ Hbt : b = true, false_elim (a = b) (subst (Hba (eqt_elim Hbt)) Haf)) - (λ Hbf : b = false, trans Haf (symm Hbf))) - --- Another name for boolext -theorem iff_intro {a b : Bool} (Hab : a → b) (Hba : b → a) : a ↔ b -:= boolext Hab Hba - -theorem eqt_intro {a : Bool} (H : a) : a = true -:= boolext (assume H1 : a, trivial) - (assume H2 : true, H) - -theorem eqf_intro {a : Bool} (H : ¬ a) : a = false -:= boolext (assume H1 : a, absurd H1 H) - (assume H2 : false, false_elim a H2) - -theorem by_contradiction {a : Bool} (H : ¬ a → false) : a -:= or_elim (em a) (λ H1 : a, H1) (λ H1 : ¬ a, false_elim a (H H1)) - -theorem a_neq_a {A : (Type U)} (a : A) : (a ≠ a) ↔ false -:= boolext (assume H, a_neq_a_elim H) - (assume H, false_elim (a ≠ a) H) - -theorem eq_id {A : (Type U)} (a : A) : (a = a) ↔ true -:= eqt_intro (refl a) - -theorem iff_id (a : Bool) : (a ↔ a) ↔ true -:= eqt_intro (refl a) - -theorem heq_id (A : (Type U+1)) (a : A) : (a == a) ↔ true -:= eqt_intro (hrefl a) - -theorem neq_elim {A : (Type U)} {a b : A} (H : a ≠ b) : a = b ↔ false -:= eqf_intro H - -theorem neq_to_not_eq {A : (Type U)} {a b : A} : a ≠ b ↔ ¬ a = b -:= refl (a ≠ b) - -add_rewrite eq_id iff_id neq_to_not_eq - --- Remark: ordered rewriting + assoc + comm + left_comm sorts a term lexicographically -theorem left_comm {A : (Type U)} {R : A -> A -> A} (comm : ∀ x y, R x y = R y x) (assoc : ∀ x y z, R (R x y) z = R x (R y z)) : - ∀ x y z, R x (R y z) = R y (R x z) -:= take x y z, calc R x (R y z) = R (R x y) z : symm (assoc x y z) - ... = R (R y x) z : { comm x y } - ... = R y (R x z) : assoc y x z - -theorem or_comm (a b : Bool) : (a ∨ b) = (b ∨ a) -:= boolext (assume H, or_elim H (λ H1, or_intror b H1) (λ H2, or_introl H2 a)) - (assume H, or_elim H (λ H1, or_intror a H1) (λ H2, or_introl H2 b)) - -theorem or_assoc (a b c : Bool) : (a ∨ b) ∨ c ↔ a ∨ (b ∨ c) -:= boolext (assume H : (a ∨ b) ∨ c, - or_elim H (λ H1 : a ∨ b, or_elim H1 (λ Ha : a, or_introl Ha (b ∨ c)) - (λ Hb : b, or_intror a (or_introl Hb c))) - (λ Hc : c, or_intror a (or_intror b Hc))) - (assume H : a ∨ (b ∨ c), - or_elim H (λ Ha : a, (or_introl (or_introl Ha b) c)) - (λ H1 : b ∨ c, or_elim H1 (λ Hb : b, or_introl (or_intror a Hb) c) - (λ Hc : c, or_intror (a ∨ b) Hc))) - -theorem or_id (a : Bool) : a ∨ a ↔ a -:= boolext (assume H, or_elim H (λ H1, H1) (λ H2, H2)) - (assume H, or_introl H a) - -theorem or_falsel (a : Bool) : a ∨ false ↔ a -:= boolext (assume H, or_elim H (λ H1, H1) (λ H2, false_elim a H2)) - (assume H, or_introl H false) - -theorem or_falser (a : Bool) : false ∨ a ↔ a -:= trans (or_comm false a) (or_falsel a) - -theorem or_truel (a : Bool) : true ∨ a ↔ true -:= boolext (assume H : true ∨ a, trivial) - (assume H : true, or_introl trivial a) - -theorem or_truer (a : Bool) : a ∨ true ↔ true -:= trans (or_comm a true) (or_truel a) - -theorem or_tauto (a : Bool) : a ∨ ¬ a ↔ true -:= eqt_intro (em a) - -theorem or_left_comm (a b c : Bool) : a ∨ (b ∨ c) ↔ b ∨ (a ∨ c) -:= left_comm or_comm or_assoc a b c - -add_rewrite or_comm or_assoc or_id or_falsel or_falser or_truel or_truer or_tauto or_left_comm - -theorem and_comm (a b : Bool) : a ∧ b ↔ b ∧ a -:= boolext (assume H, and_intro (and_elimr H) (and_eliml H)) - (assume H, and_intro (and_elimr H) (and_eliml H)) - -theorem and_id (a : Bool) : a ∧ a ↔ a -:= boolext (assume H, and_eliml H) - (assume H, and_intro H H) - -theorem and_assoc (a b c : Bool) : (a ∧ b) ∧ c ↔ a ∧ (b ∧ c) -:= boolext (assume H, and_intro (and_eliml (and_eliml H)) (and_intro (and_elimr (and_eliml H)) (and_elimr H))) - (assume H, and_intro (and_intro (and_eliml H) (and_eliml (and_elimr H))) (and_elimr (and_elimr H))) - -theorem and_truer (a : Bool) : a ∧ true ↔ a -:= boolext (assume H : a ∧ true, and_eliml H) - (assume H : a, and_intro H trivial) - -theorem and_truel (a : Bool) : true ∧ a ↔ a -:= trans (and_comm true a) (and_truer a) - -theorem and_falsel (a : Bool) : a ∧ false ↔ false -:= boolext (assume H, and_elimr H) - (assume H, false_elim (a ∧ false) H) - -theorem and_falser (a : Bool) : false ∧ a ↔ false -:= trans (and_comm false a) (and_falsel a) - -theorem and_absurd (a : Bool) : a ∧ ¬ a ↔ false -:= boolext (assume H, absurd (and_eliml H) (and_elimr H)) - (assume H, false_elim (a ∧ ¬ a) H) - -theorem and_left_comm (a b c : Bool) : a ∧ (b ∧ c) ↔ b ∧ (a ∧ c) -:= left_comm and_comm and_assoc a b c - -add_rewrite and_comm and_assoc and_id and_falsel and_falser and_truel and_truer and_absurd and_left_comm - -theorem imp_truer (a : Bool) : (a → true) ↔ true -:= boolext (assume H, trivial) - (assume H Ha, trivial) - -theorem imp_truel (a : Bool) : (true → a) ↔ a -:= boolext (assume H : true → a, H trivial) - (assume Ha H, Ha) - -theorem imp_falser (a : Bool) : (a → false) ↔ ¬ a -:= refl _ - -theorem imp_falsel (a : Bool) : (false → a) ↔ true -:= boolext (assume H, trivial) - (assume H Hf, false_elim a Hf) - -theorem imp_id (a : Bool) : (a → a) ↔ true -:= eqt_intro (λ H : a, H) - -add_rewrite imp_truer imp_truel imp_falser imp_falsel imp_id - -theorem imp_or (a b : Bool) : (a → b) ↔ ¬ a ∨ b -:= boolext - (assume H : a → b, - (or_elim (em a) - (λ Ha : a, or_intror (¬ a) (H Ha)) - (λ Hna : ¬ a, or_introl Hna b))) - (assume H : ¬ a ∨ b, - assume Ha : a, - resolve1 H ((symm (not_not_eq a)) ◂ Ha)) - -theorem or_imp (a b : Bool) : a ∨ b ↔ (¬ a → b) -:= boolext - (assume H : a ∨ b, - (or_elim H - (assume (Ha : a) (Hna : ¬ a), absurd_elim b Ha Hna) - (assume (Hb : b) (Hna : ¬ a), Hb))) - (assume H : ¬ a → b, - (or_elim (em a) - (assume Ha : a, or_introl Ha b) - (assume Hna : ¬ a, or_intror a (H Hna)))) - -theorem not_congr {a b : Bool} (H : a ↔ b) : ¬ a ↔ ¬ b -:= congr2 not H - --- Recall that exists is defined as ¬ ∀ x : A, ¬ P x -theorem exists_elim {A : (Type U)} {P : A → Bool} {B : Bool} (H1 : Exists A P) (H2 : ∀ (a : A) (H : P a), B) : B -:= by_contradiction (assume R : ¬ B, - absurd (take a : A, mt (assume H : P a, H2 a H) R) - H1) - -theorem exists_intro {A : (Type U)} {P : A → Bool} (a : A) (H : P a) : Exists A P -:= assume H1 : (∀ x : A, ¬ P x), - absurd H (H1 a) - -theorem not_exists (A : (Type U)) (P : A → Bool) : ¬ (∃ x : A, P x) ↔ (∀ x : A, ¬ P x) -:= calc (¬ ∃ x : A, P x) = ¬ ¬ ∀ x : A, ¬ P x : refl (¬ ∃ x : A, P x) - ... = ∀ x : A, ¬ P x : not_not_eq (∀ x : A, ¬ P x) - -theorem not_exists_elim {A : (Type U)} {P : A → Bool} (H : ¬ ∃ x : A, P x) : ∀ x : A, ¬ P x -:= (not_exists A P) ◂ H - -theorem exists_unfold1 {A : (Type U)} {P : A → Bool} (a : A) (H : ∃ x : A, P x) : P a ∨ (∃ x : A, x ≠ a ∧ P x) -:= exists_elim H - (λ (w : A) (H1 : P w), - or_elim (em (w = a)) - (λ Heq : w = a, or_introl (subst H1 Heq) (∃ x : A, x ≠ a ∧ P x)) - (λ Hne : w ≠ a, or_intror (P a) (exists_intro w (and_intro Hne H1)))) - -theorem exists_unfold2 {A : (Type U)} {P : A → Bool} (a : A) (H : P a ∨ (∃ x : A, x ≠ a ∧ P x)) : ∃ x : A, P x -:= or_elim H - (λ H1 : P a, exists_intro a H1) - (λ H2 : (∃ x : A, x ≠ a ∧ P x), - exists_elim H2 - (λ (w : A) (Hw : w ≠ a ∧ P w), - exists_intro w (and_elimr Hw))) - -theorem exists_unfold {A : (Type U)} (P : A → Bool) (a : A) : (∃ x : A, P x) ↔ (P a ∨ (∃ x : A, x ≠ a ∧ P x)) -:= boolext (assume H : (∃ x : A, P x), exists_unfold1 a H) - (assume H : (P a ∨ (∃ x : A, x ≠ a ∧ P x)), exists_unfold2 a H) - -definition inhabited (A : (Type U)) -:= ∃ x : A, true - --- If we have an element of type A, then A is inhabited -theorem inhabited_intro {A : (Type U)} (a : A) : inhabited A -:= assume H : (∀ x, ¬ true), absurd_not_true (H a) - -theorem inhabited_elim {A : (Type U)} (H1 : inhabited A) {B : Bool} (H2 : A → B) : B -:= obtain (w : A) (Hw : true), from H1, - H2 w - -theorem inhabited_ex_intro {A : (Type U)} {P : A → Bool} (H : ∃ x, P x) : inhabited A -:= obtain (w : A) (Hw : P w), from H, - exists_intro w trivial - --- If a function space is non-empty, then for every 'a' in the domain, the range (B a) is not empty -theorem inhabited_range {A : (Type U)} {B : A → (Type U)} (H : inhabited (∀ x, B x)) (a : A) : inhabited (B a) -:= by_contradiction (assume N : ¬ inhabited (B a), - let s1 : ¬ ∃ x : B a, true := N, - s2 : ∀ x : B a, false := take x : B a, absurd_not_true (not_exists_elim s1 x), - s3 : ∃ y : (∀ x, B x), true := H - in obtain (w : (∀ x, B x)) (Hw : true), from s3, - let s4 : B a := w a - in s2 s4) - -theorem exists_rem {A : (Type U)} (H : inhabited A) (p : Bool) : (∃ x : A, p) ↔ p -:= iff_intro - (assume Hl : (∃ x : A, p), - obtain (w : A) (Hw : p), from Hl, - Hw) - (assume Hr : p, - inhabited_elim H (λ w, exists_intro w Hr)) - -theorem forall_rem {A : (Type U)} (H : inhabited A) (p : Bool) : (∀ x : A, p) ↔ p -:= iff_intro - (assume Hl : (∀ x : A, p), - inhabited_elim H (λ w, Hl w)) - (assume Hr : p, - take x, Hr) - - -theorem not_and (a b : Bool) : ¬ (a ∧ b) ↔ ¬ a ∨ ¬ b -:= boolext (assume H, or_elim (em a) - (assume Ha, or_elim (em b) - (assume Hb, absurd_elim (¬ a ∨ ¬ b) (and_intro Ha Hb) H) - (assume Hnb, or_intror (¬ a) Hnb)) - (assume Hna, or_introl Hna (¬ b))) - (assume (H : ¬ a ∨ ¬ b) (N : a ∧ b), - or_elim H - (assume Hna, absurd (and_eliml N) Hna) - (assume Hnb, absurd (and_elimr N) Hnb)) - -theorem not_and_elim {a b : Bool} (H : ¬ (a ∧ b)) : ¬ a ∨ ¬ b -:= (not_and a b) ◂ H - -theorem not_or (a b : Bool) : ¬ (a ∨ b) ↔ ¬ a ∧ ¬ b -:= boolext (assume H, or_elim (em a) - (assume Ha, absurd_elim (¬ a ∧ ¬ b) (or_introl Ha b) H) - (assume Hna, or_elim (em b) - (assume Hb, absurd_elim (¬ a ∧ ¬ b) (or_intror a Hb) H) - (assume Hnb, and_intro Hna Hnb))) - (assume (H : ¬ a ∧ ¬ b) (N : a ∨ b), - or_elim N - (assume Ha, absurd Ha (and_eliml H)) - (assume Hb, absurd Hb (and_elimr H))) - -theorem not_or_elim {a b : Bool} (H : ¬ (a ∨ b)) : ¬ a ∧ ¬ b -:= (not_or a b) ◂ H - -theorem not_implies (a b : Bool) : ¬ (a → b) ↔ a ∧ ¬ b -:= calc (¬ (a → b)) = ¬ (¬ a ∨ b) : { imp_or a b } - ... = ¬ ¬ a ∧ ¬ b : not_or (¬ a) b - ... = a ∧ ¬ b : congr2 (λ x, x ∧ ¬ b) (not_not_eq a) - -theorem and_imp (a b : Bool) : a ∧ b ↔ ¬ (a → ¬ b) -:= have H1 : a ∧ ¬ ¬ b ↔ ¬ (a → ¬ b), - from symm (not_implies a (¬ b)), - subst H1 (not_not_eq b) - -theorem not_implies_elim {a b : Bool} (H : ¬ (a → b)) : a ∧ ¬ b -:= (not_implies a b) ◂ H - -theorem a_eq_not_a (a : Bool) : (a = ¬ a) ↔ false -:= boolext (λ H, or_elim (em a) - (λ Ha, absurd Ha (subst Ha H)) - (λ Hna, absurd (subst Hna (symm H)) Hna)) - (λ H, false_elim (a = ¬ a) H) - -theorem a_iff_not_a (a : Bool) : (a ↔ ¬ a) ↔ false -:= a_eq_not_a a - -theorem true_eq_false : (true = false) ↔ false -:= subst (a_eq_not_a true) not_true - -theorem true_iff_false : (true ↔ false) ↔ false -:= true_eq_false - -theorem false_eq_true : (false = true) ↔ false -:= subst (a_eq_not_a false) not_false - -theorem false_iff_true : (false ↔ true) ↔ false -:= false_eq_true - -theorem a_iff_true (a : Bool) : (a ↔ true) ↔ a -:= boolext (λ H, eqt_elim H) - (λ H, eqt_intro H) - -theorem a_iff_false (a : Bool) : (a ↔ false) ↔ ¬ a -:= boolext (λ H, eqf_elim H) - (λ H, eqf_intro H) - -add_rewrite a_eq_not_a a_iff_not_a true_eq_false true_iff_false false_eq_true false_iff_true a_iff_true a_iff_false - -theorem not_iff (a b : Bool) : ¬ (a ↔ b) ↔ (¬ a ↔ b) -:= or_elim (em b) - (λ Hb, calc (¬ (a ↔ b)) = (¬ (a ↔ true)) : { eqt_intro Hb } - ... = ¬ a : { a_iff_true a } - ... = ¬ a ↔ true : { symm (a_iff_true (¬ a)) } - ... = ¬ a ↔ b : { symm (eqt_intro Hb) }) - (λ Hnb, calc (¬ (a ↔ b)) = (¬ (a ↔ false)) : { eqf_intro Hnb } - ... = ¬ ¬ a : { a_iff_false a } - ... = ¬ a ↔ false : { symm (a_iff_false (¬ a)) } - ... = ¬ a ↔ b : { symm (eqf_intro Hnb) }) - -theorem not_iff_elim {a b : Bool} (H : ¬ (a ↔ b)) : (¬ a) ↔ b -:= (not_iff a b) ◂ H - - --- Congruence theorems for contextual simplification - --- Simplify a → b, by first simplifying a to c using the fact that ¬ b is true, and then --- b to d using the fact that c is true -theorem imp_congrr {a b c d : Bool} (H_ac : ∀ (H_nb : ¬ b), a = c) (H_bd : ∀ (H_c : c), b = d) : (a → b) = (c → d) -:= or_elim (em b) - (λ H_b : b, - or_elim (em c) - (λ H_c : c, - calc (a → b) = (a → true) : { eqt_intro H_b } - ... = true : imp_truer a - ... = (c → true) : symm (imp_truer c) - ... = (c → b) : { symm (eqt_intro H_b) } - ... = (c → d) : { H_bd H_c }) - (λ H_nc : ¬ c, - calc (a → b) = (a → true) : { eqt_intro H_b } - ... = true : imp_truer a - ... = (false → d) : symm (imp_falsel d) - ... = (c → d) : { symm (eqf_intro H_nc) })) - (λ H_nb : ¬ b, - or_elim (em c) - (λ H_c : c, - calc (a → b) = (c → b) : { H_ac H_nb } - ... = (c → d) : { H_bd H_c }) - (λ H_nc : ¬ c, - calc (a → b) = (c → b) : { H_ac H_nb } - ... = (false → b) : { eqf_intro H_nc } - ... = true : imp_falsel b - ... = (false → d) : symm (imp_falsel d) - ... = (c → d) : { symm (eqf_intro H_nc) })) - - --- Simplify a → b, by first simplifying b to d using the fact that a is true, and then --- b to d using the fact that ¬ d is true. --- This kind of congruence seems to be useful in very rare cases. -theorem imp_congrl {a b c d : Bool} (H_bd : ∀ (H_a : a), b = d) (H_ac : ∀ (H_nd : ¬ d), a = c) : (a → b) = (c → d) -:= or_elim (em a) - (λ H_a : a, - or_elim (em d) - (λ H_d : d, - calc (a → b) = (a → d) : { H_bd H_a } - ... = (a → true) : { eqt_intro H_d } - ... = true : imp_truer a - ... = (c → true) : symm (imp_truer c) - ... = (c → d) : { symm (eqt_intro H_d) }) - (λ H_nd : ¬ d, - calc (a → b) = (c → b) : { H_ac H_nd } - ... = (c → d) : { H_bd H_a })) - (λ H_na : ¬ a, - or_elim (em d) - (λ H_d : d, - calc (a → b) = (false → b) : { eqf_intro H_na } - ... = true : imp_falsel b - ... = (c → true) : symm (imp_truer c) - ... = (c → d) : { symm (eqt_intro H_d) }) - (λ H_nd : ¬ d, - calc (a → b) = (false → b) : { eqf_intro H_na } - ... = true : imp_falsel b - ... = (false → d) : symm (imp_falsel d) - ... = (a → d) : { symm (eqf_intro H_na) } - ... = (c → d) : { H_ac H_nd })) - --- (Common case) simplify a to c, and then b to d using the fact that c is true -theorem imp_congr {a b c d : Bool} (H_ac : a = c) (H_bd : ∀ (H_c : c), b = d) : (a → b) = (c → d) -:= imp_congrr (λ H, H_ac) H_bd - -theorem or_congrr {a b c d : Bool} (H_ac : ∀ (H_nb : ¬ b), a = c) (H_bd : ∀ (H_nc : ¬ c), b = d) : a ∨ b ↔ c ∨ d -:= have H1 : (¬ a → b) ↔ (¬ c → d), - from imp_congrr (λ H_nb : ¬ b, congr2 not (H_ac H_nb)) H_bd, - calc (a ∨ b) = (¬ a → b) : or_imp _ _ - ... = (¬ c → d) : H1 - ... = c ∨ d : symm (or_imp _ _) - -theorem or_congrl {a b c d : Bool} (H_bd : ∀ (H_na : ¬ a), b = d) (H_ac : ∀ (H_nd : ¬ d), a = c) : a ∨ b ↔ c ∨ d -:= have H1 : (¬ a → b) ↔ (¬ c → d), - from imp_congrl H_bd (λ H_nd : ¬ d, congr2 not (H_ac H_nd)), - calc (a ∨ b) = (¬ a → b) : or_imp _ _ - ... = (¬ c → d) : H1 - ... = c ∨ d : symm (or_imp _ _) --- (Common case) simplify a to c, and then b to d using the fact that ¬ c is true -theorem or_congr {a b c d : Bool} (H_ac : a = c) (H_bd : ∀ (H_nc : ¬ c), b = d) : a ∨ b ↔ c ∨ d -:= or_congrr (λ H, H_ac) H_bd - -theorem and_congrr {a b c d : Bool} (H_ac : ∀ (H_b : b), a = c) (H_bd : ∀ (H_c : c), b = d) : a ∧ b ↔ c ∧ d -:= have H1 : ¬ (a → ¬ b) ↔ ¬ (c → ¬ d), - from congr2 not (imp_congrr (λ (H_nnb : ¬ ¬ b), H_ac (not_not_elim H_nnb)) (λ H_c : c, congr2 not (H_bd H_c))), - calc (a ∧ b) = ¬ (a → ¬ b) : and_imp _ _ - ... = ¬ (c → ¬ d) : H1 - ... = c ∧ d : symm (and_imp _ _) - -theorem and_congrl {a b c d : Bool} (H_bd : ∀ (H_a : a), b = d) (H_ac : ∀ (H_d : d), a = c) : a ∧ b ↔ c ∧ d -:= have H1 : ¬ (a → ¬ b) ↔ ¬ (c → ¬ d), - from congr2 not (imp_congrl (λ H_a : a, congr2 not (H_bd H_a)) (λ (H_nnd : ¬ ¬ d), H_ac (not_not_elim H_nnd))), - calc (a ∧ b) = ¬ (a → ¬ b) : and_imp _ _ - ... = ¬ (c → ¬ d) : H1 - ... = c ∧ d : symm (and_imp _ _) - --- (Common case) simplify a to c, and then b to d using the fact that c is true -theorem and_congr {a b c d : Bool} (H_ac : a = c) (H_bd : ∀ (H_c : c), b = d) : a ∧ b ↔ c ∧ d -:= and_congrr (λ H, H_ac) H_bd - -theorem forall_or_distributer {A : (Type U)} (p : Bool) (φ : A → Bool) : (∀ x, p ∨ φ x) = (p ∨ ∀ x, φ x) -:= boolext - (assume H : (∀ x, p ∨ φ x), - or_elim (em p) - (λ Hp : p, or_introl Hp (∀ x, φ x)) - (λ Hnp : ¬ p, or_intror p (take x, - resolve1 (H x) Hnp))) - (assume H : (p ∨ ∀ x, φ x), - take x, - or_elim H - (λ H1 : p, or_introl H1 (φ x)) - (λ H2 : (∀ x, φ x), or_intror p (H2 x))) - -theorem forall_or_distributel {A : Type} (p : Bool) (φ : A → Bool) : (∀ x, φ x ∨ p) = ((∀ x, φ x) ∨ p) -:= boolext - (assume H : (∀ x, φ x ∨ p), - or_elim (em p) - (λ Hp : p, or_intror (∀ x, φ x) Hp) - (λ Hnp : ¬ p, or_introl (take x, resolve2 (H x) Hnp) p)) - (assume H : (∀ x, φ x) ∨ p, - take x, - or_elim H - (λ H1 : (∀ x, φ x), or_introl (H1 x) p) - (λ H2 : p, or_intror (φ x) H2)) - -theorem forall_and_distribute {A : (Type U)} (φ ψ : A → Bool) : (∀ x, φ x ∧ ψ x) ↔ (∀ x, φ x) ∧ (∀ x, ψ x) -:= boolext - (assume H : (∀ x, φ x ∧ ψ x), - and_intro (take x, and_eliml (H x)) (take x, and_elimr (H x))) - (assume H : (∀ x, φ x) ∧ (∀ x, ψ x), - take x, and_intro (and_eliml H x) (and_elimr H x)) - -theorem exists_and_distributer {A : (Type U)} (p : Bool) (φ : A → Bool) : (∃ x, p ∧ φ x) ↔ p ∧ ∃ x, φ x -:= boolext - (assume H : (∃ x, p ∧ φ x), - obtain (w : A) (Hw : p ∧ φ w), from H, - and_intro (and_eliml Hw) (exists_intro w (and_elimr Hw))) - (assume H : (p ∧ ∃ x, φ x), - obtain (w : A) (Hw : φ w), from (and_elimr H), - exists_intro w (and_intro (and_eliml H) Hw)) - - -theorem exists_or_distribute {A : (Type U)} (φ ψ : A → Bool) : (∃ x, φ x ∨ ψ x) ↔ (∃ x, φ x) ∨ (∃ x, ψ x) -:= boolext - (assume H : (∃ x, φ x ∨ ψ x), - obtain (w : A) (Hw : φ w ∨ ψ w), from H, - or_elim Hw - (λ Hw1 : φ w, or_introl (exists_intro w Hw1) (∃ x, ψ x)) - (λ Hw2 : ψ w, or_intror (∃ x, φ x) (exists_intro w Hw2))) - (assume H : (∃ x, φ x) ∨ (∃ x, ψ x), - or_elim H - (λ H1 : (∃ x, φ x), - obtain (w : A) (Hw : φ w), from H1, - exists_intro w (or_introl Hw (ψ w))) - (λ H2 : (∃ x, ψ x), - obtain (w : A) (Hw : ψ w), from H2, - exists_intro w (or_intror (φ w) Hw))) - -theorem eq_exists_intro {A : (Type U)} {P Q : A → Bool} (H : ∀ x : A, P x ↔ Q x) : (∃ x : A, P x) ↔ (∃ x : A, Q x) -:= boolext - (assume Hex, obtain w Pw, from Hex, exists_intro w ((H w) ◂ Pw)) - (assume Hex, obtain w Qw, from Hex, exists_intro w ((symm (H w)) ◂ Qw)) - -theorem not_forall (A : (Type U)) (P : A → Bool) : ¬ (∀ x : A, P x) ↔ (∃ x : A, ¬ P x) -:= boolext - (assume H, by_contradiction (assume N : ¬ (∃ x, ¬ P x), - absurd (take x, not_not_elim (not_exists_elim N x)) H)) - (assume (H : ∃ x, ¬ P x) (N : ∀ x, P x), - obtain w Hw, from H, - absurd (N w) Hw) - -theorem not_forall_elim {A : (Type U)} {P : A → Bool} (H : ¬ (∀ x : A, P x)) : ∃ x : A, ¬ P x -:= (not_forall A P) ◂ H - -theorem exists_and_distributel {A : (Type U)} (p : Bool) (φ : A → Bool) : (∃ x, φ x ∧ p) ↔ (∃ x, φ x) ∧ p -:= calc (∃ x, φ x ∧ p) = (∃ x, p ∧ φ x) : eq_exists_intro (λ x, and_comm (φ x) p) - ... = (p ∧ (∃ x, φ x)) : exists_and_distributer p φ - ... = ((∃ x, φ x) ∧ p) : and_comm p (∃ x, φ x) - -theorem exists_imp_distribute {A : (Type U)} (φ ψ : A → Bool) : (∃ x, φ x → ψ x) ↔ ((∀ x, φ x) → (∃ x, ψ x)) -:= calc (∃ x, φ x → ψ x) = (∃ x, ¬ φ x ∨ ψ x) : eq_exists_intro (λ x, imp_or (φ x) (ψ x)) - ... = (∃ x, ¬ φ x) ∨ (∃ x, ψ x) : exists_or_distribute _ _ - ... = ¬ (∀ x, φ x) ∨ (∃ x, ψ x) : { symm (not_forall A φ) } - ... = (∀ x, φ x) → (∃ x, ψ x) : symm (imp_or _ _) - -theorem forall_uninhabited {A : (Type U)} {B : A → Bool} (H : ¬ inhabited A) : ∀ x, B x -:= by_contradiction (assume N : ¬ (∀ x, B x), - obtain w Hw, from not_forall_elim N, - absurd (inhabited_intro w) H) - -theorem allext {A : (Type U)} {B C : A → Bool} (H : ∀ x : A, B x = C x) : (∀ x : A, B x) = (∀ x : A, C x) -:= boolext - (assume Hl, take x, (H x) ◂ (Hl x)) - (assume Hr, take x, (symm (H x)) ◂ (Hr x)) - -theorem proj1_congr {A : (Type U)} {B : A → (Type U)} {a b : sig x, B x} (H : a = b) : proj1 a = proj1 b -:= subst (refl (proj1 a)) H - -theorem proj2_congr {A B : (Type U)} {a b : A # B} (H : a = b) : proj2 a = proj2 b -:= subst (refl (proj2 a)) H - -theorem hproj2_congr {A : (Type U)} {B : A → (Type U)} {a b : sig x, B x} (H : a = b) : proj2 a == proj2 b -:= subst (hrefl (proj2 a)) H - --- Up to this point, we proved all theorems using just reflexivity, substitution and case (proof by cases) - --- Function extensionality -axiom funext {A : (Type U)} {B : A → (Type U)} {f g : ∀ x : A, B x} (H : ∀ x : A, f x = g x) : f = g - --- Eta is a consequence of function extensionality -theorem eta {A : (Type U)} {B : A → (Type U)} (f : ∀ x : A, B x) : (λ x : A, f x) = f -:= funext (λ x : A, refl (f x)) - --- Epsilon (Hilbert's operator) -variable eps {A : (Type U)} (H : inhabited A) (P : A → Bool) : A -alias ε : eps -axiom eps_ax {A : (Type U)} (H : inhabited A) {P : A → Bool} (a : A) : P a → P (ε H P) - -theorem eps_th {A : (Type U)} {P : A → Bool} (a : A) : P a → P (ε (inhabited_intro a) P) -:= assume H : P a, @eps_ax A (inhabited_intro a) P a H - -theorem eps_singleton {A : (Type U)} (H : inhabited A) (a : A) : ε H (λ x, x = a) = a -:= let P := λ x, x = a, - Ha : P a := refl a - in eps_ax H a Ha - --- A function space (∀ x : A, B x) is inhabited if forall a : A, we have inhabited (B a) -theorem inhabited_dfun {A : (Type U)} {B : A → (Type U)} (Hn : ∀ a, inhabited (B a)) : inhabited (∀ x, B x) -:= inhabited_intro (λ x, ε (Hn x) (λ y, true)) - -theorem inhabited_fun (A : (Type U)) {B : (Type U)} (H : inhabited B) : inhabited (A → B) -:= inhabited_intro (λ x, ε H (λ y, true)) - -theorem exists_to_eps {A : (Type U)} {P : A → Bool} (H : ∃ x, P x) : P (ε (inhabited_ex_intro H) P) -:= obtain (w : A) (Hw : P w), from H, - @eps_ax _ (inhabited_ex_intro H) P w Hw - -theorem axiom_of_choice {A : (Type U)} {B : A → (Type U)} {R : ∀ x : A, B x → Bool} (H : ∀ x, ∃ y, R x y) : ∃ f, ∀ x, R x (f x) -:= exists_intro - (λ x, ε (inhabited_ex_intro (H x)) (λ y, R x y)) -- witness for f - (λ x, exists_to_eps (H x)) -- proof that witness satisfies ∀ x, R x (f x) - -theorem skolem_th {A : (Type U)} {B : A → (Type U)} {P : ∀ x : A, B x → Bool} : - (∀ x, ∃ y, P x y) ↔ ∃ f, (∀ x, P x (f x)) -:= iff_intro - (λ H : (∀ x, ∃ y, P x y), @axiom_of_choice _ _ P H) - (λ H : (∃ f, (∀ x, P x (f x))), - take x, obtain (fw : ∀ x, B x) (Hw : ∀ x, P x (fw x)), from H, - exists_intro (fw x) (Hw x)) - --- if-then-else expression, we define it using Hilbert's operator -definition ite {A : (Type U)} (c : Bool) (a b : A) : A -:= ε (inhabited_intro a) (λ r, (c → r = a) ∧ (¬ c → r = b)) -notation 45 if _ then _ else _ : ite - -theorem if_true {A : (Type U)} (a b : A) : (if true then a else b) = a -:= calc (if true then a else b) = ε (inhabited_intro a) (λ r, (true → r = a) ∧ (¬ true → r = b)) : refl (if true then a else b) - ... = ε (inhabited_intro a) (λ r, r = a) : by simp - ... = a : eps_singleton (inhabited_intro a) a - -theorem if_false {A : (Type U)} (a b : A) : (if false then a else b) = b -:= calc (if false then a else b) = ε (inhabited_intro a) (λ r, (false → r = a) ∧ (¬ false → r = b)) : refl (if false then a else b) - ... = ε (inhabited_intro a) (λ r, r = b) : by simp - ... = b : eps_singleton (inhabited_intro a) b - -theorem if_a_a {A : (Type U)} (c : Bool) (a: A) : (if c then a else a) = a -:= or_elim (em c) - (λ H : c, calc (if c then a else a) = (if true then a else a) : { eqt_intro H } - ... = a : if_true a a) - (λ H : ¬ c, calc (if c then a else a) = (if false then a else a) : { eqf_intro H } - ... = a : if_false a a) - -add_rewrite if_true if_false if_a_a - -theorem if_congr {A : (Type U)} {b c : Bool} {x y u v : A} (H_bc : b = c) - (H_xu : ∀ (H_c : c), x = u) (H_yv : ∀ (H_nc : ¬ c), y = v) : - (if b then x else y) = if c then u else v -:= or_elim (em c) - (λ H_c : c, calc - (if b then x else y) = if c then x else y : { H_bc } - ... = if true then x else y : { eqt_intro H_c } - ... = x : if_true _ _ - ... = u : H_xu H_c - ... = if true then u else v : symm (if_true _ _) - ... = if c then u else v : { symm (eqt_intro H_c) }) - (λ H_nc : ¬ c, calc - (if b then x else y) = if c then x else y : { H_bc } - ... = if false then x else y : { eqf_intro H_nc } - ... = y : if_false _ _ - ... = v : H_yv H_nc - ... = if false then u else v : symm (if_false _ _) - ... = if c then u else v : { symm (eqf_intro H_nc) }) - -theorem if_imp_then {a b c : Bool} (H : if a then b else c) : a → b -:= assume Ha : a, eqt_elim (calc b = if true then b else c : symm (if_true b c) - ... = if a then b else c : { symm (eqt_intro Ha) } - ... = true : eqt_intro H) - -theorem if_imp_else {a b c : Bool} (H : if a then b else c) : ¬ a → c -:= assume Hna : ¬ a, eqt_elim (calc c = if false then b else c : symm (if_false b c) - ... = if a then b else c : { symm (eqf_intro Hna) } - ... = true : eqt_intro H) - -theorem app_if_distribute {A B : (Type U)} (c : Bool) (f : A → B) (a b : A) : f (if c then a else b) = if c then f a else f b -:= or_elim (em c) - (λ Hc : c , calc - f (if c then a else b) = f (if true then a else b) : { eqt_intro Hc } - ... = f a : { if_true a b } - ... = if true then f a else f b : symm (if_true (f a) (f b)) - ... = if c then f a else f b : { symm (eqt_intro Hc) }) - (λ Hnc : ¬ c, calc - f (if c then a else b) = f (if false then a else b) : { eqf_intro Hnc } - ... = f b : { if_false a b } - ... = if false then f a else f b : symm (if_false (f a) (f b)) - ... = if c then f a else f b : { symm (eqf_intro Hnc) }) - -theorem eq_if_distributer {A : (Type U)} (c : Bool) (a b v : A) : (v = (if c then a else b)) = if c then v = a else v = b -:= app_if_distribute c (eq v) a b - -theorem eq_if_distributel {A : (Type U)} (c : Bool) (a b v : A) : ((if c then a else b) = v) = if c then a = v else b = v -:= app_if_distribute c (λ x, x = v) a b - -set_opaque exists true -set_opaque not true -set_opaque or true -set_opaque and true -set_opaque implies true -set_opaque ite true -set_opaque eq true - -definition injective {A B : (Type U)} (f : A → B) := ∀ x1 x2, f x1 = f x2 → x1 = x2 -definition non_surjective {A B : (Type U)} (f : A → B) := ∃ y, ∀ x, ¬ f x = y - --- The set of individuals, we need to assert the existence of one infinite set -variable ind : Type --- ind is infinite, i.e., there is a function f s.t. f is injective, and not surjective -axiom infinity : ∃ f : ind → ind, injective f ∧ non_surjective f - --- Pair extensionality -axiom pairext {A : (Type U)} {B : A → (Type U)} (a b : sig x, B x) - (H1 : proj1 a = proj1 b) (H2 : proj2 a == proj2 b) - : a = b - -theorem pair_proj_eq {A : (Type U)} {B : A → (Type U)} (a : sig x, B x) : pair (proj1 a) (proj2 a) = a -:= have Heq1 : proj1 (pair (proj1 a) (proj2 a)) = proj1 a, - from refl (proj1 a), - have Heq2 : proj2 (pair (proj1 a) (proj2 a)) == proj2 a, - from hrefl (proj2 a), - show pair (proj1 a) (proj2 a) = a, - from pairext (pair (proj1 a) (proj2 a)) a Heq1 Heq2 - -theorem pair_congr {A : (Type U)} {B : A → (Type U)} {a a' : A} {b : B a} {b' : B a'} (Ha : a = a') (Hb : b == b') - : (pair a b) = (pair a' b') -:= have Heq1 : proj1 (pair a b) = proj1 (pair a' b'), - from Ha, - have Heq2 : proj2 (pair a b) == proj2 (pair a' b'), - from Hb, - show (pair a b) = (pair a' b'), - from pairext (pair a b) (pair a' b') Heq1 Heq2 - -theorem pairext_proj {A B : (Type U)} {p : A # B} {a : A} {b : B} (H1 : proj1 p = a) (H2 : proj2 p = b) : p = (pair a b) -:= pairext p (pair a b) H1 (to_heq H2) - -theorem hpairext_proj {A : (Type U)} {B : A → (Type U)} {p : sig x, B x} {a : A} {b : B a} - (H1 : proj1 p = a) (H2 : proj2 p == b) : p = (pair a b) -:= pairext p (pair a b) H1 H2 - --- Heterogeneous equality axioms and theorems - --- We can "type-cast" an A expression into a B expression, if we can prove that A == B --- Remark: we use A == B instead of A = B, because A = B would be type incorrect. --- A = B is actually (@eq (Type U) A B), which is type incorrect because --- the first argument of eq must have type (Type U) and the type of (Type U) is (Type U+1) -variable cast {A B : (Type U+1)} : A == B → A → B - -axiom cast_heq {A B : (Type U+1)} (H : A == B) (a : A) : cast H a == a - --- Heterogeneous equality satisfies the usual properties: symmetry, transitivity, congruence, function extensionality, ... - --- Heterogeneous version of subst -axiom hsubst {A B : (Type U+1)} {a : A} {b : B} (P : ∀ T : (Type U+1), T → Bool) : P A a → a == b → P B b - -theorem hsymm {A B : (Type U+1)} {a : A} {b : B} (H : a == b) : b == a -:= hsubst (λ (T : (Type U+1)) (x : T), x == a) (hrefl a) H - -theorem htrans {A B C : (Type U+1)} {a : A} {b : B} {c : C} (H1 : a == b) (H2 : b == c) : a == c -:= hsubst (λ (T : (Type U+1)) (x : T), a == x) H1 H2 - -axiom hcongr {A A' : (Type U+1)} {B : A → (Type U+1)} {B' : A' → (Type U+1)} {f : ∀ x, B x} {f' : ∀ x, B' x} {a : A} {a' : A'} : - f == f' → a == a' → f a == f' a' - -axiom hfunext {A A' : (Type U+1)} {B : A → (Type U+1)} {B' : A' → (Type U+1)} {f : ∀ x, B x} {f' : ∀ x, B' x} : - A == A' → (∀ x x', x == x' → f x == f' x') → f == f' - -axiom hpiext {A A' : (Type U+1)} {B : A → (Type U+1)} {B' : A' → (Type U+1)} : - A == A' → (∀ x x', x == x' → B x == B' x') → (∀ x, B x) == (∀ x, B' x) - -axiom hsigext {A A' : (Type U+1)} {B : A → (Type U+1)} {B' : A' → (Type U+1)} : - A == A' → (∀ x x', x == x' → B x == B' x') → (sig x, B x) == (sig x, B' x) - --- Heterogeneous version of the allext theorem -theorem hallext {A A' : (Type U+1)} {B : A → Bool} {B' : A' → Bool} - (Ha : A == A') (Hb : ∀ x x', x == x' → B x = B' x') : (∀ x, B x) = (∀ x, B' x) -:= to_eq (hpiext Ha (λ x x' Heq, to_heq (Hb x x' Heq))) - --- Simpler version of hfunext axiom, we use it to build proofs -theorem hsfunext {A : (Type U)} {B B' : A → (Type U)} {f : ∀ x, B x} {f' : ∀ x, B' x} : - (∀ x, f x == f' x) → f == f' -:= λ Hb, - hfunext (hrefl A) (λ (x x' : A) (Heq : x == x'), - let s1 : f x == f' x := Hb x, - s2 : f' x == f' x' := hcongr (hrefl f') Heq - in htrans s1 s2) - -theorem heq_congr {A B : (Type U)} {a a' : A} {b b' : B} (H1 : a = a') (H2 : b = b') : (a == b) = (a' == b') -:= calc (a == b) = (a' == b) : { H1 } - ... = (a' == b') : { H2 } - -theorem hheq_congr {A A' B B' : (Type U+1)} {a : A} {a' : A'} {b : B} {b' : B'} (H1 : a == a') (H2 : b == b') : (a == b) = (a' == b') -:= have Heq1 : (a == b) = (a' == b), - from (hsubst (λ (T : (Type U+1)) (x : T), (a == b) = (x == b)) (refl (a == b)) H1), - have Heq2 : (a' == b) = (a' == b'), - from (hsubst (λ (T : (Type U+1)) (x : T), (a' == b) = (a' == x)) (refl (a' == b)) H2), - show (a == b) = (a' == b'), - from trans Heq1 Heq2 - -theorem type_eq {A B : (Type U)} {a : A} {b : B} (H : a == b) : A == B -:= hsubst (λ (T : (Type U+1)) (x : T), A == T) (hrefl A) H - --- Some theorems that are useful for applying simplifications. -theorem cast_eq {A : (Type U)} (H : A == A) (a : A) : cast H a = a -:= to_eq (cast_heq H a) - -theorem cast_trans {A B C : (Type U)} (Hab : A == B) (Hbc : B == C) (a : A) : cast Hbc (cast Hab a) = cast (htrans Hab Hbc) a -:= have Heq1 : cast Hbc (cast Hab a) == cast Hab a, - from cast_heq Hbc (cast Hab a), - have Heq2 : cast Hab a == a, - from cast_heq Hab a, - have Heq3 : cast (htrans Hab Hbc) a == a, - from cast_heq (htrans Hab Hbc) a, - show cast Hbc (cast Hab a) = cast (htrans Hab Hbc) a, - from to_eq (htrans (htrans Heq1 Heq2) (hsymm Heq3)) - -theorem cast_pull {A : (Type U)} {B B' : A → (Type U)} - (f : ∀ x, B x) (a : A) (Hb : (∀ x, B x) == (∀ x, B' x)) (Hba : (B a) == (B' a)) : - cast Hb f a = cast Hba (f a) -:= have s1 : cast Hb f a == f a, - from hcongr (cast_heq Hb f) (hrefl a), - have s2 : cast Hba (f a) == f a, - from cast_heq Hba (f a), - show cast Hb f a = cast Hba (f a), - from to_eq (htrans s1 (hsymm s2)) - --- Proof irrelevance is true in the set theoretic model we have for Lean. -axiom proof_irrel {a : Bool} (H1 H2 : a) : H1 = H2 - --- A more general version of proof_irrel that can be be derived using proof_irrel, heq axioms and boolext/iff_intro -theorem hproof_irrel {a b : Bool} (H1 : a) (H2 : b) : H1 == H2 -:= let Hab : a == b := to_heq (iff_intro (assume Ha, H2) (assume Hb, H1)), - H1b : b := cast Hab H1, - H1_eq_H1b : H1 == H1b := hsymm (cast_heq Hab H1), - H1b_eq_H2 : H1b == H2 := to_heq (proof_irrel H1b H2) - in htrans H1_eq_H1b H1b_eq_H2 diff --git a/src/builtin/lean2cpp.lean b/src/builtin/lean2cpp.lean deleted file mode 100644 index 0da5c219b9..0000000000 --- a/src/builtin/lean2cpp.lean +++ /dev/null @@ -1,32 +0,0 @@ -(* - -- Auxiliary script for generating .cpp files that define - -- constants defined in Lean - local env = get_environment() - local num_imports = 0 - print('/*') - print('Copyright (c) 2013 Microsoft Corporation. All rights reserved.') - print('Released under Apache 2.0 license as described in the file LICENSE.') - print('*/') - print("// Automatically generated file, DO NOT EDIT") - print('#include "kernel/environment.h"') - print('#include "kernel/decl_macros.h"') - print('namespace lean {') - for obj in env:objects() do - if obj:is_begin_import() or obj:is_begin_builtin_import() then - num_imports = num_imports + 1 - elseif obj:is_end_import() then - num_imports = num_imports - 1 - elseif num_imports == 0 and obj:has_name() and obj:has_type() and not is_explicit(env, obj:get_name()) and not obj:is_builtin() then - local is_fn = env:normalize(obj:get_type()):is_pi() - io.write('MK_CONSTANT(') - name_to_cpp_decl(obj:get_name()) - if is_fn then - io.write('_fn') - end - io.write(', ') - name_to_cpp_expr(obj:get_name()) - print(');') - end - end - print('}') -*) diff --git a/src/builtin/lean2cpp.sh b/src/builtin/lean2cpp.sh deleted file mode 100755 index 01bc9aaa33..0000000000 --- a/src/builtin/lean2cpp.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -LEAN=$1 # Lean executable -SOURCE_DIR=$2 # Where the .lean and .lua auxiliary files are located -LEAN_FILE=$3 # Lean file to be exported -DEST=$4 # where to put the CPP file -ARGS=$5 # extra arguments -if $LEAN -q $ARGS $LEAN_FILE $SOURCE_DIR/name_conv.lua $SOURCE_DIR/lean2cpp.lean > $DEST.tmp -then - mv $DEST.tmp $DEST -else - echo "Failed to generate $DEST" - exit 1 -fi diff --git a/src/builtin/lean2h.lean b/src/builtin/lean2h.lean deleted file mode 100644 index 6752ce4258..0000000000 --- a/src/builtin/lean2h.lean +++ /dev/null @@ -1,71 +0,0 @@ -(* - -- Auxiliary script for generating .h file that declare mk_* and is_* functions for - -- constants defined in Lean - local env = get_environment() - local num_imports = 0 - print('/*') - print('Copyright (c) 2013 Microsoft Corporation. All rights reserved.') - print('Released under Apache 2.0 license as described in the file LICENSE.') - print('*/') - print("// Automatically generated file, DO NOT EDIT") - print('#include "kernel/expr.h"') - print('namespace lean {') - for obj in env:objects() do - if obj:is_begin_import() or obj:is_begin_builtin_import() then - num_imports = num_imports + 1 - elseif obj:is_end_import() then - num_imports = num_imports - 1 - elseif num_imports == 0 and obj:has_name() and obj:has_type() and not is_explicit(env, obj:get_name()) and not obj:is_builtin() then - local ty = env:normalize(obj:get_type()) - local is_fn = ty:is_pi() - local arity = 0 - while ty:is_pi() do - n, d, ty = ty:fields() - arity = arity + 1 - end - local is_th = obj:is_theorem() or obj:is_axiom() - io.write("expr mk_") - name_to_cpp_decl(obj:get_name()) - if is_fn then - io.write("_fn"); - end - print("();") - io.write("bool is_") - name_to_cpp_decl(obj:get_name()) - if is_fn then - io.write("_fn"); - end - print("(expr const & e);") - if is_fn and not is_th then - io.write("inline bool is_") - name_to_cpp_decl(obj:get_name()) - io.write("(expr const & e) { return is_app(e) && is_"); - name_to_cpp_decl(obj:get_name()) - print("_fn(arg(e, 0)) && num_args(e) == " .. (arity+1) .. "; }") - end - if is_fn then - io.write("inline expr mk_") - name_to_cpp_decl(obj:get_name()) - if is_th then - io.write("_th"); - end - io.write("("); - for i = 1, arity do - if i > 1 then - io.write(", ") - end - io.write("expr const & e" .. tostring(i)) - end - io.write(") { return mk_app({mk_"); - name_to_cpp_decl(obj:get_name()) - io.write("_fn()") - for i = 1, arity do - io.write(", e" .. tostring(i)) - end - print ("}); }") - end - end - end - print('}') - -*) diff --git a/src/builtin/lean2h.sh b/src/builtin/lean2h.sh deleted file mode 100755 index 2b9ac419d1..0000000000 --- a/src/builtin/lean2h.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -LEAN=$1 # Lean executable -SOURCE_DIR=$2 # Where the .lean and .lua auxiliary files are located -LEAN_FILE=$3 # Lean file to be exported -DEST=$4 # where to put the CPP file -ARGS=$5 # extra arguments -if $LEAN -q $ARGS $LEAN_FILE $SOURCE_DIR/name_conv.lua $SOURCE_DIR/lean2h.lean > $DEST.tmp -then - mv $DEST.tmp $DEST -else - echo "Failed to generate $DEST" - exit 1 -fi diff --git a/src/builtin/list.lean b/src/builtin/list.lean deleted file mode 100644 index a950aeeb77..0000000000 --- a/src/builtin/list.lean +++ /dev/null @@ -1,195 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import num subtype optional macros tactic -using num -using subtype - -namespace list -definition none {A : (Type U)} : optional A -:= optional::@none A - -definition some {A : (Type U)} (a : A) : optional A -:= optional::some a - -definition list_rep (A : (Type U)) -:= (num → optional A) # num - -definition list_pred (A : (Type U)) -:= λ p : list_rep A, ∀ i, i < (proj2 p) ↔ (proj1 p) i ≠ (@none A) - -definition list (A : (Type U)) -:= subtype (list_rep A) (list_pred A) - -definition len {A : (Type U)} (l : list A) : num -:= proj2 (rep l) - -definition fn {A : (Type U)} (l : list A) : num → optional A -:= proj1 (rep l) - -theorem ext {A : (Type U)} {l1 l2 : list A} (H1 : len l1 = len l2) (H2 : fn l1 = fn l2) : l1 = l2 -:= have Heq : rep l1 = rep l2, - from pairext _ _ H2 (to_heq H1), - rep_inj Heq - -definition nil_rep (A : (Type U)) : list_rep A -:= (pair (λ n : num, @none A) zero : list_rep A) - -theorem nil_pred (A : (Type U)) : list_pred A (nil_rep A) -:= take i : num, - let nil := nil_rep A - in iff_intro - (assume Hl : i < (proj2 nil), - have H1 : i < zero, - from Hl, - absurd_elim ((proj1 nil) i ≠ (@none A)) H1 (not_lt_zero i)) - (assume Hr : (proj1 nil) i ≠ (@none A), - have H1 : (@none A) ≠ (@none A), - from Hr, - false_elim (i < (proj2 nil)) (a_neq_a_elim H1)) - -theorem inhab (A : (Type U)) : inhabited (list A) -:= subtype_inhabited (exists_intro (nil_rep A) (nil_pred A)) - -definition nil {A : (Type U)} : list A -:= abst (nil_rep A) (list::inhab A) - -theorem len_nil {A : (Type U)} : len (@nil A) = zero -:= have H1 : rep (@nil A) = (pair (λ n : num, @none A) zero : list_rep A), - from rep_abst (list::inhab A) (nil_rep A) (nil_pred A), - have H2 : len (@nil A) = proj2 (rep (@nil A)), - from refl (len (@nil A)), - have H3 : proj2 (rep (@nil A)) = zero, - from proj2_congr H1, - trans H2 H3 - -definition cons_rep {A : (Type U)} (h : A) (t : list A) : list_rep A -:= pair (λ n, if n = (len t) then (some h) else (fn t) n) (succ (len t)) - -theorem cons_rep_fn_at {A : (Type U)} (h : A) (t : list A) (i : num) - : (proj1 (cons_rep h t)) i = (if i = len t then some h else (fn t) i) -:= have Heq : proj1 (cons_rep h t) = λ n, if n = len t then some h else (fn t) n, - from refl (proj1 (cons_rep h t)), - congr1 Heq i - -definition cons_pred {A : (Type U)} (h : A) (t : list A) : list_pred A (cons_rep h t) -:= take i : num, - let c := cons_rep h t in - have Hci : (proj1 c) i = (if i = (len t) then (some h) else (fn t) i), - from cons_rep_fn_at h t i, - have Ht : ∀ i, i < (len t) ↔ (fn t) i ≠ (@none A), - from P_rep t, - iff_intro - (assume Hl : i < (succ (len t)), - or_elim (em (i = len t)) - (assume Heq : i = len t, - calc (proj1 c) i = (if i = (len t) then (some h) else (fn t) i) : Hci - ... = some h : by simp - ... ≠ @none A : optional::distinct h) - (assume Hne : i ≠ len t, - have Hlt : i < len t, - from lt_succ_ne_to_lt Hl Hne, - calc (proj1 c) i = (if i = (len t) then (some h) else (fn t) i) : Hci - ... = (fn t) i : by simp - ... ≠ @none A : (Ht i) ◂ Hlt)) - (assume Hr : (proj1 c) i ≠ (@none A), - or_elim (em (i = len t)) - (assume Heq : i = len t, - subst (n_lt_succ_n (len t)) (symm Heq)) - (assume Hne : i ≠ len t, - have Hne2 : (fn t) i ≠ (@none A), - from calc (fn t) i = (if i = (len t) then (some h) else (fn t) i) : by simp - ... = (proj1 c) i : symm Hci - ... ≠ (@none A) : Hr, - have Hlt : i < len t, - from (symm (Ht i)) ◂ Hne2, - show i < succ (len t), - from lt_to_lt_succ Hlt)) - -definition cons {A : (Type U)} (h : A) (t : list A) : list A -:= abst (cons_rep h t) (list::inhab A) - -theorem cons_fn_at {A : (Type U)} (h : A) (t : list A) (i : num) - : (fn (cons h t)) i = (if i = len t then some h else (fn t) i) -:= have H1 : rep (cons h t) = (cons_rep h t) , - from rep_abst (list::inhab A) (cons_rep h t) (cons_pred h t), - have H2 : fn (cons h t) = proj1 (cons_rep h t), - from proj1_congr H1, - have H3 : fn (cons h t) i = (proj1 (cons_rep h t)) i, - from congr1 H2 i, - have H4 : (proj1 (cons_rep h t)) i = (if i = len t then some h else (fn t) i), - from cons_rep_fn_at h t i, - trans H3 H4 - -theorem len_cons {A : (Type U)} (h : A) (t : list A) : len (cons h t) = succ (len t) -:= have H1 : rep (cons h t) = cons_rep h t, - from rep_abst (list::inhab A) (cons_rep h t) (cons_pred h t), - have H2 : proj2 (cons_rep h t) = succ (len t), - from refl (proj2 (cons_rep h t)), - have H3 : proj2 (rep (cons h t)) = proj2 (cons_rep h t), - from proj2_congr H1, - trans H3 H2 - -theorem cons_ne_nil {A : (Type U)} (h : A) (t : list A) : cons h t ≠ nil -:= not_intro (assume R : cons h t = nil, - have Heq1 : cons_rep h t = (nil_rep A), - from abst_inj (list::inhab A) (cons_pred h t) (nil_pred A) R, - have Heq2 : succ (len t) = zero, - from proj2_congr Heq1, - absurd Heq2 (succ_nz (len t))) - -theorem flip_iff {a b : Bool} (H : a ↔ b) : ¬ a ↔ ¬ b -:= subst (refl (¬ a)) H - -theorem cons_inj {A : (Type U)} {h1 h2 : A} {t1 t2 : list A} : cons h1 t1 = cons h2 t2 → h1 = h2 ∧ t1 = t2 -:= assume Heq : cons h1 t1 = cons h2 t2, - have Heq_rep : (cons_rep h1 t1) = (cons_rep h2 t2), - from abst_inj (list::inhab A) (cons_pred h1 t1) (cons_pred h2 t2) Heq, - have Heq_len : len t1 = len t2, - from succ_inj (proj2_congr Heq_rep), - have Heq_fn : (λ n, if n = len t2 then some h1 else (fn t1) n) = - (λ n, if n = len t2 then some h2 else (fn t2) n), - from subst (proj1_congr Heq_rep) Heq_len, - have Heq_some : some h1 = some h2, - from calc some h1 = if len t2 = len t2 then some h1 else (fn t1) (len t2) : by simp - ... = if len t2 = len t2 then some h2 else (fn t2) (len t2) : congr1 Heq_fn (len t2) - ... = some h2 : by simp, - have Heq_head : h1 = h2, - from optional::injectivity Heq_some, - have Heq_fn_t : fn t1 = fn t2, - from funext (λ i, - or_elim (em (i = len t2)) - (λ Heqi : i = len t2, - have Hlti2 : ¬ (i < len t2), - from eq_to_not_lt Heqi, - have Hlti1 : ¬ (i < len t1), - from subst Hlti2 (symm Heq_len), - have Ht1 : i < len t1 ↔ (fn t1) i ≠ (@none A), - from P_rep t1 i, - have Ht2 : i < len t2 ↔ (fn t2) i ≠ (@none A), - from P_rep t2 i, - have Heq1 : (fn t1) i = (@none A), - from not_not_elim ((flip_iff Ht1) ◂ Hlti1), - have Heq2 : (fn t2) i = (@none A), - from not_not_elim ((flip_iff Ht2) ◂ Hlti2), - trans Heq1 (symm Heq2)) - (λ Hnei : i ≠ len t2, - calc fn t1 i = if i = len t2 then some h1 else (fn t1) i : by simp - ... = if i = len t2 then some h2 else (fn t2) i : congr1 Heq_fn i - ... = fn t2 i : by simp)), - have Heq_tail : t1 = t2, - from ext Heq_len Heq_fn_t, - and_intro Heq_head Heq_tail - -theorem cons_inj_head {A : (Type U)} {h1 h2 : A} {t1 t2 : list A} : cons h1 t1 = cons h2 t2 → h1 = h2 -:= assume H, and_eliml (cons_inj H) - -theorem cons_inj_tail {A : (Type U)} {h1 h2 : A} {t1 t2 : list A} : cons h1 t1 = cons h2 t2 → t1 = t2 -:= assume H, and_elimr (cons_inj H) - -set_opaque list true -set_opaque cons true -set_opaque nil true -set_opaque len true -end -definition list := list::list \ No newline at end of file diff --git a/src/builtin/macros.lua b/src/builtin/macros.lua deleted file mode 100644 index d87b575876..0000000000 --- a/src/builtin/macros.lua +++ /dev/null @@ -1,142 +0,0 @@ --- Extra macros for automating proof construction using Lua. - --- This macro creates the syntax-sugar --- name bindings ',' expr --- For a function f with signature --- f : ... (A : Type) ... (Pi x : A, ...) --- --- farity is the arity of f --- typepos is the position of (A : Type) argument --- lambdapos is the position of the (Pi x : A, ...) argument --- -function binder_macro(name, f, farity, typepos, lambdapos) - local precedence = 0 - macro(name, { macro_arg.Parameters, macro_arg.Comma, macro_arg.Expr }, - function (env, bindings, body) - local r = body - for i = #bindings, 1, -1 do - local bname = bindings[i][1] - local btype = bindings[i][2] - local args = {} - args[#args + 1] = f - for j = 1, farity, 1 do - if j == typepos then - args[#args + 1] = btype - elseif j == lambdapos then - args[#args + 1] = fun(bname, btype, r) - else - args[#args + 1] = mk_placeholder() - end - end - r = mk_app(unpack(args)) - end - return r - end, - precedence) -end - --- The following macro is used to create nary versions of operators such as mp. --- Example: suppose we invoke --- --- nary_macro("eqmp'", Const("eqmp"), 4) --- --- Then, the macro expression --- --- eqmp' Foo H1 H2 H3 --- --- produces the expression --- --- (eqmp (eqmp (eqmp Foo H1) H2) H3) -function nary_macro(name, f, farity) - local bin_app = function(e1, e2) - local args = {} - args[#args + 1] = f - for i = 1, farity - 2, 1 do - args[#args + 1] = mk_placeholder() - end - args[#args + 1] = e1 - args[#args + 1] = e2 - return mk_app(unpack(args)) - end - - macro(name, { macro_arg.Expr, macro_arg.Expr, macro_arg.Exprs }, - function (env, e1, e2, rest) - local r = bin_app(e1, e2) - for i = 1, #rest do - r = bin_app(r, rest[i]) - end - return r - end) -end - --- exists::elim syntax-sugar --- Example: --- Assume we have the following two axioms --- Axiom Ax1: exists x y, P x y --- Axiom Ax2: forall x y, not P x y --- Now, the following macro expression --- obtain (a b : Nat) (H : P a b) from Ax1, --- show false, from absurd H (instantiate Ax2 a b) --- expands to --- exists::elim Ax1 --- (fun (a : Nat) (Haux : ...), --- exists::elim Haux --- (fun (b : Na) (H : P a b), --- show false, from absurd H (instantiate Ax2 a b) -macro("obtain", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Id, macro_arg.Expr, macro_arg.Comma, macro_arg.Expr }, - function (env, bindings, fromid, exPr, body) - local n = #bindings - if n < 2 then - error("invalid 'obtain' expression at least two bindings must be provided") - end - if fromid ~= name("from") then - error("invalid 'obtain' expression, 'from' keyword expected, got '" .. tostring(fromid) .. "'") - end - local exElim = mk_constant("exists_elim") - local H_name = bindings[n][1] - local H_type = bindings[n][2] - local a_name = bindings[n-1][1] - local a_type = bindings[n-1][2] - for i = n - 2, 1, -1 do - local Haux = name("obtain", "macro", "H", i) - body = mk_app(exElim, mk_placeholder(), mk_placeholder(), mk_placeholder(), mk_constant(Haux), - fun(a_name, a_type, fun(H_name, H_type, body))) - H_name = Haux - H_type = mk_placeholder() - a_name = bindings[i][1] - a_type = bindings[i][2] - -- We added a new binding, so we must lift free vars - body = body:lift_free_vars(0, 1) - end - -- exPr occurs after the bindings, so it is in the context of them. - -- However, this is not the case for ExistsElim. - -- So, we must lower the free variables there - exPr = exPr:lower_free_vars(n, n) - return mk_app(exElim, mk_placeholder(), mk_placeholder(), mk_placeholder(), exPr, - fun(a_name, a_type, fun(H_name, H_type, body))) - end, - 0) - -function mk_lambdas(bindings, body) - local r = body - for i = #bindings, 1, -1 do - r = fun(bindings[i][1], bindings[i][2], r) - end - return r -end - --- Allow (assume x : A, B) to be used instead of (fun x : A, B). --- It can be used to make scripts more readable, when (fun x : A, B) is being used to encode a discharge -macro("assume", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Expr}, - function (env, bindings, body) - return mk_lambdas(bindings, body) - end, - 0) - --- Allow (assume x : A, B) to be used instead of (fun x : A, B). --- It can be used to make scripts more readable, when (fun x : A, B) is being used to encode a forall_intro -macro("take", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Expr}, - function (env, bindings, body) - return mk_lambdas(bindings, body) - end, - 0) diff --git a/src/builtin/name_conv.lua b/src/builtin/name_conv.lua deleted file mode 100644 index 3a31c7e299..0000000000 --- a/src/builtin/name_conv.lua +++ /dev/null @@ -1,44 +0,0 @@ --- Output a C++ statement that creates the given name -function sanitize(s) - s, _ = string.gsub(s, "'", "_") - return s -end -function name_to_cpp_expr(n) - function rec(n) - if not n:is_atomic() then - rec(n:get_prefix()) - io.write(", ") - end - if n:is_string() then - local s = n:get_string() - io.write("\"" .. sanitize(s) .. "\"") - else - error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n)) - end - end - - io.write("name(") - if n:is_atomic() then - rec(n) - else - io.write("{") - rec(n) - io.write("}") - end - io.write(")") -end - --- Output a C++ constant name based on the given hierarchical name --- It uses '_' to glue the hierarchical name parts -function name_to_cpp_decl(n) - if not n:is_atomic(n) then - name_to_cpp_decl(n:get_prefix()) - io.write("_") - end - if n:is_string() then - local s = n:get_string() - io.write(sanitize(s)) - else - error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n)) - end -end diff --git a/src/builtin/num.lean b/src/builtin/num.lean deleted file mode 100644 index 646dfc6507..0000000000 --- a/src/builtin/num.lean +++ /dev/null @@ -1,711 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros subtype tactic -using subtype - -namespace num -theorem inhabited_ind : inhabited ind --- We use as the witness for non-emptiness, the value w in ind that is not convered by f. -:= obtain f His, from infinity, - obtain w Hw, from and_elimr His, - inhabited_intro w - -definition S := ε (inhabited_ex_intro infinity) (λ f, injective f ∧ non_surjective f) -definition Z := ε inhabited_ind (λ y, ∀ x, ¬ S x = y) - -theorem injective_S : injective S -:= and_eliml (exists_to_eps infinity) - -theorem non_surjective_S : non_surjective S -:= and_elimr (exists_to_eps infinity) - -theorem S_ne_Z (i : ind) : S i ≠ Z -:= obtain w Hw, from non_surjective_S, - eps_ax inhabited_ind w Hw i - -definition N (i : ind) : Bool -:= ∀ P, P Z → (∀ x, P x → P (S x)) → P i - -theorem N_Z : N Z -:= λ P Hz Hi, Hz - -theorem N_S {i : ind} (H : N i) : N (S i) -:= λ P Hz Hi, Hi i (H P Hz Hi) - -theorem N_smallest : ∀ P : ind → Bool, P Z → (∀ x, P x → P (S x)) → (∀ i, N i → P i) -:= λ P Hz Hi i Hni, Hni P Hz Hi - -definition num := subtype ind N - -theorem inhab : inhabited num -:= subtype_inhabited (exists_intro Z N_Z) - -definition zero : num -:= abst Z inhab - -theorem zero_pred : N Z -:= N_Z - -definition succ (n : num) : num -:= abst (S (rep n)) inhab - -theorem succ_pred (n : num) : N (S (rep n)) -:= have N_n : N (rep n), - from P_rep n, - show N (S (rep n)), - from N_S N_n - -theorem succ_inj {a b : num} : succ a = succ b → a = b -:= assume Heq1 : succ a = succ b, - have Heq2 : S (rep a) = S (rep b), - from abst_inj inhab (succ_pred a) (succ_pred b) Heq1, - have rep_eq : (rep a) = (rep b), - from injective_S (rep a) (rep b) Heq2, - show a = b, - from rep_inj rep_eq - -theorem succ_inj_rw {a b : num} : succ a = succ b ↔ a = b -:= iff_intro - (assume Hl, succ_inj Hl) - (assume Hr, congr2 succ Hr) - -add_rewrite succ_inj_rw - -theorem succ_nz (a : num) : ¬ (succ a = zero) -:= not_intro (assume R : succ a = zero, - have Heq1 : S (rep a) = Z, - from abst_inj inhab (succ_pred a) zero_pred R, - show false, - from absurd Heq1 (S_ne_Z (rep a))) - -add_rewrite succ_nz - -theorem induction {P : num → Bool} (H1 : P zero) (H2 : ∀ n, P n → P (succ n)) : ∀ a, P a -:= take a, - let Q := λ x, N x ∧ P (abst x inhab) - in have QZ : Q Z, - from and_intro zero_pred H1, - have QS : ∀ x, Q x → Q (S x), - from take x, assume Qx, - have Hp1 : P (succ (abst x inhab)), - from H2 (abst x inhab) (and_elimr Qx), - have Hp2 : P (abst (S (rep (abst x inhab))) inhab), - from Hp1, - have Nx : N x, - from and_eliml Qx, - have rep_eq : rep (abst x inhab) = x, - from rep_abst inhab x Nx, - show Q (S x), - from and_intro (N_S Nx) (subst Hp2 rep_eq), - have Qa : P (abst (rep a) inhab), - from and_elimr (N_smallest Q QZ QS (rep a) (P_rep a)), - have abst_eq : abst (rep a) inhab = a, - from abst_rep inhab a, - show P a, - from subst Qa abst_eq - -theorem induction_on {P : num → Bool} (a : num) (H1 : P zero) (H2 : ∀ n, P n → P (succ n)) : P a -:= induction H1 H2 a - -theorem dichotomy (m : num) : m = zero ∨ (∃ n, m = succ n) -:= induction_on m - (by simp) - (λ n iH, or_intror _ - (@exists_intro _ (λ x, succ n = succ x) n (refl (succ n)))) - -theorem sn_ne_n (n : num) : succ n ≠ n -:= induction_on n - (succ_nz zero) - (λ (n : num) (iH : succ n ≠ n), - not_intro - (assume R : succ (succ n) = succ n, - absurd (succ_inj R) iH)) - -add_rewrite sn_ne_n - -set_opaque num true -set_opaque Z true -set_opaque S true -set_opaque zero true -set_opaque succ true - -definition lt (m n : num) := ∃ P, (∀ i, P (succ i) → P i) ∧ P m ∧ ¬ P n -infix 50 < : lt - -theorem lt_elim {m n : num} {B : Bool} (H1 : m < n) - (H2 : ∀ (P : num → Bool), (∀ i, P (succ i) → P i) → P m → ¬ P n → B) - : B -:= obtain P Pdef, from H1, - H2 P (and_eliml Pdef) (and_eliml (and_elimr Pdef)) (and_elimr (and_elimr Pdef)) - -theorem lt_intro {m n : num} {P : num → Bool} (H1 : ∀ i, P (succ i) → P i) (H2 : P m) (H3 : ¬ P n) : m < n -:= exists_intro P (and_intro H1 (and_intro H2 H3)) - -set_opaque lt true - -theorem lt_nrefl (n : num) : ¬ (n < n) -:= not_intro - (assume N : n < n, - lt_elim N (λ P Pred Pn nPn, absurd Pn nPn)) - -add_rewrite lt_nrefl - -theorem lt_succ {m n : num} : succ m < n → m < n -:= assume H : succ m < n, - lt_elim H - (λ (P : num → Bool) (Pred : ∀ i, P (succ i) → P i) (Psm : P (succ m)) (nPn : ¬ P n), - have Pm : P m, - from Pred m Psm, - show m < n, - from lt_intro Pred Pm nPn) - -theorem not_lt_zero (n : num) : ¬ (n < zero) -:= induction_on n - (show ¬ (zero < zero), - from lt_nrefl zero) - (λ (n : num) (iH : ¬ (n < zero)), - show ¬ (succ n < zero), - from not_intro - (assume N : succ n < zero, - have nLTzero : n < zero, - from lt_succ N, - show false, - from absurd nLTzero iH)) - -add_rewrite not_lt_zero - -definition one := succ zero - -theorem one_eq_succ_zero : one = succ zero -:= refl one - -theorem zero_lt_one : zero < one -:= let P : num → Bool := λ x, x = zero - in have Ppred : ∀ i, P (succ i) → P i, - from take i, assume Ps : P (succ i), - have si_eq_z : succ i = zero, - from Ps, - have si_ne_z : succ i ≠ zero, - from succ_nz i, - show P i, - from absurd_elim (P i) si_eq_z (succ_nz i), - have Pz : P zero, - from (refl zero), - have nPs : ¬ P (succ zero), - from succ_nz zero, - show zero < succ zero, - from lt_intro Ppred Pz nPs - -theorem succ_mono_lt {m n : num} : m < n → succ m < succ n -:= assume H : m < n, - lt_elim H - (λ (P : num → Bool) (Ppred : ∀ i, P (succ i) → P i) (Pm : P m) (nPn : ¬ P n), - let Q : num → Bool := λ x, x = succ m ∨ P x - in have Qpred : ∀ i, Q (succ i) → Q i, - from take i, assume Qsi : Q (succ i), - or_elim Qsi - (assume Hl : succ i = succ m, - have Him : i = m, from succ_inj Hl, - have Pi : P i, from subst Pm (symm Him), - or_intror _ Pi) - (assume Hr : P (succ i), - have Pi : P i, from Ppred i Hr, - or_intror _ Pi), - have Qsm : Q (succ m), - from or_introl (refl (succ m)) _, - have nQsn : ¬ Q (succ n), - from not_intro - (assume R : Q (succ n), - or_elim R - (assume Hl : succ n = succ m, - absurd Pm (subst nPn (succ_inj Hl))) - (assume Hr : P (succ n), absurd (Ppred n Hr) nPn)), - show succ m < succ n, - from lt_intro Qpred Qsm nQsn) - -theorem lt_to_lt_succ {m n : num} : m < n → m < succ n -:= assume H : m < n, - lt_elim H - (λ (P : num → Bool) (Ppred : ∀ i, P (succ i) → P i) (Pm : P m) (nPn : ¬ P n), - have nPsn : ¬ P (succ n), - from not_intro - (assume R : P (succ n), - absurd (Ppred n R) nPn), - show m < succ n, - from lt_intro Ppred Pm nPsn) - -theorem n_lt_succ_n (n : num) : n < succ n -:= induction_on n - (show zero < succ zero, from zero_lt_one) - (λ (n : num) (iH : n < succ n), - succ_mono_lt iH) - -add_rewrite n_lt_succ_n - -theorem lt_to_neq {m n : num} : m < n → m ≠ n -:= assume H : m < n, - lt_elim H - (λ (P : num → Bool) (Ppred : ∀ i, P (succ i) → P i) (Pm : P m) (nPn : ¬ P n), - not_intro - (assume R : m = n, - absurd Pm (subst nPn (symm R)))) - -theorem eq_to_not_lt {m n : num} : m = n → ¬ (m < n) -:= assume Heq : m = n, - not_intro (assume R : m < n, absurd (subst R Heq) (lt_nrefl n)) - -theorem zero_lt_succ_n {n : num} : zero < succ n -:= induction_on n - (show zero < succ zero, from zero_lt_one) - (λ (n : num) (iH : zero < succ n), - lt_to_lt_succ iH) - -add_rewrite zero_lt_succ_n - -theorem lt_succ_to_disj {m n : num} : m < succ n → m = n ∨ m < n -:= assume H : m < succ n, - lt_elim H - (λ (P : num → Bool) (Ppred : ∀ i, P (succ i) → P i) (Pm : P m) (nPsn : ¬ P (succ n)), - or_elim (em (m = n)) - (assume Heq : m = n, or_introl Heq _) - (assume Hne : m ≠ n, - let Q : num → Bool := λ x, x ≠ n ∧ P x - in have Qpred : ∀ i, Q (succ i) → Q i, - from take i, assume Hsi : Q (succ i), - have H1 : succ i ≠ n, - from and_eliml Hsi, - have Psi : P (succ i), - from and_elimr Hsi, - have Pi : P i, - from Ppred i Psi, - have neq : i ≠ n, - from not_intro (assume N : i = n, - absurd (subst Psi N) nPsn), - and_intro neq Pi, - have Qm : Q m, - from and_intro Hne Pm, - have nQn : ¬ Q n, - from not_intro - (assume N : n ≠ n ∧ P n, - absurd (refl n) (and_eliml N)), - show m = n ∨ m < n, - from or_intror _ (lt_intro Qpred Qm nQn))) - -theorem disj_to_lt_succ {m n : num} : m = n ∨ m < n → m < succ n -:= assume H : m = n ∨ m < n, - or_elim H - (λ Hl : m = n, - have H1 : n < succ n, - from n_lt_succ_n n, - show m < succ n, - from subst H1 (symm Hl)) - (λ Hr : m < n, lt_to_lt_succ Hr) - -theorem lt_succ_ne_to_lt {m n : num} : m < succ n → m ≠ n → m < n -:= assume (H1 : m < succ n) (H2 : m ≠ n), - resolve1 (lt_succ_to_disj H1) H2 - -definition simp_rec_rel {A : (Type U)} (fn : num → A) (x : A) (f : A → A) (n : num) -:= fn zero = x ∧ (∀ m, m < n → fn (succ m) = f (fn m)) - -definition simp_rec_fun {A : (Type U)} (x : A) (f : A → A) (n : num) : num → A -:= ε (inhabited_fun num (inhabited_intro x)) (λ fn : num → A, simp_rec_rel fn x f n) - --- The basic idea is: --- (simp_rec_fun x f n) returns a function that 'works' for all m < n --- We have that n < succ n, then we can define (simp_rec x f n) as: -definition simp_rec {A : (Type U)} (x : A) (f : A → A) (n : num) : A -:= simp_rec_fun x f (succ n) n - -theorem simp_rec_def {A : (Type U)} (x : A) (f : A → A) (n : num) - : (∃ fn, simp_rec_rel fn x f n) - ↔ - (simp_rec_fun x f n zero = x ∧ - ∀ m, m < n → simp_rec_fun x f n (succ m) = f (simp_rec_fun x f n m)) -:= iff_intro - (assume Hl : (∃ fn, simp_rec_rel fn x f n), - obtain (fn : num → A) (Hfn : simp_rec_rel fn x f n), - from Hl, - have inhab : inhabited (num → A), - from (inhabited_fun num (inhabited_intro x)), - show simp_rec_rel (simp_rec_fun x f n) x f n, - from @eps_ax (num → A) inhab (λ fn, simp_rec_rel fn x f n) fn Hfn) - (assume Hr, - have H1 : simp_rec_rel (simp_rec_fun x f n) x f n, - from Hr, - show (∃ fn, simp_rec_rel fn x f n), - from exists_intro (simp_rec_fun x f n) H1) - -theorem simp_rec_ex {A : (Type U)} (x : A) (f : A → A) (n : num) - : ∃ fn, simp_rec_rel fn x f n -:= induction_on n - (let fn : num → A := λ n, x in - have fz : fn zero = x, by simp, - have fs : ∀ m, m < zero → fn (succ m) = f (fn m), - from take m, assume Hmn : m < zero, - absurd_elim (fn (succ m) = f (fn m)) - Hmn - (not_lt_zero m), - show ∃ fn, simp_rec_rel fn x f zero, - from exists_intro fn (and_intro fz fs)) - (λ (n : num) (iH : ∃ fn, simp_rec_rel fn x f n), - obtain (fn : num → A) (Hfn : simp_rec_rel fn x f n), from iH, - let fn1 : num → A := λ m, if succ n = m then f (fn n) else fn m in - have fnz : fn zero = x, from and_eliml Hfn, - have f1z : fn1 zero = x, by simp, - have f1s : ∀ m, m < succ n → fn1 (succ m) = f (fn1 m), - from take m, assume Hlt : m < succ n, - or_elim (lt_succ_to_disj Hlt) - (assume Hl : m = n, by simp) - (assume Hr : m < n, - have Haux1 : fn (succ m) = f (fn m), - from (and_elimr Hfn m Hr), - have Hrw1 : (succ n = succ m) ↔ false, - from eqf_intro (not_intro (assume N : succ n = succ m, - have nLt : ¬ m < n, - from eq_to_not_lt (symm (succ_inj N)), - absurd Hr nLt)), - have Haux2 : m < succ n, - from lt_to_lt_succ Hr, - have Haux3 : ¬ (succ n = m), - from ne_symm (lt_to_neq Haux2), - have Hrw2 : fn m = fn1 m, - by simp, - calc fn1 (succ m) = if succ n = succ m then f (fn n) else fn (succ m) : refl (fn1 (succ m)) - ... = if false then f (fn n) else fn (succ m) : { Hrw1 } - ... = fn (succ m) : if_false _ _ - ... = f (fn m) : Haux1 - ... = f (fn1 m) : { Hrw2 }), - show ∃ fn, simp_rec_rel fn x f (succ n), - from exists_intro fn1 (and_intro f1z f1s)) - - -theorem simp_rec_lemma1 {A : (Type U)} (x : A) (f : A → A) (n : num) - : simp_rec_fun x f n zero = x ∧ - ∀ m, m < n → simp_rec_fun x f n (succ m) = f (simp_rec_fun x f n m) -:= (simp_rec_def x f n) ◂ (simp_rec_ex x f n) - -theorem simp_rec_lemma2 {A : (Type U)} (x : A) (f : A → A) (n m1 m2 : num) - : n < m1 → n < m2 → simp_rec_fun x f m1 n = simp_rec_fun x f m2 n -:= induction_on n - (assume H1 H2, - calc simp_rec_fun x f m1 zero = x : and_eliml (simp_rec_lemma1 x f m1) - ... = simp_rec_fun x f m2 zero : symm (and_eliml (simp_rec_lemma1 x f m2))) - (λ (n : num) (iH : n < m1 → n < m2 → simp_rec_fun x f m1 n = simp_rec_fun x f m2 n), - assume (Hs1 : succ n < m1) (Hs2 : succ n < m2), - have H1 : n < m1, - from lt_succ Hs1, - have H2 : n < m2, - from lt_succ Hs2, - have Heq1 : simp_rec_fun x f m1 (succ n) = f (simp_rec_fun x f m1 n), - from and_elimr (simp_rec_lemma1 x f m1) n H1, - have Heq2 : simp_rec_fun x f m1 n = simp_rec_fun x f m2 n, - from iH H1 H2, - have Heq3 : simp_rec_fun x f m2 (succ n) = f (simp_rec_fun x f m2 n), - from and_elimr (simp_rec_lemma1 x f m2) n H2, - show simp_rec_fun x f m1 (succ n) = simp_rec_fun x f m2 (succ n), - by simp) - -theorem simp_rec_thm {A : (Type U)} (x : A) (f : A → A) - : simp_rec x f zero = x ∧ - ∀ m, simp_rec x f (succ m) = f (simp_rec x f m) -:= have Heqz : simp_rec_fun x f (succ zero) zero = x, - from and_eliml (simp_rec_lemma1 x f (succ zero)), - have Hz : simp_rec x f zero = x, - from calc simp_rec x f zero = simp_rec_fun x f (succ zero) zero : refl _ - ... = x : Heqz, - have Hs : ∀ m, simp_rec x f (succ m) = f (simp_rec x f m), - from take m, - have Hlt1 : m < succ (succ m), - from lt_to_lt_succ (n_lt_succ_n m), - have Hlt2 : m < succ m, - from n_lt_succ_n m, - have Heq1 : simp_rec_fun x f (succ (succ m)) (succ m) = f (simp_rec_fun x f (succ (succ m)) m), - from and_elimr (simp_rec_lemma1 x f (succ (succ m))) m Hlt1, - have Heq2 : simp_rec_fun x f (succ (succ m)) m = simp_rec_fun x f (succ m) m, - from simp_rec_lemma2 x f m (succ (succ m)) (succ m) Hlt1 Hlt2, - calc simp_rec x f (succ m) = simp_rec_fun x f (succ (succ m)) (succ m) : refl _ - ... = f (simp_rec_fun x f (succ (succ m)) m) : Heq1 - ... = f (simp_rec_fun x f (succ m) m) : { Heq2 } - ... = f (simp_rec x f m) : refl _, - show simp_rec x f zero = x ∧ ∀ m, simp_rec x f (succ m) = f (simp_rec x f m), - from and_intro Hz Hs - -definition pre (m : num) := if m = zero then zero else ε inhab (λ n, succ n = m) - -theorem pre_zero : pre zero = zero -:= by (Then (unfold num::pre) simp) - -theorem pre_succ (m : num) : pre (succ m) = m -:= have Heq : (λ n, succ n = succ m) = (λ n, n = m), - from funext (λ n, iff_intro (assume Hl, succ_inj Hl) - (assume Hr, congr2 succ Hr)), - calc pre (succ m) = ε inhab (λ n, succ n = succ m) : by (Then (unfold num::pre) simp) - ... = ε inhab (λ n, n = m) : { Heq } - ... = m : eps_singleton inhab m - -add_rewrite pre_zero pre_succ - -theorem succ_pre (m : num) : m ≠ zero → succ (pre m) = m -:= assume H : m ≠ zero, - have H1 : ∃ n, m = succ n, - from resolve1 (dichotomy m) H, - obtain (w : num) (H2 : m = succ w), from H1, - have H3 : (λ n, succ n = m) = (λ n, n = w), - from funext (λ n, by simp), - calc succ (pre m) = succ (if m = zero then zero else ε inhab (λ n, succ n = m)) : refl _ - ... = succ (ε inhab (λ n, n = w)) : by simp - ... = succ w : { eps_singleton inhab w } - ... = m : symm H2 - -definition prim_rec_fun {A : (Type U)} (x : A) (f : A → num → A) -:= simp_rec (λ n : num, x) (λ fn n, f (fn (pre n)) n) - -definition prim_rec {A : (Type U)} (x : A) (f : A → num → A) (m : num) -:= prim_rec_fun x f m (pre m) - -theorem prim_rec_thm {A : (Type U)} (x : A) (f : A → num → A) - : prim_rec x f zero = x ∧ - ∀ m, prim_rec x f (succ m) = f (prim_rec x f m) m -:= let faux := λ fn n, f (fn (pre n)) n in - have Hz : prim_rec x f zero = x, - from have Heq1 : simp_rec (λ n, x) faux zero = (λ n : num, x), - from and_eliml (simp_rec_thm (λ n, x) faux), - calc prim_rec x f zero = prim_rec_fun x f zero (pre zero) : refl _ - ... = prim_rec_fun x f zero zero : { pre_zero } - ... = simp_rec (λ n, x) faux zero zero : refl _ - ... = x : congr1 Heq1 zero, - have Hs : ∀ m, prim_rec x f (succ m) = f (prim_rec x f m) m, - from take m, - have Heq1 : pre (succ m) = m, - from pre_succ m, - have Heq2 : simp_rec (λ n, x) faux (succ m) = faux (simp_rec (λ n, x) faux m), - from and_elimr (simp_rec_thm (λ n, x) faux) m, - calc prim_rec x f (succ m) = prim_rec_fun x f (succ m) (pre (succ m)) : refl _ - ... = prim_rec_fun x f (succ m) m : { Heq1 } - ... = simp_rec (λ n, x) faux (succ m) m : refl _ - ... = faux (simp_rec (λ n, x) faux m) m : congr1 Heq2 m - ... = f (prim_rec x f m) m : refl _, - show prim_rec x f zero = x ∧ ∀ m, prim_rec x f (succ m) = f (prim_rec x f m) m, - from and_intro Hz Hs - -theorem prim_rec_zero {A : (Type U)} (x : A) (f : A → num → A) : prim_rec x f zero = x -:= and_eliml (prim_rec_thm x f) - -theorem prim_rec_succ {A : (Type U)} (x : A) (f : A → num → A) (m : num) : prim_rec x f (succ m) = f (prim_rec x f m) m -:= and_elimr (prim_rec_thm x f) m - -set_opaque simp_rec_rel true -set_opaque simp_rec_fun true -set_opaque simp_rec true -set_opaque prim_rec_fun true -set_opaque prim_rec true - -definition add (a b : num) : num -:= prim_rec a (λ x n, succ x) b -infixl 65 + : add - -theorem add_zeror (a : num) : a + zero = a -:= prim_rec_zero a (λ x n, succ x) - -theorem add_succr (a b : num) : a + succ b = succ (a + b) -:= prim_rec_succ a (λ x n, succ x) b - -definition mul (a b : num) : num -:= prim_rec zero (λ x n, x + a) b -infixl 70 * : mul - -theorem mul_zeror (a : num) : a * zero = zero -:= prim_rec_zero zero (λ x n, x + a) - -theorem mul_succr (a b : num) : a * (succ b) = a * b + a -:= prim_rec_succ zero (λ x n, x + a) b - -add_rewrite add_zeror add_succr mul_zeror mul_succr - -set_opaque add true -set_opaque mul true - -theorem add_zerol (a : num) : zero + a = a -:= induction_on a (by simp) (by simp) - -theorem add_succl (a b : num) : (succ a) + b = succ (a + b) -:= induction_on b (by simp) (by simp) - -add_rewrite add_zerol add_succl - -theorem add_comm (a b : num) : a + b = b + a -:= induction_on b (by simp) (by simp) - -theorem add_assoc (a b c : num) : (a + b) + c = a + (b + c) -:= induction_on a (by simp) (by simp) - -theorem add_left_comm (a b c : num) : a + (b + c) = b + (a + c) -:= left_comm add_comm add_assoc a b c - -add_rewrite add_assoc add_comm add_left_comm - -theorem mul_zerol (a : num) : zero * a = zero -:= induction_on a (by simp) (by simp) - -theorem mul_succl (a b : num) : (succ a) * b = a * b + b -:= induction_on b (by simp) (by simp) - -add_rewrite mul_zerol mul_succl - -theorem mul_onel (a : num) : (succ zero) * a = a -:= induction_on a (by simp) (by simp) - -theorem mul_oner (a : num) : a * (succ zero) = a -:= induction_on a (by simp) (by simp) - -add_rewrite mul_onel mul_oner - -theorem mul_comm (a b : num) : a * b = b * a -:= induction_on b (by simp) (by simp) - -theorem distributer (a b c : num) : a * (b + c) = a * b + a * c -:= induction_on a (by simp) (by simp) - -add_rewrite mul_comm distributer - -theorem distributel (a b c : num) : (a + b) * c = a * c + b * c -:= induction_on a (by simp) (by simp) - -add_rewrite distributel - -theorem mul_assoc (a b c : num) : (a * b) * c = a * (b * c) -:= induction_on b (by simp) (by simp) - -theorem mul_left_comm (a b c : num) : a * (b * c) = b * (a * c) -:= left_comm mul_comm mul_assoc a b c - -add_rewrite mul_assoc mul_left_comm - -theorem lt_addr {a b : num} (c : num) : a < b → a + c < b + c -:= assume H : a < b, - induction_on c - (by simp) - (λ (c : num) (iH : a + c < b + c), - have H1 : succ (a + c) < succ (b + c), - from succ_mono_lt iH, - show a + succ c < b + succ c, - from subst (subst H1 (symm (add_succr a c))) (symm (add_succr b c))) - -theorem addl_lt {a b c : num} : a + c < b → a < b -:= induction_on c - (assume H : a + zero < b, subst H (add_zeror a)) - (λ (c : num) (iH : a + c < b → a < b), - assume H : a + (succ c) < b, - have H1 : succ (a + c) < b, - from subst H (add_succr a c), - have H2 : a + c < b, - from lt_succ H1, - show a < b, from iH H2) - -theorem lt_to_nez {a b : num} (H : a < b) : b ≠ zero -:= not_intro (assume N : b = zero, - absurd (subst H N) (not_lt_zero a)) - -theorem lt_ex1 {a b : num} : a < b → ∃ c, a + (succ c) = b -:= induction_on a - (assume H : zero < b, - have H1 : b ≠ zero, from lt_to_nez H, - have H2 : succ (pre b) = b, from succ_pre b H1, - show ∃ c, zero + (succ c) = b, - from exists_intro (pre b) (by simp)) - (λ (a : num) (iH : a < b → ∃ c, a + (succ c) = b), - assume H : succ a < b, - have H1 : a < b, from lt_succ H, - obtain (c : num) (Hc : a + (succ c) = b), from iH H1, - have Hcnz : c ≠ zero, - from not_intro (assume L1 : c = zero, - have Hb : b = a + (succ c), from symm Hc, - have L2 : succ a = b, by simp, - show false, from absurd L2 (lt_to_neq H)), - have Hspc : succ (pre c) = c, - from succ_pre c Hcnz, - show ∃ c, (succ a) + (succ c) = b, - from exists_intro (pre c) (calc (succ a) + (succ (pre c)) = succ (a + c) : by simp - ... = a + (succ c) : symm (add_succr _ _) - ... = b : Hc )) - -theorem lt_ex2 {a b : num} : (∃ c, a + (succ c) = b) → a < b -:= assume Hex : ∃ c, a + (succ c) = b, - obtain (c : num) (Hc : a + (succ c) = b), from Hex, - have H1 : succ (a + c) = b, - from subst Hc (add_succr a c), - have H2 : a + c < b, - from subst (n_lt_succ_n (a + c)) H1, - show a < b, - from addl_lt H2 - -theorem lt_ex (a b : num) : a < b ↔ ∃ c, a + (succ c) = b -:= iff_intro (assume Hl, lt_ex1 Hl) (assume Hr, lt_ex2 Hr) - -theorem lt_to_ex {a b : num} (H : a < b) : ∃ c, a + (succ c) = b -:= lt_ex1 H - -theorem ex_to_lt {a b c : num} (H : a + succ c = b) : a < b -:= lt_ex2 (exists_intro c H) - -theorem lt_trans {a b c : num} : a < b → b < c → a < c -:= assume H1 H2, - obtain (w1 : num) (Hw1 : a + succ w1 = b), from lt_to_ex H1, - obtain (w2 : num) (Hw2 : b + succ w2 = c), from lt_to_ex H2, - have Hac : a + succ (succ (w1 + w2)) = c, - from calc a + succ (succ (w1 + w2)) = (a + succ w1) + succ w2 : by simp_no_assump - ... = b + succ w2 : { Hw1 } - ... = c : { Hw2 }, - ex_to_lt Hac - -theorem strong_induction {P : num → Bool} (H : ∀ n, (∀ m, m < n → P m) → P n) : ∀ a, P a -:= take a : num, - have stronger : P a ∧ ∀ m, m < a → P m, - from induction_on a -- we prove a stronger result by regular induction on a - (have c2 : ∀ m, m < zero → P m, - from λ (m : num) (Hlt : m < zero), absurd_elim (P m) Hlt (not_lt_zero m), - have c1 : P zero, - from H zero c2, - show P zero ∧ ∀ m, m < zero → P m, - from and_intro c1 c2) - (λ (n : num) (iH : P n ∧ ∀ m, m < n → P m), - have iH1 : P n, - from and_eliml iH, - have iH2 : ∀ m, m < n → P m, - from and_elimr iH, - have c2 : ∀ m, m < succ n → P m, - from take m : num, assume Hlt : m < succ n, - or_elim (em (m = n)) - (assume Heq : m = n, subst iH1 (symm Heq)) - (assume Hne : m ≠ n, iH2 m (lt_succ_ne_to_lt Hlt Hne)), - have c1 : P (succ n), - from H (succ n) c2, - and_intro c1 c2), - show P a, - from and_eliml stronger - -definition fact (a : num) : num -:= prim_rec one (λ x n, succ n * x) a - -theorem fact_zero : fact zero = one -:= prim_rec_zero one (λ x n : num, succ n * x) - -theorem fact_succ (n : num) : fact (succ n) = succ n * fact n -:= prim_rec_succ one (λ x n : num, succ n * x) n - -definition exp (a b : num) : num -:= prim_rec one (λ x n, a * x) b - -theorem exp_zero (a : num) : exp a zero = one -:= prim_rec_zero one (λ x n, a * x) - -theorem exp_succ (a b : num) : exp a (succ b) = a * (exp a b) -:= prim_rec_succ one (λ x n, a * x) b - -set_opaque fact true -set_opaque exp true -end - -definition num := num::num diff --git a/src/builtin/obj/Int.olean b/src/builtin/obj/Int.olean deleted file mode 100644 index e1a16bf66c18036fca893e00d26b1b1a6cfa71f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1429 zcmZ`(!EO^V5FLBdCQTx>NIeu3ltU=0s8VQqKnf)iASxlG@(Gcbbt8+-x+G3dJ#y)P zlpo8N;2H0F?Nz9%&71X`dC%kV>RgKAR^<}PKc*IUdTHR7Toy8iGP)54?!^-Lx57Y| z0Z+97kt?wRzWMV6iOWvcDmSVCRtPgQdZsMfs|6doYJabz?xUK3m zsCpPwU9HnCO~Wd#P0wrif*{GX5cUb~&_IpP@lA6pV>d;#m7_qkkaMCBe2*|3#(fwQ znOtGcw$nULxcp6v zz)0d00~)J7dEj^-?Ny8Q9)g1y1!^L7N_9_OCtR8G3*i)KaNl~F9?2Y29Ex!M0QMi* z?`c;j@Z-+iiz8N{fk#7+MjoAbwCB;jM~BQ^I{ZFW1C(%#>@2x^H$hi!gvjuOywj9S z+%dTxA+2l|!p2<)2k5MB*0>s=57i7z>Q+p{Rxlop(WURhncvGL`&wkz_$mGemukZ$ diff --git a/src/builtin/obj/Nat.olean b/src/builtin/obj/Nat.olean deleted file mode 100644 index 8c23f25d87d94080ab941f37093f24a58ab3568e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22935 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 diff --git a/src/builtin/obj/Real.olean b/src/builtin/obj/Real.olean deleted file mode 100644 index dc0f82ceabe1eea5503090fc8cb79fe78769e542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1032 zcmZ`&%Sr<=6urqvEA|DtsGuS^;zBJxHg2?_q9B3`f1qTXv;@;crfF9$-S`pi^vC)o z&b^s-9%vZu+$1OG+?=^%wG?Kkw1jLhHGZ>+gIAdtsUe#^3AacejDwj-fImy2VT}Qg ztOKEym;j%Dd_mxuqN&nO8DPq|fwO}I;kQ;MFUlH%@K_Fk8?dZgQujxacRj&vH@hW6X}4F@TjE&W-f<4Kx?J_pCyIjKM6|j`@9C?R4(}EYi)d0gd=PNuvLBY^J~R+kqYz>| YrnD%+`8%W!HpB(#?7^Lh@A2>d1+%xKa{vGU diff --git a/src/builtin/obj/kernel.olean b/src/builtin/obj/kernel.olean deleted file mode 100644 index 89828906083f545eb14cd62594a3925c0b72fb55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52554 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 i&ADR&TN7@`)|*mtg@tO{%!tNMB+Njxyf) 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 diff --git a/src/builtin/obj/specialfn.olean b/src/builtin/obj/specialfn.olean deleted file mode 100644 index c2c9170a52ed1f43ffbf14efad7351d42cd475dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 768 zcmah{!A`?440Y0WWf!yq8V9(bR@|7z{sE30_<<^{8AN1h)nwC-{2{-@Y^OyUo#?^x zv!9>c*EUuww=q^je1zGyO&8!(cTQV~=tYG-ebvgsUUeY#p@j>nAdysK0qWT1osb~Z z8g40Tln43!1ql{XR`JF$x7Hhw>&7$6<$)3?h&+KZNqLXoy#YvUmZCczQ`KfqR9Pg_ zsZfQc!a9IBB3J)}JT-7y-@UeH8-S-}k&+(a8$b@L~HG|&f@j2uyF)VtY&-2K+WpD65yv38N IpYgB%0bSl_VgLXD diff --git a/src/builtin/obj/subtype.olean b/src/builtin/obj/subtype.olean deleted file mode 100644 index fbadac0369d4841e395f51a2c04e57d0907bd0f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3027 zcma)8%W@k<6z%S@M@lU5SRl)6(j@VN@KhBEumA!SK{iz(n*cl2s6563y%-Hf-oZ~~ z4_=TpuVMk8!T)g2xiiy)k*YFP>N)pz_w92}-|o?DoF>zg(Kt25V@H$uEX&Q;X*NyA zrm*fOxj9Zxj9Yv=%+KekX}b5#RcqWsK@a4Y7>59n`(QR37oi$>TN;EBV06VTIo95Q z8KbcXy-~%^(mCU!i{bH(u*OY>fLYGOs*cgG&`Wp~Fe2OnY{g_@4<~b&rYS#Xbye7n zWVpyzE}5a*#7);XHzGHho+iUlo*o->6MhD7bA;MpLyB!K&Mrgv6hfX3{gu?@);&knl25we0eb{QGmjqzx@XqZ{M%&a9I$t*uL8|Z8l+cgNxv2lE` zZ+Jx5z6k5mnrLBmx`_s&$F2^C>lJTK|G+{M62}!bi35xIWg)QJQ%DmC`@cIX1ojh z0vg>>Aj?eY)NQ;DuO`h|Ev|2>%JR}(Ut3m|6uw$nTM1&BR?`g$I@kx2xCXl$_)uOY zwaRIAQm9DJ`Dk%K#6Dn)0}cQ?gf9Xf9z<@QjIwl@!xZhyqVTZZKvPp{ zFLI~zY&JU?jIvBF4nuvqdh&Gd3nNy|+WLyiZ3F)eD^FFt>2mNS2NOgZ%>EYd0F_Ud zN1v3IN4A28?hzfd+%EE=0`}^f4 zAaiEep_F-+o)mW_m#d_BMMg$-B_PAvDweAWp;7jzCe5`Ia^2aB*o8*(;db-F}PUoM2Za^q2~n)EUCB z>R~E+c&{M_we*S?bT*wEY2PH@Q<5=aUH>MT9?qyq*GVU*Qe{didHx zUB3VF&!+ZoB@p}_V}7M-y!`$OrPK_i^fyL54hgCaC&^u09*LgXdF67XYbouY=noti zLkp%no%dwGrnTn3-+^^s@IK<jhrXkbkB3bL;i$x+ zj`a_~XBeba^*NAM)fa$rSc|0@le@%l|Dd-odnaqxKL+Ov&N_ZpFJ|0F1qZrgm}K)| bDau3f$Qk`~u4^?b)T)rNA5D+%;g9^kp~&!h diff --git a/src/builtin/obj/sum.olean b/src/builtin/obj/sum.olean deleted file mode 100644 index 31758cfe812cb2b7d5afd00208fcd0810cc86f19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8874 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 diff --git a/src/builtin/optional.lean b/src/builtin/optional.lean deleted file mode 100644 index aa7b685fc6..0000000000 --- a/src/builtin/optional.lean +++ /dev/null @@ -1,125 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros subtype -using subtype --- We are encoding the (optional A) as a subset of A → Bool where --- none is the predicate that is false everywhere --- some(a) is the predicate that is true only at a -definition optional_pred (A : (Type U)) := (λ p : A → Bool, (∀ x, ¬ p x) ∨ exists_unique p) -definition optional (A : (Type U)) := subtype (A → Bool) (optional_pred A) - -namespace optional -theorem some_pred {A : (Type U)} (a : A) : optional_pred A (λ x, x = a) -:= or_intror - (∀ x, ¬ x = a) - (exists_intro a - (and_intro (refl a) (take y, assume H : y ≠ a, H))) - -theorem none_pred (A : (Type U)) : optional_pred A (λ x, false) -:= or_introl (take x, not_false_trivial) (exists_unique (λ x, false)) - -theorem inhab (A : (Type U)) : inhabited (optional A) -:= subtype_inhabited (exists_intro (λ x, false) (none_pred A)) - -definition none {A : (Type U)} : optional A -:= abst (λ x, false) (inhab A) - -definition some {A : (Type U)} (a : A) : optional A -:= abst (λ x, x = a) (inhab A) - -definition is_some {A : (Type U)} (n : optional A) := ∃ x : A, some x = n - -theorem injectivity {A : (Type U)} {a a' : A} : some a = some a' → a = a' -:= assume Heq : some a = some a', - have eq_reps : (λ x, x = a) = (λ x, x = a'), - from abst_inj (inhab A) (some_pred a) (some_pred a') Heq, - show a = a', - from (congr1 eq_reps a) ◂ (refl a) - -theorem distinct {A : (Type U)} (a : A) : some a ≠ none -:= not_intro (assume N : some a = none, - have eq_reps : (λ x, x = a) = (λ x, false), - from abst_inj (inhab A) (some_pred a) (none_pred A) N, - show false, - from (congr1 eq_reps a) ◂ (refl a)) - -definition value {A : (Type U)} (n : optional A) (H : is_some n) : A -:= ε (inhabited_ex_intro H) (λ x, some x = n) - -theorem is_some_some {A : (Type U)} (a : A) : is_some (some a) -:= exists_intro a (refl (some a)) - -theorem not_is_some_none {A : (Type U)} : ¬ is_some (@none A) -:= not_intro (assume N : is_some (@none A), - obtain (w : A) (Hw : some w = @none A), - from N, - show false, - from absurd Hw (distinct w)) - -theorem value_some {A : (Type U)} (a : A) (H : is_some (some a)) : value (some a) H = a -:= have eq1 : some (value (some a) H) = some a, - from eps_ax (inhabited_ex_intro H) a (refl (some a)), - show value (some a) H = a, - from injectivity eq1 - -theorem false_pred {A : (Type U)} {p : A → Bool} (H : ∀ x, ¬ p x) : p = λ x, false -:= funext (λ x, eqf_intro (H x)) - -theorem singleton_pred {A : (Type U)} {p : A → Bool} {w : A} (H : p w ∧ ∀ y, y ≠ w → ¬ p y) : p = (λ x, x = w) -:= funext (take x, iff_intro - (assume Hpx : p x, - show x = w, - from by_contradiction (assume N : x ≠ w, - show false, from absurd Hpx (and_elimr H x N))) - (assume Heq : x = w, - show p x, - from subst (and_eliml H) (symm Heq))) - -theorem dichotomy {A : (Type U)} (n : optional A) : n = none ∨ ∃ a, n = some a -:= have pred : optional_pred A (rep n), - from P_rep n, - show n = none ∨ ∃ a, n = some a, - from or_elim pred - (assume Hl : ∀ x : A, ¬ rep n x, - have rep_n_eq : rep n = λ x, false, - from false_pred Hl, - have rep_none_eq : rep none = λ x, false, - from rep_abst (inhab A) (λ x, false) (none_pred A), - show n = none ∨ ∃ a, n = some a, - from or_introl (rep_inj (trans rep_n_eq (symm rep_none_eq))) - (∃ a, n = some a)) - (assume Hr : ∃ x, rep n x ∧ ∀ y, y ≠ x → ¬ rep n y, - obtain (w : A) (Hw : rep n w ∧ ∀ y, y ≠ w → ¬ rep n y), - from Hr, - have rep_n_eq : rep n = λ x, x = w, - from singleton_pred Hw, - have rep_some_eq : rep (some w) = λ x, x = w, - from rep_abst (inhab A) (λ x, x = w) (some_pred w), - have n_eq_some : n = some w, - from rep_inj (trans rep_n_eq (symm rep_some_eq)), - show n = none ∨ ∃ a, n = some a, - from or_intror (n = none) - (exists_intro w n_eq_some)) - -theorem induction {A : (Type U)} {P : optional A → Bool} (H1 : P none) (H2 : ∀ x, P (some x)) : ∀ n, P n -:= take n, or_elim (dichotomy n) - (assume Heq : n = none, - show P n, - from subst H1 (symm Heq)) - (assume Hex : ∃ a, n = some a, - obtain (w : A) (Hw : n = some w), - from Hex, - show P n, - from subst (H2 w) (symm Hw)) - -set_opaque some true -set_opaque none true -set_opaque is_some true -set_opaque value true -end - -set_opaque optional true -set_opaque optional_pred true -definition optional_inhabited := optional::inhab -add_rewrite optional::is_some_some optional::not_is_some_none optional::distinct optional::value_some diff --git a/src/builtin/proof_irrel.lean b/src/builtin/proof_irrel.lean deleted file mode 100644 index 018c00c5c5..0000000000 --- a/src/builtin/proof_irrel.lean +++ /dev/null @@ -1,64 +0,0 @@ -import macros - -definition has_fixpoint (A : Bool) : Bool -:= ∃ F : (A → A) → A, ∀ f : A → A, F f = f (F f) - -theorem eq_arrow (A : Bool) : inhabited A → (A → A) = A -:= assume Hin : inhabited A, - obtain (p : A) (Hp : true), from Hin, - iff_intro - (assume Hl : A → A, p) - (assume Hr : A, (assume H : A, H)) - -theorem bool_fixpoint (A : Bool) : inhabited A → has_fixpoint A -:= assume Hin : inhabited A, - have Heq1 : (A → A) == A, - from (to_heq (eq_arrow A Hin)), - have Heq2 : A == (A → A), - from hsymm Heq1, - let g1 : A → (A → A) := λ x : A, cast Heq2 x, - g2 : (A → A) → A := λ x : A → A, cast Heq1 x, - Y : (A → A) → A := (λ f : A → A, (λ x : A, f (g1 x x)) (g2 (λ x : A, f (g1 x x)))) in - have R : ∀ f, g1 (g2 f) = f, - from take f : A → A, - calc g1 (g2 f) = cast Heq2 (cast Heq1 f) : refl _ - ... = cast (htrans Heq1 Heq2) f : cast_trans _ _ _ - ... = f : cast_eq _ _, - have Fix : (∀ f, Y f = f (Y f)), - from take f : A → A, - let h : A → A := λ x : A, f (g1 x x) in - have H1 : Y f = f (g1 (g2 h) (g2 h)), - from refl (Y f), - have H2 : g1 (g2 h) = h, - from R h, - have H3 : Y f = f (h (g2 h)), - from substp (λ x, Y f = f (x (g2 h))) H1 H2, - have H4 : f (Y f) = f (h (g2 h)), - from refl (f (Y f)), - trans H3 (symm H4), - @exists_intro ((A → A) → A) (λ Y, ∀ f, Y f = f (Y f)) Y Fix - -theorem proof_irrel_new (A : Bool) (p1 p2 : A) : p1 = p2 -:= have H1 : inhabited A, - from inhabited_intro p1, - obtain (Y : (A → A) → A) (HY : ∀ f : A → A, Y f = f (Y f)), from bool_fixpoint A H1, - let h : A → A := (λ x : A, if x = p1 then p2 else p1) in - have HYh : Y h = h (Y h), - from HY h, - or_elim (em (Y h = p1)) - (assume Heq : Y h = p1, - have Heq1 : h (Y h) = p2, - from calc h (Y h) = if Y h = p1 then p2 else p1 : refl _ - ... = if true then p2 else p1 : { eqt_intro Heq } - ... = p2 : if_true _ _, - calc p1 = Y h : symm Heq - ... = h (Y h) : HYh - ... = p2 : Heq1) - (assume Hne : Y h ≠ p1, - have Heq1 : h (Y h) = p1, - from calc h (Y h) = if Y h = p1 then p2 else p1 : refl _ - ... = if false then p2 else p1 : { eqf_intro Hne } - ... = p1 : if_false _ _, - have Heq2 : Y h = p1, - from trans HYh Heq1, - absurd_elim (p1 = p2) Heq2 Hne) diff --git a/src/builtin/quotient.lean b/src/builtin/quotient.lean deleted file mode 100644 index 7d51622978..0000000000 --- a/src/builtin/quotient.lean +++ /dev/null @@ -1,118 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros -import subtype - -definition reflexive {A : Type} (r : A → A → Bool) := ∀ a, r a a -definition symmetric {A : Type} (r : A → A → Bool) := ∀ a b, r a b → r b a -definition transitive {A : Type} (r : A → A → Bool) := ∀ a b c, r a b → r b c → r a c -definition equivalence {A : Type} (r : A → A → Bool) := reflexive r ∧ symmetric r ∧ transitive r - -namespace quotient -definition member {A : Type} (a : A) (S : A → Bool) := S a -infix 50 ∈ : member - -definition eqc {A : Type} (a : A) (r : A → A → Bool) := λ b, r a b - -theorem eqc_mem {A : Type} {a b : A} (r : A → A → Bool) : r a b → b ∈ eqc a r -:= assume H : r a b, H - -theorem eqc_r {A : Type} {a b : A} (r : A → A → Bool) : b ∈ (eqc a r) → r a b -:= assume H : b ∈ (eqc a r), H - -theorem eqc_eq {A : Type} {a b : A} {r : A → A → Bool} : equivalence r → r a b → (eqc a r) = (eqc b r) -:= assume (Heqv : equivalence r) (Hrab : r a b), - have Hsym : symmetric r, - from and_eliml (and_elimr Heqv), - have Htrans : transitive r, - from and_elimr (and_elimr Heqv), - funext (λ x : A, - iff_intro - (assume Hin : x ∈ (eqc a r), - have Hb : r b x, - from Htrans b a x (Hsym a b Hrab) (eqc_r r Hin), - eqc_mem r Hb) - (assume Hin : x ∈ (eqc b r), - have Ha : r a x, - from Htrans a b x Hrab (eqc_r r Hin), - eqc_mem r Ha)) - -definition rep_i {A : Type} (a : A) (r : A → A → Bool) : A -:= ε (inhabited_intro a) (eqc a r) - -theorem r_rep {A : Type} (a : A) (r : A → A → Bool) : reflexive r → r a (rep_i a r) -:= assume R : reflexive r, - eps_ax (inhabited_intro a) a (R a) - -theorem rep_eq {A : Type} {a b : A} {r : A → A → Bool} : equivalence r → r a b → rep_i a r = rep_i b r -:= assume (Heqv : equivalence r) (Hrab : r a b), - have Heq : eqc a r = eqc b r, - from eqc_eq Heqv Hrab, - have Hin : inhabited_intro a = inhabited_intro b, - from proof_irrel (inhabited_intro a) (inhabited_intro b), - calc rep_i a r = ε (inhabited_intro a) (eqc a r) : refl _ - ... = ε (inhabited_intro b) (eqc a r) : { Hin } - ... = ε (inhabited_intro b) (eqc b r) : { Heq } - ... = rep_i b r : refl _ - -theorem rep_rep {A : Type} (a : A) {r : A → A → Bool} : equivalence r → rep_i (rep_i a r) r = rep_i a r -:= assume Heqv : equivalence r, - have Hrefl : reflexive r, - from and_eliml Heqv, - have Hsym : symmetric r, - from and_eliml (and_elimr Heqv), - have Hr : r (rep_i a r) a, - from Hsym _ _ (r_rep a r Hrefl), - rep_eq Heqv Hr - -definition quotient {A : Type} {r : A → A → Bool} (e : equivalence r) -:= subtype A (λ a, rep_i a r = a) - -theorem inhab {A : Type} (Hin : inhabited A) {r : A → A → Bool} (e : equivalence r) : inhabited (quotient e) -:= obtain (a : A) (Ht : true), from Hin, - subtype::subtype_inhabited (exists_intro (rep_i a r) (rep_rep a e)) - -definition abst {A : Type} (a : A) {r : A → A → Bool} (e : equivalence r) : quotient e -:= subtype::abst (rep_i a r) (inhab (inhabited_intro a) e) - -notation 65 [ _ ] _ : abst - -definition rep {A : Type} {r : A → A → Bool} {e : equivalence r} (q : quotient e) : A -:= subtype::rep q - -theorem quotient_eq {A : Type} (a b : A) {r : A → A → Bool} (e : equivalence r) : r a b → [a]e = [b]e -:= assume Hrab : r a b, - have Heq_a : [a]e = subtype::abst (rep_i a r) (inhab (inhabited_intro a) e), - from refl _, - have Heq_b : [b]e = subtype::abst (rep_i b r) (inhab (inhabited_intro b) e), - from refl _, - have Heq_r : rep_i a r = rep_i b r, - from rep_eq e Hrab, - have Heq_pr : inhabited_intro a = inhabited_intro b, - from proof_irrel _ _, - calc [a]e = subtype::abst (rep_i a r) (inhab (inhabited_intro a) e) : Heq_a - ... = subtype::abst (rep_i b r) (inhab (inhabited_intro a) e) : { Heq_r } - ... = subtype::abst (rep_i b r) (inhab (inhabited_intro b) e) : { Heq_pr } - ... = [b]e : symm Heq_b - -theorem quotient_rep {A : Type} (a : A) {r : A → A → Bool} (e : equivalence r) : r a (rep ([a]e)) -:= have Heq1 : [a]e = subtype::abst (rep_i a r) (inhab (inhabited_intro a) e), - from refl ([a]e), - have Heq2 : rep ([a]e) = @rep A r e (subtype::abst (rep_i a r) (inhab (inhabited_intro a) e)), - from congr2 (λ x : quotient e, @rep A r e x) Heq1, - have Heq3 : @rep A r e (subtype::abst (rep_i a r) (inhab (inhabited_intro a) e)) = (rep_i a r), - from subtype::rep_abst (inhab (inhabited_intro a) e) (rep_i a r) (rep_rep a e), - have Heq4 : rep ([a]e) = (rep_i a r), - from trans Heq2 Heq3, - have Hr : r a (rep_i a r), - from r_rep a r (and_eliml e), - subst Hr (symm Heq4) - -set_opaque eqc true -set_opaque rep_i true -set_opaque quotient true -set_opaque abst true -set_opaque rep true -end -definition quotient {A : Type} {r : A → A → Bool} (e : equivalence r) := quotient::quotient e diff --git a/src/builtin/repl.lua b/src/builtin/repl.lua deleted file mode 100644 index cfaaeb1885..0000000000 --- a/src/builtin/repl.lua +++ /dev/null @@ -1,36 +0,0 @@ --- Simple read-eval-print loop for Lean Lua frontend -local function trim(s) - return s:gsub('^%s+', ''):gsub('%s+$', '') -end - -local function show_results(...) - if select('#', ...) > 1 then - print(select(2, ...)) - end -end - -print([[Type 'exit' to exit.]]) -repeat - io.write'lean > ' - local s = io.read() - if s == nil then print(); break end - if trim(s) == 'exit' then break end - local f, err = loadstring(s, 'stdin') - if err then - f = loadstring('return (' .. s .. ')', 'stdin') - end - if f then - local ok, err = pcall(f) - if not ok then - if is_exception(err) then - print(err:what()) - else - print(err) - end - else - if err then print(err) end - end - else - print(err) - end -until false diff --git a/src/builtin/specialfn.lean b/src/builtin/specialfn.lean deleted file mode 100644 index 95f4e4e714..0000000000 --- a/src/builtin/specialfn.lean +++ /dev/null @@ -1,19 +0,0 @@ -import Real. - -variable exp : Real → Real. -variable log : Real → Real. -variable pi : Real. -alias π : pi. - -variable sin : Real → Real. -definition cos x := sin (x - π / 2). -definition tan x := sin x / cos x. -definition cot x := cos x / sin x. -definition sec x := 1 / cos x. -definition csc x := 1 / sin x. -definition sinh x := (1 - exp (-2 * x)) / (2 * exp (- x)). -definition cosh x := (1 + exp (-2 * x)) / (2 * exp (- x)). -definition tanh x := sinh x / cosh x. -definition coth x := cosh x / sinh x. -definition sech x := 1 / cosh x. -definition csch x := 1 / sinh x. diff --git a/src/builtin/subtype.lean b/src/builtin/subtype.lean deleted file mode 100644 index 505b92b69e..0000000000 --- a/src/builtin/subtype.lean +++ /dev/null @@ -1,52 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros --- Simulate "subtypes" using Sigma types and proof irrelevance -definition subtype (A : (Type U)) (P : A → Bool) := sig x, P x - -namespace subtype -definition rep {A : (Type U)} {P : A → Bool} (a : subtype A P) : A -:= proj1 a - -definition abst {A : (Type U)} {P : A → Bool} (r : A) (H : inhabited (subtype A P)) : subtype A P -:= ε H (λ a, rep a = r) - -theorem subtype_inhabited {A : (Type U)} {P : A → Bool} (H : ∃ x, P x) : inhabited (subtype A P) -:= obtain (w : A) (Hw : P w), from H, - inhabited_intro (pair w Hw) - -theorem P_rep {A : (Type U)} {P : A → Bool} (a : subtype A P) : P (rep a) -:= proj2 a - -theorem rep_inj {A : (Type U)} {P : A → Bool} {a b : subtype A P} (H : rep a = rep b) : a = b -:= pairext _ _ H (hproof_irrel (proj2 a) (proj2 b)) - -theorem ex_abst {A : (Type U)} {P : A → Bool} {r : A} (H : P r) : ∃ a, rep a = r -:= exists_intro (pair r H) (refl r) - -theorem abst_rep {A : (Type U)} {P : A → Bool} (H : inhabited (subtype A P)) (a : subtype A P) - : abst (rep a) H = a -:= let s1 : rep (abst (rep a) H) = rep a := - @eps_ax (subtype A P) H (λ x, rep x = rep a) a (refl (rep a)) - in rep_inj s1 - -theorem rep_abst {A : (Type U)} {P : A → Bool} (H : inhabited (subtype A P)) : ∀ r, P r → rep (abst r H) = r -:= take r, assume Hl : P r, - @eps_ax (subtype A P) H (λ x, rep x = r) (pair r Hl) (refl r) - -theorem abst_inj {A : (Type U)} {P : A → Bool} (H : inhabited (subtype A P)) {r r' : A} : - P r → P r' → abst r H = abst r' H → r = r' -:= assume Hr Hr' Heq, - calc r = rep (abst r H) : symm (rep_abst H r Hr) - ... = rep (abst r' H) : { Heq } - ... = r' : rep_abst H r' Hr' - -theorem ex_rep {A : (Type U)} {P : A → Bool} (H : inhabited (subtype A P)) : - ∀ a, ∃ r, abst r H = a ∧ P r -:= take a, exists_intro (rep a) (and_intro (abst_rep H a) (proj2 a)) - -set_opaque rep true -set_opaque abst true -end -- namespace subtype -set_opaque subtype true diff --git a/src/builtin/sum.lean b/src/builtin/sum.lean deleted file mode 100644 index abfc2e50f5..0000000000 --- a/src/builtin/sum.lean +++ /dev/null @@ -1,137 +0,0 @@ --- Copyright (c) 2014 Microsoft Corporation. All rights reserved. --- Released under Apache 2.0 license as described in the file LICENSE. --- Author: Leonardo de Moura -import macros subtype optional -using subtype -using optional - --- We are encoding the (sum A B) as a subtype of (optional A) # (optional B), where --- (proj1 n = none) ≠ (proj2 n = none) -definition sum_pred (A B : (Type U)) := λ p : (optional A) # (optional B), (proj1 p = none) ≠ (proj2 p = none) -definition sum (A B : (Type U)) := subtype ((optional A) # (optional B)) (sum_pred A B) - -namespace sum -theorem inl_pred {A : (Type U)} (a : A) (B : (Type U)) : sum_pred A B (pair (some a) none) -:= not_intro - (assume N : (some a = none) = (none = (@none B)), - have eq : some a = none, - from (symm N) ◂ (refl (@none B)), - show false, - from absurd eq (distinct a)) - -theorem inr_pred (A : (Type U)) {B : (Type U)} (b : B) : sum_pred A B (pair none (some b)) -:= not_intro - (assume N : (none = (@none A)) = (some b = none), - have eq : some b = none, - from N ◂ (refl (@none A)), - show false, - from absurd eq (distinct b)) - -theorem inhabl {A : (Type U)} (H : inhabited A) (B : (Type U)) : inhabited (sum A B) -:= inhabited_elim H (take w : A, - subtype_inhabited (exists_intro (pair (some w) none) (inl_pred w B))) - -theorem inhabr (A : (Type U)) {B : (Type U)} (H : inhabited B) : inhabited (sum A B) -:= inhabited_elim H (take w : B, - subtype_inhabited (exists_intro (pair none (some w)) (inr_pred A w))) - -definition inl {A : (Type U)} (a : A) (B : (Type U)) : sum A B -:= abst (pair (some a) none) (inhabl (inhabited_intro a) B) - -definition inr (A : (Type U)) {B : (Type U)} (b : B) : sum A B -:= abst (pair none (some b)) (inhabr A (inhabited_intro b)) - -theorem inl_inj {A B : (Type U)} {a1 a2 : A} : inl a1 B = inl a2 B → a1 = a2 -:= assume Heq : inl a1 B = inl a2 B, - have eq1 : inl a1 B = abst (pair (some a1) none) (inhabl (inhabited_intro a1) B), - from refl (inl a1 B), - have eq2 : inl a2 B = abst (pair (some a2) none) (inhabl (inhabited_intro a1) B), - from subst (refl (inl a2 B)) (proof_irrel (inhabl (inhabited_intro a2) B) (inhabl (inhabited_intro a1) B)), - have rep_eq : (pair (some a1) none) = (pair (some a2) none), - from abst_inj (inhabl (inhabited_intro a1) B) (inl_pred a1 B) (inl_pred a2 B) (trans (trans (symm eq1) Heq) eq2), - show a1 = a2, - from optional::injectivity - (calc some a1 = proj1 (pair (some a1) (@none B)) : refl (some a1) - ... = proj1 (pair (some a2) (@none B)) : proj1_congr rep_eq - ... = some a2 : refl (some a2)) - -theorem inr_inj {A B : (Type U)} {b1 b2 : B} : inr A b1 = inr A b2 → b1 = b2 -:= assume Heq : inr A b1 = inr A b2, - have eq1 : inr A b1 = abst (pair none (some b1)) (inhabr A (inhabited_intro b1)), - from refl (inr A b1), - have eq2 : inr A b2 = abst (pair none (some b2)) (inhabr A (inhabited_intro b1)), - from subst (refl (inr A b2)) (proof_irrel (inhabr A (inhabited_intro b2)) (inhabr A (inhabited_intro b1))), - have rep_eq : (pair none (some b1)) = (pair none (some b2)), - from abst_inj (inhabr A (inhabited_intro b1)) (inr_pred A b1) (inr_pred A b2) (trans (trans (symm eq1) Heq) eq2), - show b1 = b2, - from optional::injectivity - (calc some b1 = proj2 (pair (@none A) (some b1)) : refl (some b1) - ... = proj2 (pair (@none A) (some b2)) : proj2_congr rep_eq - ... = some b2 : refl (some b2)) - -theorem distinct {A B : (Type U)} (a : A) (b : B) : inl a B ≠ inr A b -:= not_intro (assume N : inl a B = inr A b, - have eq1 : inl a B = abst (pair (some a) none) (inhabl (inhabited_intro a) B), - from refl (inl a B), - have eq2 : inr A b = abst (pair none (some b)) (inhabl (inhabited_intro a) B), - from subst (refl (inr A b)) (proof_irrel (inhabr A (inhabited_intro b)) (inhabl (inhabited_intro a) B)), - have rep_eq : (pair (some a) none) = (pair none (some b)), - from abst_inj (inhabl (inhabited_intro a) B) (inl_pred a B) (inr_pred A b) (trans (trans (symm eq1) N) eq2), - show false, - from absurd (proj1_congr rep_eq) (optional::distinct a)) - -theorem dichotomy {A B : (Type U)} (n : sum A B) : (∃ a, n = inl a B) ∨ (∃ b, n = inr A b) -:= let pred : (proj1 (rep n) = none) ≠ (proj2 (rep n) = none) := P_rep n - in or_elim (em (proj1 (rep n) = none)) - (assume Heq : proj1 (rep n) = none, - have neq_none : ¬ proj2 (rep n) = (@none B), - from (symm (not_iff_elim (ne_symm pred))) ◂ Heq, - have ex_some : ∃ b, proj2 (rep n) = some b, - from resolve1 (optional::dichotomy (proj2 (rep n))) neq_none, - obtain (b : B) (Hb : proj2 (rep n) = some b), - from ex_some, - show (∃ a, n = inl a B) ∨ (∃ b, n = inr A b), - from or_intror (∃ a, n = inl a B) - (have rep_eq : rep n = pair none (some b), - from pairext_proj Heq Hb, - have rep_inr : rep (inr A b) = pair none (some b), - from rep_abst (inhabr A (inhabited_intro b)) (pair none (some b)) (inr_pred A b), - have n_eq_inr : n = inr A b, - from rep_inj (trans rep_eq (symm rep_inr)), - show (∃ b, n = inr A b), - from exists_intro b n_eq_inr)) - (assume Hne : ¬ proj1 (rep n) = none, - have eq_none : proj2 (rep n) = (@none B), - from (not_iff_elim pred) ◂ Hne, - have ex_some : ∃ a, proj1 (rep n) = some a, - from resolve1 (optional::dichotomy (proj1 (rep n))) Hne, - obtain (a : A) (Ha : proj1 (rep n) = some a), - from ex_some, - show (∃ a, n = inl a B) ∨ (∃ b, n = inr A b), - from or_introl - (have rep_eq : rep n = pair (some a) none, - from pairext_proj Ha eq_none, - have rep_inl : rep (inl a B) = pair (some a) none, - from rep_abst (inhabl (inhabited_intro a) B) (pair (some a) none) (inl_pred a B), - have n_eq_inl : n = inl a B, - from rep_inj (trans rep_eq (symm rep_inl)), - show ∃ a, n = inl a B, - from exists_intro a n_eq_inl) - (∃ b, n = inr A b)) - -theorem induction {A B : (Type U)} {P : sum A B → Bool} (H1 : ∀ a, P (inl a B)) (H2 : ∀ b, P (inr A b)) : ∀ n, P n -:= take n, or_elim (sum::dichotomy n) - (assume Hex : ∃ a, n = inl a B, - obtain (a : A) (Ha : n = inl a B), from Hex, - show P n, - from subst (H1 a) (symm Ha)) - (assume Hex : ∃ b, n = inr A b, - obtain (b : B) (Hb : n = inr A b), from Hex, - show P n, - from subst (H2 b) (symm Hb)) - -set_opaque inl true -set_opaque inr true -end -set_opaque sum_pred true -set_opaque sum true diff --git a/src/builtin/sum2.lean b/src/builtin/sum2.lean deleted file mode 100644 index d57843fa31..0000000000 --- a/src/builtin/sum2.lean +++ /dev/null @@ -1,91 +0,0 @@ -import macros tactic - -namespace sum -definition sum (A B : Type) := sig b : Bool, if b then A else B - -theorem sum_if_l (A B : Type) : A == if true then A else B -:= by simp - -theorem sum_if_r (A B : Type) : B == if false then A else B -:= by simp - -definition inl {A : Type} (a : A) (B : Type) : sum A B -:= pair true (cast (sum_if_l A B) a) - -definition inr (A : Type) {B : Type} (b : B) : sum A B -:= pair false (cast (sum_if_r A B) b) - -theorem cast_eq_cast {A B1 B2 : Type} {H1 : A == B1} {H2 : A == B2} {a1 a2 : A} (H : cast H1 a1 == cast H2 a2) : a1 = a2 -:= have S1 : cast H1 a1 == a1, - from cast_heq H1 a1, - have S2 : cast H2 a2 == a2, - from cast_heq H2 a2, - to_eq (htrans (htrans (hsymm S1) H) S2) - -theorem inl_inj {A B : Type} {a1 a2 : A} : inl a1 B = inl a2 B → a1 = a2 -:= assume H : inl a1 B = inl a2 B, - have H1 : (cast _ a1) == (cast _ a2), - from hproj2_congr H, - cast_eq_cast H1 - -theorem inr_inj {A B : Type} {b1 b2 : B} : inr A b1 = inr A b2 → b1 = b2 -:= assume H : inr A b1 = inr A b2, - have H1 : (cast _ b1) == (cast _ b2), - from hproj2_congr H, - cast_eq_cast H1 - -theorem distinct {A B : Type} (a : A) (b : B) : inl a B ≠ inr A b -:= not_intro (assume N : inl a B = inr A b, - absurd (proj1_congr N) true_ne_false) - -theorem dichotomy {A B : Type} (n : sum A B) : (∃ a, n = inl a B) ∨ (∃ b, n = inr A b) -:= or_elim (em (proj1 n)) - (assume H : proj1 n, - have H1n : proj1 n = true, - from eqt_intro H, - have Haux : (if (proj1 n) then A else B) = A, - from calc (if (proj1 n) then A else B) = if true then A else B : { H1n } - ... = A : if_true _ _, - let a : A := cast (to_heq Haux) (proj2 n) in - have H1i : proj1 (inl a B) = true, - from refl _, - have H2n : proj2 n == a, - from hsymm (cast_heq (to_heq Haux) (proj2 n)), - have H2i : proj2 (inl a B) == a, - from cast_heq (sum_if_l A B) a, - have Heq : n = (inl a B), - from pairext n (inl a B) (trans H1n (symm H1i)) (htrans H2n (hsymm H2i)), - or_introl (exists_intro a Heq) (∃ b, n = inr A b)) - (assume H : ¬ proj1 n, - have H1n : proj1 n = false, - from eqf_intro H, - have Haux : (if (proj1 n) then A else B) = B, - from calc (if (proj1 n) then A else B) = if false then A else B : { H1n } - ... = B : if_false _ _, - let b : B := cast (to_heq Haux) (proj2 n) in - have H1i : proj1 (inr A b) = false, - from refl _, - have H2n : proj2 n == b, - from hsymm (cast_heq (to_heq Haux) (proj2 n)), - have H2i : proj2 (inr A b) == b, - from cast_heq (sum_if_r A B) b, - have Heq : n = (inr A b), - from pairext n (inr A b) (trans H1n (symm H1i)) (htrans H2n (hsymm H2i)), - or_intror (∃ a, n = inl a B) (exists_intro b Heq)) - -theorem induction {A B : Type} {P : sum A B → Bool} (H1 : ∀ a, P (inl a B)) (H2 : ∀ b, P (inr A b)) : ∀ n, P n -:= take n, or_elim (dichotomy n) - (assume Hex : ∃ a, n = inl a B, - obtain (a : A) (Ha : n = inl a B), from Hex, - show P n, - from subst (H1 a) (symm Ha)) - (assume Hex : ∃ b, n = inr A b, - obtain (b : B) (Hb : n = inr A b), from Hex, - show P n, - from subst (H2 b) (symm Hb)) - -set_opaque inl true -set_opaque inr true -set_opaque sum true -end -definition sum := sum::sum \ No newline at end of file diff --git a/src/builtin/tactic.lua b/src/builtin/tactic.lua deleted file mode 100644 index c7f852e3b0..0000000000 --- a/src/builtin/tactic.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Define macros for simplifying Tactic creation -local unary_combinator = function (name, fn) tactic_macro(name, { macro_arg.Tactic }, function (env, t) return fn(t) end) end -local nary_combinator = function (name, fn) tactic_macro(name, { macro_arg.Tactics }, function (env, ts) return fn(unpack(ts)) end) end -local const_tactic = function (name, fn) tactic_macro(name, {}, function (env) return fn() end) end - -unary_combinator("Repeat", Repeat) -unary_combinator("Try", Try) -nary_combinator("Then", Then) -nary_combinator("OrElse", OrElse) -const_tactic("exact", assumption_tac) -const_tactic("trivial", trivial_tac) -const_tactic("id", id_tac) -const_tactic("absurd", absurd_tac) -const_tactic("conj_hyp", conj_hyp_tac) -const_tactic("disj_hyp", disj_hyp_tac) -const_tactic("unfold_all", unfold_tac) -const_tactic("beta", beta_tac) -tactic_macro("apply", { macro_arg.Expr }, function (env, e) return apply_tac(e) end) -tactic_macro("unfold", { macro_arg.Id }, function (env, id) return unfold_tac(id) end) - -tactic_macro("simp", { macro_arg.Ids }, - function (env, ids) - if #ids == 0 then - ids[1] = "default" - end - return simp_tac(ids) - end -) - -tactic_macro("simp_no_assump", { macro_arg.Ids }, - function (env, ids) - if #ids == 0 then - ids[1] = "default" - end - return simp_tac(ids, options({"simp_tac", "assumptions"}, false)) - end -) - --- Create a 'bogus' tactic that consume all goals, but it does not create a valid proof. --- This tactic is useful for momentarily ignoring/skipping a "hole" in a big proof. --- Remark: the kernel will not accept a proof built using this tactic. -skip_tac = tactic(function (env, ios, s) - local gs = s:goals() - local pb = s:proof_builder() - local buggy_pr = mk_constant("invalid proof built using skip tactic") - local new_pb = - function(m, a) - -- We provide a "fake/incorrect" proof for all goals in gs - local new_m = proof_map(m) -- Copy proof map m - for n, g in gs:pairs() do - new_m:insert(n, buggy_pr) - end - return pb(new_m, a) - end - local new_gs = {} - return proof_state(s, goals(new_gs), proof_builder(new_pb)) - end) - -const_tactic("skip", function() return skip_tac end) diff --git a/src/builtin/template.lua b/src/builtin/template.lua deleted file mode 100644 index 5054253b28..0000000000 --- a/src/builtin/template.lua +++ /dev/null @@ -1,31 +0,0 @@ --- Parse a template expression string 'str'. --- The string 'str' may contain placeholders of the form '% i', where 'i' is a numeral. --- The placeholders are replaced with values from the array 'arg_array'. -local arg_array = {} - --- We implement this feature using macros available in Lean. -macro("%", - { macro_arg.Int }, - function (env, i) - if i <= 0 then - error("invalid template argument reference %" .. i .. ", first argument is 1") - elseif i > #arg_array then - error("invalid template argument reference %" .. i .. ", only " .. tostring(#arg_array) .. " argument(s) were provided") - else - return arg_array[i] - end - end -) - --- Parse a template. --- Example: --- r = parse_template("%1 + %2 + %1", {Const("a"), Const("b")}) --- print(r) --- >> a + b + a -function parse_template(str, args, env, opts, fmt) - assert(type(str) == "string") - assert(type(args) == "table") - assert(env == nil or is_environment(env)) - arg_array = args - return parse_lean(str, env, opts, fmt) -end diff --git a/src/builtin/util.lua b/src/builtin/util.lua deleted file mode 100644 index b331688203..0000000000 --- a/src/builtin/util.lua +++ /dev/null @@ -1,16 +0,0 @@ --- Extra useful functions - --- Create sequence of expressions. --- Examples: --- local a, b, c = Consts("a,b,c") --- We can use ';', ' ', ',', tabs ad line breaks for separating the constant names --- local a, b, c = Consts("a b c") -function Consts(s) - local r = {} - local i = 1 - for c in string.gmatch(s, '[^ ,;\t\n]+') do - r[i] = Const(c) - i = i + 1 - end - return unpack(r) -end