refactor(builtin/kernel): define if-then-else using Hilbert's operator

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-30 19:11:58 -08:00
parent b45ab9dc30
commit 759aa61f70
28 changed files with 201 additions and 296 deletions

View file

@ -34,20 +34,13 @@ eval s + 1
## Function applications
In Lean, the expression `f t` is a function application, where `f` is a function that is applied to `t`.
In the following example, we define the function `max`. The `eval` command evaluates the application `max 1 2`,
and returns the value `2`. Note that, the expression `if (x >= y) then x else y` is also a function application.
It is notation for `ite (x >= y) x y`.
In the following example, we define the function `max`. The `eval` command evaluates the application `double 3`,
and returns the value `6`.
```lean
import if_then_else
definition max (x y : Nat) : Nat := if (x >= y) then x else y
eval max 1 2
```
The expression `max 1` is also a valid expression in Lean, and it has type `Nat -> Nat`.
```lean
check max 1
import tactic -- load basic tactics such as 'simp'
definition double (x : Nat) : Nat := x + x
eval double 3
```
In the following command, we define the function `inc`, and evaluate some expressions using `inc` and `max`.
@ -55,5 +48,5 @@ In the following command, we define the function `inc`, and evaluate some expres
```lean
definition inc (x : Nat) : Nat := x + 1
eval inc (inc (inc 2))
eval max (inc 2) 2 = 3
eval double (inc 3)
```

View file

@ -89,8 +89,7 @@ endfunction()
add_kernel_theory("kernel.lean" "${CMAKE_CURRENT_BINARY_DIR}/macros.lua")
add_kernel_theory("Nat.lean" "${CMAKE_CURRENT_BINARY_DIR}/kernel.olean")
add_theory("if_then_else.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean")
add_theory("Int.lean" "${CMAKE_CURRENT_BINARY_DIR}/if_then_else.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("heq.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean")
@ -100,6 +99,5 @@ 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" "")
update_interface("if_then_else.olean" "library" "")
update_interface("heq.olean" "library" "")
update_interface("cast.olean" "library" "")

View file

@ -1,5 +1,4 @@
import Nat
import if_then_else
variable Int : Type
alias : Int

View file

@ -1,5 +1,4 @@
import Int
import if_then_else
variable Real : Type
alias : Real

View file

@ -1,62 +0,0 @@
import macros
-- if_then_else expression support
builtin ite {A : (Type U)} : Bool → A → A → A
notation 45 if _ then _ else _ : ite
axiom if_true {A : TypeU} (a b : A) : (if true then a else b) = a
axiom if_false {A : TypeU} (a b : A) : (if false then a else b) = b
theorem if_a_a {A : TypeU} (c : Bool) (a : A) : (if c then a else a) = a
:= case (λ x, (if x then a else a) = a) (if_true a a) (if_false a a) c
-- Simplify the then branch using the fact that c is true, and the else branch that c is false
theorem if_congr {A : TypeU} {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 : TypeU} (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 : TypeU} (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 : TypeU} (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 ite true

View file

@ -1,4 +1,5 @@
import macros
import tactic
universe U ≥ 1
definition TypeU := (Type U)
@ -72,14 +73,24 @@ axiom eps_ax {A : TypeU} (H : nonempty A) {P : A → Bool} (a : A) : P a → P (
-- Proof irrelevance
axiom proof_irrel {a : Bool} (H1 H2 : a) : H1 = H2
theorem eps_th {A : TypeU} {P : A → Bool} (a : A) : P a → P (ε (nonempty_intro a) P)
:= assume H : P a, @eps_ax A (nonempty_intro a) P a H
-- Alias for subst where we can provide P explicitly, but keep A,a,b implicit
theorem substp {A : TypeU} {a b : A} (P : A → Bool) (H1 : P a) (H2 : a = b) : P b
:= subst H1 H2
-- We will mark not as opaque later
theorem eps_th {A : TypeU} {P : A → Bool} (a : A) : P a → P (ε (nonempty_intro a) P)
:= assume H : P a, @eps_ax A (nonempty_intro a) P a H
theorem eps_singleton {A : TypeU} (H : nonempty A) (a : A) : ε H (λ x, x = a) = a
:= let P := λ x, x = a,
Ha : P a := refl a
in eps_ax H a Ha
-- if-then-else expression
definition ite {A : TypeU} (c : Bool) (a b : A) : A
:= ε (nonempty_intro a) (λ r, (c → r = a) ∧ (¬ c → r = b))
notation 45 if _ then _ else _ : ite
-- We will mark 'not' as opaque later
theorem not_intro {a : Bool} (H : a → false) : ¬ a
:= H
@ -119,6 +130,8 @@ theorem eq_imp_trans {a b c : Bool} (H1 : a = b) (H2 : b → c) : a → c
theorem not_not_eq (a : Bool) : ¬ ¬ a ↔ a
:= case (λ x, ¬ ¬ x ↔ x) trivial trivial a
add_rewrite not_not_eq
theorem not_not_elim {a : Bool} (H : ¬ ¬ a) : a
:= (not_not_eq a) ◂ H
@ -273,6 +286,15 @@ theorem eq_id {A : TypeU} (a : A) : (a = a) ↔ true
theorem iff_id (a : Bool) : (a ↔ a) ↔ true
:= eqt_intro (refl a)
add_rewrite eq_id iff_id
-- Remark: ordered rewriting + assoc + comm + left_comm sorts a term lexicographically
theorem left_comm {A : TypeU} {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))
@ -307,6 +329,11 @@ theorem or_truer (a : Bool) : a true ↔ true
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))
@ -337,6 +364,11 @@ 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
:= case (λ x, (x → true) ↔ true) trivial trivial a
@ -352,6 +384,8 @@ theorem imp_falsel (a : Bool) : (false → a) ↔ true
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
:= iff_intro
(assume H : a → b,
@ -371,6 +405,8 @@ theorem not_false : ¬ false ↔ true
theorem not_neq {A : TypeU} (a b : A) : ¬ (a ≠ b) ↔ a = b
:= not_not_eq (a = b)
add_rewrite not_true not_false not_neq
theorem not_neq_elim {A : TypeU} {a b : A} (H : ¬ (a ≠ b)) : a = b
:= (not_neq a b) ◂ H
@ -464,20 +500,6 @@ theorem exists_unfold {A : TypeU} (P : A → Bool) (a : 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)
-- Remark: ordered rewriting + assoc + comm + left_comm sorts a term lexicographically
theorem left_comm {A : TypeU} {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 and_left_comm (a b c : Bool) : a ∧ (b ∧ c) ↔ b ∧ (a ∧ c)
:= left_comm and_comm and_assoc a b c
theorem or_left_comm (a b c : Bool) : a (b c) ↔ b (a c)
:= left_comm or_comm or_assoc a b c
-- Congruence theorems for contextual simplification
-- Simplify a → b, by first simplifying a to c using the fact that ¬ b is true, and then
@ -487,11 +509,11 @@ theorem imp_congrr {a b c d : Bool} (H_ac : ∀ (H_nb : ¬ b), a = c) (H_bd :
(λ 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 })
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
@ -624,8 +646,74 @@ theorem exists_imp_distribute {A : TypeU} (φ ψ : A → Bool) : (∃ x, φ x
... = ¬ (∀ x, φ x) (∃ x, ψ x) : { symm (not_forall A φ) }
... = (∀ x, φ x) → (∃ x, ψ x) : symm (imp_or _ _)
theorem if_true {A : TypeU} (a b : A) : (if true then a else b) = a
:= calc (if true then a else b) = ε (nonempty_intro a) (λ r, (true → r = a) ∧ (¬ true → r = b)) : refl (if true then a else b)
... = ε (nonempty_intro a) (λ r, r = a) : by simp
... = a : eps_singleton (nonempty_intro a) a
theorem if_false {A : TypeU} (a b : A) : (if false then a else b) = b
:= calc (if false then a else b) = ε (nonempty_intro a) (λ r, (false → r = a) ∧ (¬ false → r = b)) : refl (if false then a else b)
... = ε (nonempty_intro a) (λ r, r = b) : by simp
... = b : eps_singleton (nonempty_intro a) b
theorem if_a_a {A : TypeU} (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)
theorem if_congr {A : TypeU} {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 : TypeU} (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 : TypeU} (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 : TypeU} (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 implies true
set_opaque ite true

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -20,7 +20,6 @@ Author: Leonardo de Moura
#include "kernel/kernel.h"
#include "kernel/io_state.h"
#include "library/io_state_stream.h"
#include "library/ite.h"
#include "library/expr_pair.h"
#include "library/expr_pair_maps.h"
#include "library/arith/nat.h"
@ -557,7 +556,6 @@ io_state init_frontend(environment const & env, bool no_kernel) {
io_state init_test_frontend(environment const & env) {
env->set_trusted_imported(true);
io_state ios = init_frontend(env);
import_ite(env, ios);
import_int(env, ios);
import_real(env, ios);
return ios;

View file

@ -26,8 +26,10 @@ MK_CONSTANT(allext_fn, name("allext"));
MK_CONSTANT(eps_fn, name("eps"));
MK_CONSTANT(eps_ax_fn, name("eps_ax"));
MK_CONSTANT(proof_irrel_fn, name("proof_irrel"));
MK_CONSTANT(eps_th_fn, name("eps_th"));
MK_CONSTANT(substp_fn, name("substp"));
MK_CONSTANT(eps_th_fn, name("eps_th"));
MK_CONSTANT(eps_singleton_fn, name("eps_singleton"));
MK_CONSTANT(ite_fn, name("ite"));
MK_CONSTANT(not_intro_fn, name("not_intro"));
MK_CONSTANT(eta_fn, name("eta"));
MK_CONSTANT(trivial, name("trivial"));
@ -80,6 +82,7 @@ MK_CONSTANT(eqf_intro_fn, name("eqf_intro"));
MK_CONSTANT(neq_elim_fn, name("neq_elim"));
MK_CONSTANT(eq_id_fn, name("eq_id"));
MK_CONSTANT(iff_id_fn, name("iff_id"));
MK_CONSTANT(left_comm_fn, name("left_comm"));
MK_CONSTANT(or_comm_fn, name("or_comm"));
MK_CONSTANT(or_assoc_fn, name("or_assoc"));
MK_CONSTANT(or_id_fn, name("or_id"));
@ -88,6 +91,7 @@ MK_CONSTANT(or_falser_fn, name("or_falser"));
MK_CONSTANT(or_truel_fn, name("or_truel"));
MK_CONSTANT(or_truer_fn, name("or_truer"));
MK_CONSTANT(or_tauto_fn, name("or_tauto"));
MK_CONSTANT(or_left_comm_fn, name("or_left_comm"));
MK_CONSTANT(and_comm_fn, name("and_comm"));
MK_CONSTANT(and_id_fn, name("and_id"));
MK_CONSTANT(and_assoc_fn, name("and_assoc"));
@ -96,6 +100,7 @@ MK_CONSTANT(and_truel_fn, name("and_truel"));
MK_CONSTANT(and_falsel_fn, name("and_falsel"));
MK_CONSTANT(and_falser_fn, name("and_falser"));
MK_CONSTANT(and_absurd_fn, name("and_absurd"));
MK_CONSTANT(and_left_comm_fn, name("and_left_comm"));
MK_CONSTANT(imp_truer_fn, name("imp_truer"));
MK_CONSTANT(imp_truel_fn, name("imp_truel"));
MK_CONSTANT(imp_falser_fn, name("imp_falser"));
@ -125,9 +130,6 @@ MK_CONSTANT(not_exists_elim_fn, name("not_exists_elim"));
MK_CONSTANT(exists_unfold1_fn, name("exists_unfold1"));
MK_CONSTANT(exists_unfold2_fn, name("exists_unfold2"));
MK_CONSTANT(exists_unfold_fn, name("exists_unfold"));
MK_CONSTANT(left_comm_fn, name("left_comm"));
MK_CONSTANT(and_left_comm_fn, name("and_left_comm"));
MK_CONSTANT(or_left_comm_fn, name("or_left_comm"));
MK_CONSTANT(imp_congrr_fn, name("imp_congrr"));
MK_CONSTANT(imp_congrl_fn, name("imp_congrl"));
MK_CONSTANT(imp_congr_fn, name("imp_congr"));
@ -144,4 +146,13 @@ MK_CONSTANT(exists_and_distributer_fn, name("exists_and_distributer"));
MK_CONSTANT(exists_and_distributel_fn, name("exists_and_distributel"));
MK_CONSTANT(exists_or_distribute_fn, name("exists_or_distribute"));
MK_CONSTANT(exists_imp_distribute_fn, name("exists_imp_distribute"));
MK_CONSTANT(if_true_fn, name("if_true"));
MK_CONSTANT(if_false_fn, name("if_false"));
MK_CONSTANT(if_a_a_fn, name("if_a_a"));
MK_CONSTANT(if_congr_fn, name("if_congr"));
MK_CONSTANT(if_imp_then_fn, name("if_imp_then"));
MK_CONSTANT(if_imp_else_fn, name("if_imp_else"));
MK_CONSTANT(app_if_distribute_fn, name("app_if_distribute"));
MK_CONSTANT(eq_if_distributer_fn, name("eq_if_distributer"));
MK_CONSTANT(eq_if_distributel_fn, name("eq_if_distributel"));
}

View file

@ -72,12 +72,19 @@ inline expr mk_eps_ax_th(expr const & e1, expr const & e2, expr const & e3, expr
expr mk_proof_irrel_fn();
bool is_proof_irrel_fn(expr const & e);
inline expr mk_proof_irrel_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_proof_irrel_fn(), e1, e2, e3}); }
expr mk_eps_th_fn();
bool is_eps_th_fn(expr const & e);
inline expr mk_eps_th_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({mk_eps_th_fn(), e1, e2, e3, e4}); }
expr mk_substp_fn();
bool is_substp_fn(expr const & e);
inline expr mk_substp_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_substp_fn(), e1, e2, e3, e4, e5, e6}); }
expr mk_eps_th_fn();
bool is_eps_th_fn(expr const & e);
inline expr mk_eps_th_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({mk_eps_th_fn(), e1, e2, e3, e4}); }
expr mk_eps_singleton_fn();
bool is_eps_singleton_fn(expr const & e);
inline expr mk_eps_singleton_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_eps_singleton_fn(), e1, e2, e3}); }
expr mk_ite_fn();
bool is_ite_fn(expr const & e);
inline bool is_ite(expr const & e) { return is_app(e) && is_ite_fn(arg(e, 0)) && num_args(e) == 5; }
inline expr mk_ite(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({mk_ite_fn(), e1, e2, e3, e4}); }
expr mk_not_intro_fn();
bool is_not_intro_fn(expr const & e);
inline expr mk_not_intro_th(expr const & e1, expr const & e2) { return mk_app({mk_not_intro_fn(), e1, e2}); }
@ -233,6 +240,9 @@ inline expr mk_eq_id_th(expr const & e1, expr const & e2) { return mk_app({mk_eq
expr mk_iff_id_fn();
bool is_iff_id_fn(expr const & e);
inline expr mk_iff_id_th(expr const & e1) { return mk_app({mk_iff_id_fn(), e1}); }
expr mk_left_comm_fn();
bool is_left_comm_fn(expr const & e);
inline expr mk_left_comm_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7) { return mk_app({mk_left_comm_fn(), e1, e2, e3, e4, e5, e6, e7}); }
expr mk_or_comm_fn();
bool is_or_comm_fn(expr const & e);
inline expr mk_or_comm_th(expr const & e1, expr const & e2) { return mk_app({mk_or_comm_fn(), e1, e2}); }
@ -257,6 +267,9 @@ inline expr mk_or_truer_th(expr const & e1) { return mk_app({mk_or_truer_fn(), e
expr mk_or_tauto_fn();
bool is_or_tauto_fn(expr const & e);
inline expr mk_or_tauto_th(expr const & e1) { return mk_app({mk_or_tauto_fn(), e1}); }
expr mk_or_left_comm_fn();
bool is_or_left_comm_fn(expr const & e);
inline expr mk_or_left_comm_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_or_left_comm_fn(), e1, e2, e3}); }
expr mk_and_comm_fn();
bool is_and_comm_fn(expr const & e);
inline expr mk_and_comm_th(expr const & e1, expr const & e2) { return mk_app({mk_and_comm_fn(), e1, e2}); }
@ -281,6 +294,9 @@ inline expr mk_and_falser_th(expr const & e1) { return mk_app({mk_and_falser_fn(
expr mk_and_absurd_fn();
bool is_and_absurd_fn(expr const & e);
inline expr mk_and_absurd_th(expr const & e1) { return mk_app({mk_and_absurd_fn(), e1}); }
expr mk_and_left_comm_fn();
bool is_and_left_comm_fn(expr const & e);
inline expr mk_and_left_comm_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_and_left_comm_fn(), e1, e2, e3}); }
expr mk_imp_truer_fn();
bool is_imp_truer_fn(expr const & e);
inline expr mk_imp_truer_th(expr const & e1) { return mk_app({mk_imp_truer_fn(), e1}); }
@ -366,15 +382,6 @@ inline expr mk_exists_unfold2_th(expr const & e1, expr const & e2, expr const &
expr mk_exists_unfold_fn();
bool is_exists_unfold_fn(expr const & e);
inline expr mk_exists_unfold_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_exists_unfold_fn(), e1, e2, e3}); }
expr mk_left_comm_fn();
bool is_left_comm_fn(expr const & e);
inline expr mk_left_comm_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7) { return mk_app({mk_left_comm_fn(), e1, e2, e3, e4, e5, e6, e7}); }
expr mk_and_left_comm_fn();
bool is_and_left_comm_fn(expr const & e);
inline expr mk_and_left_comm_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_and_left_comm_fn(), e1, e2, e3}); }
expr mk_or_left_comm_fn();
bool is_or_left_comm_fn(expr const & e);
inline expr mk_or_left_comm_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_or_left_comm_fn(), e1, e2, e3}); }
expr mk_imp_congrr_fn();
bool is_imp_congrr_fn(expr const & e);
inline expr mk_imp_congrr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_imp_congrr_fn(), e1, e2, e3, e4, e5, e6}); }
@ -423,4 +430,31 @@ inline expr mk_exists_or_distribute_th(expr const & e1, expr const & e2, expr co
expr mk_exists_imp_distribute_fn();
bool is_exists_imp_distribute_fn(expr const & e);
inline expr mk_exists_imp_distribute_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_exists_imp_distribute_fn(), e1, e2, e3}); }
expr mk_if_true_fn();
bool is_if_true_fn(expr const & e);
inline expr mk_if_true_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_true_fn(), e1, e2, e3}); }
expr mk_if_false_fn();
bool is_if_false_fn(expr const & e);
inline expr mk_if_false_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_false_fn(), e1, e2, e3}); }
expr mk_if_a_a_fn();
bool is_if_a_a_fn(expr const & e);
inline expr mk_if_a_a_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_a_a_fn(), e1, e2, e3}); }
expr mk_if_congr_fn();
bool is_if_congr_fn(expr const & e);
inline expr mk_if_congr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7, expr const & e8, expr const & e9, expr const & e10) { return mk_app({mk_if_congr_fn(), e1, e2, e3, e4, e5, e6, e7, e8, e9, e10}); }
expr mk_if_imp_then_fn();
bool is_if_imp_then_fn(expr const & e);
inline expr mk_if_imp_then_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_if_imp_then_fn(), e1, e2, e3, e4, e5}); }
expr mk_if_imp_else_fn();
bool is_if_imp_else_fn(expr const & e);
inline expr mk_if_imp_else_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_if_imp_else_fn(), e1, e2, e3, e4, e5}); }
expr mk_app_if_distribute_fn();
bool is_app_if_distribute_fn(expr const & e);
inline expr mk_app_if_distribute_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_app_if_distribute_fn(), e1, e2, e3, e4, e5, e6}); }
expr mk_eq_if_distributer_fn();
bool is_eq_if_distributer_fn(expr const & e);
inline expr mk_eq_if_distributer_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_eq_if_distributer_fn(), e1, e2, e3, e4, e5}); }
expr mk_eq_if_distributel_fn();
bool is_eq_if_distributel_fn(expr const & e);
inline expr mk_eq_if_distributel_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_eq_if_distributel_fn(), e1, e2, e3, e4, e5}); }
}

View file

@ -1,6 +1,6 @@
add_library(library kernel_bindings.cpp deep_copy.cpp
context_to_lambda.cpp placeholder.cpp expr_lt.cpp substitution.cpp
fo_unify.cpp bin_op.cpp equality.cpp io_state_stream.cpp printer.cpp
hop_match.cpp ite.cpp heq_decls.cpp cast_decls.cpp)
hop_match.cpp heq_decls.cpp cast_decls.cpp)
target_link_libraries(library ${LEAN_LIBS})

View file

@ -1,18 +0,0 @@
/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
*/
// Automatically generated file, DO NOT EDIT
#include "kernel/environment.h"
#include "kernel/decl_macros.h"
namespace lean {
MK_CONSTANT(if_true_fn, name("if_true"));
MK_CONSTANT(if_false_fn, name("if_false"));
MK_CONSTANT(if_a_a_fn, name("if_a_a"));
MK_CONSTANT(if_congr_fn, name("if_congr"));
MK_CONSTANT(if_imp_then_fn, name("if_imp_then"));
MK_CONSTANT(if_imp_else_fn, name("if_imp_else"));
MK_CONSTANT(app_if_distribute_fn, name("app_if_distribute"));
MK_CONSTANT(eq_if_distributer_fn, name("eq_if_distributer"));
MK_CONSTANT(eq_if_distributel_fn, name("eq_if_distributel"));
}

View file

@ -1,35 +0,0 @@
/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
*/
// Automatically generated file, DO NOT EDIT
#include "kernel/expr.h"
namespace lean {
expr mk_if_true_fn();
bool is_if_true_fn(expr const & e);
inline expr mk_if_true_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_true_fn(), e1, e2, e3}); }
expr mk_if_false_fn();
bool is_if_false_fn(expr const & e);
inline expr mk_if_false_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_false_fn(), e1, e2, e3}); }
expr mk_if_a_a_fn();
bool is_if_a_a_fn(expr const & e);
inline expr mk_if_a_a_th(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_if_a_a_fn(), e1, e2, e3}); }
expr mk_if_congr_fn();
bool is_if_congr_fn(expr const & e);
inline expr mk_if_congr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7, expr const & e8, expr const & e9, expr const & e10) { return mk_app({mk_if_congr_fn(), e1, e2, e3, e4, e5, e6, e7, e8, e9, e10}); }
expr mk_if_imp_then_fn();
bool is_if_imp_then_fn(expr const & e);
inline expr mk_if_imp_then_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_if_imp_then_fn(), e1, e2, e3, e4, e5}); }
expr mk_if_imp_else_fn();
bool is_if_imp_else_fn(expr const & e);
inline expr mk_if_imp_else_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_if_imp_else_fn(), e1, e2, e3, e4, e5}); }
expr mk_app_if_distribute_fn();
bool is_app_if_distribute_fn(expr const & e);
inline expr mk_app_if_distribute_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_app_if_distribute_fn(), e1, e2, e3, e4, e5, e6}); }
expr mk_eq_if_distributer_fn();
bool is_eq_if_distributer_fn(expr const & e);
inline expr mk_eq_if_distributer_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_eq_if_distributer_fn(), e1, e2, e3, e4, e5}); }
expr mk_eq_if_distributel_fn();
bool is_eq_if_distributel_fn(expr const & e);
inline expr mk_eq_if_distributel_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_eq_if_distributel_fn(), e1, e2, e3, e4, e5}); }
}

View file

@ -1,64 +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
*/
#include "kernel/kernel.h"
#include "kernel/abstract.h"
#include "kernel/decl_macros.h"
#include "library/ite.h"
#include "library/if_then_else_decls.cpp"
#include "library/kernel_bindings.h"
namespace lean {
// =======================================
// If-then-else builtin operator
static name g_ite_name("ite");
static format g_ite_fmt(g_ite_name);
/**
\brief Semantic attachment for if-then-else operator with type
<code>Pi (A : Type), Bool -> A -> A -> A</code>
*/
class ite_fn_value : public value {
expr m_type;
static expr mk_type() {
expr A = Const("A");
// Pi (A: Type), bool -> A -> A -> A
return Pi({A, TypeU}, Bool >> (A >> (A >> A)));
}
public:
ite_fn_value():m_type(mk_type()) {}
virtual ~ite_fn_value() {}
virtual expr get_type() const { return m_type; }
virtual name get_name() const { return g_ite_name; }
virtual optional<expr> normalize(unsigned num_args, expr const * args) const {
if (num_args == 5 && is_bool_value(args[2]) && is_value(args[3]) && is_value(args[4])) {
if (to_bool(args[2]))
return some_expr(args[3]); // if A true a b --> a
else
return some_expr(args[4]); // if A false a b --> b
} else {
return none_expr();
}
}
virtual void write(serializer & s) const { s << "ite"; }
};
MK_BUILTIN(ite_fn, ite_fn_value);
MK_IS_BUILTIN(is_ite_fn, mk_ite_fn());
static register_builtin_fn ite_blt("ite", []() { return mk_ite_fn(); });
static value::register_deserializer_fn ite_ds("ite", [](deserializer & ) { return mk_ite_fn(); });
// =======================================
void import_ite(environment const & env, io_state const & ios) {
env->import("if_then_else", ios);
}
static int expr_mk_ite(lua_State * L) {
return push_expr(L, mk_ite(to_expr(L, 1), to_expr(L, 2), to_expr(L, 3), to_expr(L, 4)));
}
void open_ite(lua_State * L) {
SET_GLOBAL_FUN(expr_mk_ite, "mk_ite");
}
}

View file

@ -1,18 +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
*/
#pragma once
#include "kernel/io_state.h"
#include "library/if_then_else_decls.h"
namespace lean {
expr mk_ite_fn();
bool is_ite_fn(expr const & e);
inline bool is_ite(expr const & e) { return is_app(e) && is_ite_fn(arg(e, 0)); }
inline expr mk_ite(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app(mk_ite_fn(), e1, e2, e3, e4); }
void import_ite(environment const & env, io_state const & ios);
void open_ite(lua_State * L);
}

View file

@ -11,7 +11,6 @@ Author: Leonardo de Moura
#include "library/fo_unify.h"
#include "library/hop_match.h"
#include "library/placeholder.h"
#include "library/ite.h"
namespace lean {
inline void open_core_module(lua_State * L) {
@ -20,7 +19,6 @@ inline void open_core_module(lua_State * L) {
open_fo_unify(L);
open_placeholder(L);
open_hop_match(L);
open_ite(L);
}
inline void register_core_module() {
script_state::register_module(open_core_module);

View file

@ -12,7 +12,6 @@ Author: Leonardo de Moura
#include "kernel/instantiate.h"
#include "kernel/occurs.h"
#include "library/expr_pair.h"
#include "library/ite.h"
#include "library/kernel_bindings.h"
#include "library/equality.h"
@ -33,10 +32,6 @@ class to_ceqs_fn {
return list<expr_pair>(mk_pair(e, H));
}
bool imported_ite() {
return m_env->imported("if_then_else");
}
expr lift_free_vars(expr const & e, unsigned d) {
return ::lean::lift_free_vars(e, d, m_menv);
}
@ -96,7 +91,7 @@ class to_ceqs_fn {
return mk_pair(new_e, new_H);
});
}
} else if (is_ite(e) && imported_ite()) {
} else if (is_ite(e)) {
expr c = arg(e, 2);
expr not_c = mk_not(c);
expr c1 = lift_free_vars(c, 1);

View file

@ -1,13 +1,14 @@
Set: pp::colors
Set: pp::unicode
Imported 'Int'
2
eps (nonempty_intro -2) (λ r : , ((⊥ → r = -2) → ( → r = 2) → ⊥) → ⊥)
3
Defined: x
2
eps (nonempty_intro -2) (λ r : , ((⊥ → r = -2) → ( → r = 2) → ⊥) → ⊥)
eps (nonempty_intro -2) (λ r : , ((⊥ → r = -2) → ( → r = 2) → ⊥) → ⊥) ≤ 0 → ⊥
Assumed: y
if 0 ≤ -3 + y then -3 + y else -1 * (-3 + y)
eps (nonempty_intro (-3 + y))
(λ r : , ((0 ≤ -3 + y → r = -3 + y) → ((0 ≤ -3 + y → ⊥) → r = -1 * (-3 + y)) → ⊥) → ⊥)
| x + y | > x
Set: lean::pp::notation
Int::gt (Int::abs (Int::add x y)) x

View file

@ -19,29 +19,22 @@ show(simplify(t1, 'default', opt))
*)
set_opaque Nat::ge false
add_rewrite Nat::add_assoc
add_rewrite Nat::distributer
add_rewrite Nat::distributel
rewrite_set basic
add_rewrite Nat::add_assoc Nat::distributer Nat::distributel : basic
(*
local opt = options({"simplifier", "unfold"}, true, {"simplifier", "eval"}, false)
local t1 = parse_lean("2 * double (double 2) + 1 ≥ 3")
show(simplify(t1, 'default', opt))
show(simplify(t1, "basic", opt))
*)
variables a b c d : Nat
import if_then_else
add_rewrite if_true
add_rewrite if_false
add_rewrite if_a_a
add_rewrite Nat::add_zeror
add_rewrite Nat::add_zerol
add_rewrite eq_id
add_rewrite if_true if_false if_a_a Nat::add_zeror Nat::add_zerol eq_id : basic
(*
local t1 = parse_lean("(a + b) * (c + d)")
local r, pr = simplify(t1)
local r, pr = simplify(t1, "basic")
print(r)
print(pr)
*)
@ -63,7 +56,7 @@ add_rewrite congr2_congr1 congr2_congr2 congr1_congr2 : proofsimp
(*
local t2 = parse_lean("(if a > 0 then b else b + 0) + 10 = (if a > 0 then b else b) + 10")
local r, pr = simplify(t2)
local r, pr = simplify(t2, "basic")
print(r)
print(pr)
show(simplify(pr, 'proofsimp'))
@ -72,7 +65,7 @@ show(simplify(pr, 'proofsimp'))
(*
local t1 = parse_lean("(a + b) * (a + b)")
local t2 = simplify(t1)
local t2 = simplify(t1, "basic")
print(t2)
*)
@ -81,20 +74,20 @@ print(t2)
(*
local t1 = parse_lean("true → false")
print(simplify(t1))
print(simplify(t1, "basic"))
*)
(*
local t1 = parse_lean("true → true")
print(simplify(t1))
print(simplify(t1, "basic"))
*)
(*
local t1 = parse_lean("false → false")
print(simplify(t1))
print(simplify(t1, "basic"))
*)
(*
local t1 = parse_lean("true ↔ false")
print(simplify(t1))
print(simplify(t1, "basic"))
*)

View file

@ -11,7 +11,6 @@
Assumed: b
Assumed: c
Assumed: d
Imported 'if_then_else'
a * c + (a * d + (b * c + b * d))
trans (Nat::distributel a b (c + d))
(trans (congr (congr2 Nat::add (Nat::distributer a c d)) (Nat::distributer b c d))

View file

@ -1,4 +1,3 @@
import if_then_else
-- Define a "fake" type to simulate the natural numbers. This is just a test.
variable N : Type
variable lt : N -> N -> Bool

View file

@ -1,6 +1,5 @@
Set: pp::colors
Set: pp::unicode
Imported 'if_then_else'
Assumed: N
Assumed: lt
Assumed: zero
@ -26,7 +25,7 @@ definition select {A : Type} {n : N} (v : vector A n) (i : N) (H : i < n) : A :=
definition map {A B C : Type} {n : N} (f : A → B → C) (v1 : vector A n) (v2 : vector B n) : vector C n :=
λ (i : N) (H : i < n), f (v1 i H) (v2 i H)
select (update (const three ⊥) two ) two two_lt_three : Bool
if two = two then else ⊥
eps (nonempty_intro ) (λ r : Bool, ((two = two → r = ) → ((two = two → ⊥) → r = ⊥) → ⊥) → ⊥)
update (const three ⊥) two : vector Bool three
--------
@ -46,4 +45,5 @@ map normal form -->
f (v1 i H) (v2 i H)
update normal form -->
λ (A : Type) (n : N) (v : ∀ (i : N), i < n → A) (i : N) (d : A) (j : N) (H : j < n), if j = i then d else v j H
λ (A : Type) (n : N) (v : ∀ (i : N), i < n → A) (i : N) (d : A) (j : N) (H : j < n),
eps (nonempty_intro d) (λ r : A, ((j = i → r = d) → ((j = i → ⊥) → r = v j H) → ⊥) → ⊥)

View file

@ -1,4 +1,3 @@
import if_then_else
set_option verbose false.
notation 10 if _ then _ : implies.
print environment 1.

View file

@ -1,6 +1,5 @@
Set: pp::colors
Set: pp::unicode
Imported 'if_then_else'
Notation has been redefined, the existing notation:
notation 45 if _ then _ else _
has been replaced with:

View file

@ -22,7 +22,6 @@ function test_ceq(name, expected, is_perm)
end
parse_lean_cmds([[
import if_then_else
variable f : Nat -> Nat
axiom Ax1 : forall x : Nat, x > 0 -> f x < 0 /\ not (f x = 1)
axiom Ax2 : forall x : Nat, x < 0 -> f (f x) = x