Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
License: APACHE
/-
Copyright (c) 2019 Simon Hudon. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Simon Hudon
-/
import tactic.monotonicity tactic.norm_num
import algebra.ordered_ring
import data.list.basic
open list tactic tactic.interactive
example
(h : 3 + 6 ≤ 4 + 5)
: 1 + 3 + 2 + 6 ≤ 4 + 2 + 1 + 5 :=
begin
ac_mono,
end
example
(h : 3 ≤ (4 : ℤ))
(h' : 5 ≤ (6 : ℤ))
: (1 + 3 + 2) - 6 ≤ (4 + 2 + 1 : ℤ) - 5 :=
by ac_mono
example
(h : 3 ≤ (4 : ℤ))
(h' : 5 ≤ (6 : ℤ))
: (1 + 3 + 2) - 6 ≤ (4 + 2 + 1 : ℤ) - 5 :=
begin
transitivity (1 + 3 + 2 - 5 : ℤ),
{ ac_mono },
{ ac_mono },
end
example (x y z k : ℤ)
(h : 3 ≤ (4 : ℤ))
(h' : z ≤ y)
: (k + 3 + x) - y ≤ (k + 4 + x) - z :=
begin
mono, norm_num
end
example (x y z a b : ℤ)
(h : a ≤ (b : ℤ))
(h' : z ≤ y)
: (1 + a + x) - y ≤ (1 + b + x) - z :=
begin
transitivity (1 + a + x - z),
{ mono, },
{ mono, mono, mono },
end
example (x y z : ℤ)
(h' : z ≤ y)
: (1 + 3 + x) - y ≤ (1 + 4 + x) - z :=
begin
transitivity (1 + 3 + x - z),
{ mono },
{ mono, mono, norm_num },
end
example (x y z : ℤ)
(h : 3 ≤ (4 : ℤ))
(h' : z ≤ y)
: (1 + 3 + x) - y ≤ (1 + 4 + x) - z :=
begin
ac_mono, mono*
end
@[simp]
def list.le' {α : Type*} [has_le α] : list α → list α → Prop
| (x::xs) (y::ys) := x ≤ y ∧ list.le' xs ys
| [] [] := true
| _ _ := false
@[simp]
instance list_has_le {α : Type*} [has_le α] : has_le (list α) :=
⟨ list.le' ⟩
lemma list.le_refl {α : Type*} [preorder α] {xs : list α}
: xs ≤ xs :=
begin
induction xs with x xs,
{ trivial },
{ simp [has_le.le,list.le],
split, apply le_refl, apply xs_ih }
end
-- @[trans]
lemma list.le_trans {α : Type*} [preorder α]
{xs zs : list α} (ys : list α)
(h : xs ≤ ys)
(h' : ys ≤ zs)
: xs ≤ zs :=
begin
revert ys zs,
induction xs with x xs
; intros ys zs h h'
; cases ys with y ys
; cases zs with z zs
; try { cases h ; cases h' ; done },
{ apply list.le_refl },
{ simp [has_le.le,list.le],
split,
apply le_trans h.left h'.left,
apply xs_ih _ h.right h'.right, }
end
@[mono]
lemma list_le_mono_left {α : Type*} [preorder α] {xs ys zs : list α}
(h : xs ≤ ys)
: xs ++ zs ≤ ys ++ zs :=
begin
revert ys,
induction xs with x xs ; intros ys h,
{ cases ys, apply list.le_refl, cases h },
{ cases ys with y ys, cases h, simp [has_le.le,list.le] at *,
revert h, apply and.imp_right,
apply xs_ih }
end
@[mono]
lemma list_le_mono_right {α : Type*} [preorder α] {xs ys zs : list α}
(h : xs ≤ ys)
: zs ++ xs ≤ zs ++ ys :=
begin
revert ys zs,
induction xs with x xs ; intros ys zs h,
{ cases ys, { simp, apply list.le_refl }, cases h },
{ cases ys with y ys, cases h, simp [has_le.le,list.le] at *,
suffices : list.le' ((zs ++ [x]) ++ xs) ((zs ++ [y]) ++ ys),
{ refine cast _ this, simp, },
apply list.le_trans (zs ++ [y] ++ xs),
{ apply list_le_mono_left,
induction zs with z zs,
{ simp [has_le.le,list.le], apply h.left },
{ simp [has_le.le,list.le], split, apply le_refl,
apply zs_ih, } },
{ apply xs_ih h.right, } }
end
lemma bar_bar'
(h : [] ++ [3] ++ [2] ≤ [1] ++ [5] ++ [4])
: [] ++ [3] ++ [2] ++ [2] ≤ [1] ++ [5] ++ ([4] ++ [2]) :=
begin
ac_mono,
end
lemma bar_bar''
(h : [3] ++ [2] ++ [2] ≤ [5] ++ [4] ++ [])
: [1] ++ ([3] ++ [2]) ++ [2] ≤ [1] ++ [5] ++ ([4] ++ []) :=
begin
ac_mono,
end
lemma bar_bar
(h : [3] ++ [2] ≤ [5] ++ [4])
: [1] ++ [3] ++ [2] ++ [2] ≤ [1] ++ [5] ++ ([4] ++ [2]) :=
begin
ac_mono,
end
def P (x : ℕ) := 7 ≤ x
def Q (x : ℕ) := x ≤ 7
@[mono]
lemma P_mono {x y : ℕ}
(h : x ≤ y)
: P x → P y :=
by { intro h', apply le_trans h' h }
@[mono]
lemma Q_mono {x y : ℕ}
(h : y ≤ x)
: Q x → Q y :=
by apply le_trans h
example (x y z : ℕ)
(h : x ≤ y)
: P (x + z) → P (z + y) :=
begin
ac_mono,
ac_mono,
end
example (x y z : ℕ)
(h : y ≤ x)
: Q (x + z) → Q (z + y) :=
begin
ac_mono,
ac_mono,
end
example (x y z k m n : ℤ)
(h₀ : z ≤ 0)
(h₁ : y ≤ x)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
begin
ac_mono,
ac_mono,
ac_mono,
end
example (x y z k m n : ℕ)
(h₀ : z ≥ 0)
(h₁ : x ≤ y)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
begin
ac_mono,
ac_mono,
ac_mono,
end
example (x y z k m n : ℕ)
(h₀ : z ≥ 0)
(h₁ : x ≤ y)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
begin
ac_mono,
-- ⊢ (m + x + n) * z ≤ z * (y + n + m)
ac_mono,
-- ⊢ m + x + n ≤ y + n + m
ac_mono,
end
example (x y z k m n : ℕ)
(h₀ : z ≥ 0)
(h₁ : x ≤ y)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
by { ac_mono* := h₁ }
example (x y z k m n : ℕ)
(h₀ : z ≥ 0)
(h₁ : m + x + n ≤ y + n + m)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
by { ac_mono* := h₁ }
example (x y z k m n : ℕ)
(h₀ : z ≥ 0)
(h₁ : n + x + m ≤ y + n + m)
: (m + x + n) * z + k ≤ z * (y + n + m) + k :=
begin
ac_mono* : m + x + n ≤ y + n + m,
transitivity ; [ skip , apply h₁ ],
apply le_of_eq,
ac_refl,
end
example (x y z k m n : ℤ)
(h₁ : x ≤ y)
: true :=
begin
have : (m + x + n) * z + k ≤ z * (y + n + m) + k,
{ ac_mono,
success_if_fail { ac_mono },
admit },
trivial
end
example (x y z k m n : ℕ)
(h₁ : x ≤ y)
: true :=
begin
have : (m + x + n) * z + k ≤ z * (y + n + m) + k,
{ ac_mono*,
change 0 ≤ z, apply nat.zero_le, },
trivial
end
example (x y z k m n : ℕ)
(h₁ : x ≤ y)
: true :=
begin
have : (m + x + n) * z + k ≤ z * (y + n + m) + k,
{ ac_mono,
change (m + x + n) * z ≤ z * (y + n + m),
admit },
trivial,
end
example (x y z k m n i j : ℕ)
(h₁ : x + i = y + j)
: (m + x + n + i) * z + k = z * (j + n + m + y) + k :=
begin
ac_mono^3,
simp [h₁],
end
example (x y z k m n i j : ℕ)
(h₁ : x + i = y + j)
: z * (x + i + n + m) + k = z * (y + j + n + m) + k :=
begin
congr,
simp [h₁],
end
example (x y z k m n i j : ℕ)
(h₁ : x + i = y + j)
: (m + x + n + i) * z + k = z * (j + n + m + y) + k :=
begin
ac_mono*,
simp [h₁],
end
example (x y : ℕ)
(h : x ≤ y)
: true :=
begin
(do v ← mk_mvar,
p ← to_expr ```(%%v + x ≤ y + %%v),
assert `h' p),
ac_mono := h,
trivial,
exact 1,
end
example {x y z : ℕ} : true :=
begin
have : y + x ≤ y + z,
{ mono,
guard_target' x ≤ z,
admit },
trivial
end
example {x y z : ℕ} : true :=
begin
suffices : x + y ≤ z + y, trivial,
mono,
guard_target' x ≤ z,
admit,
end
example {x y z w : ℕ} : true :=
begin
have : x + y ≤ z + w,
{ mono,
guard_target' x ≤ z, admit,
guard_target' y ≤ w, admit },
trivial
end
example {x y z w : ℕ} : true :=
begin
have : x * y ≤ z * w,
{ mono with [0 ≤ z,0 ≤ y],
{ guard_target 0 ≤ z, admit },
{ guard_target 0 ≤ y, admit },
guard_target' x ≤ z, admit,
guard_target' y ≤ w, admit },
trivial
end
example {x y z w : Prop} : true :=
begin
have : x ∧ y → z ∧ w,
{ mono,
guard_target' x → z, admit,
guard_target' y → w, admit },
trivial
end
example {x y z w : Prop} : true :=
begin
have : x ∨ y → z ∨ w,
{ mono,
guard_target' x → z, admit,
guard_target' y → w, admit },
trivial
end
example {x y z w : ℤ} : true :=
begin
suffices : x + y < w + z, trivial,
have : x < w, admit,
have : y ≤ z, admit,
mono right,
end
example {x y z w : ℤ} : true :=
begin
suffices : x * y < w * z, trivial,
have : x < w, admit,
have : y ≤ z, admit,
mono right,
{ guard_target' 0 < y, admit },
{ guard_target' 0 ≤ w, admit },
end
open tactic
example (x y : ℕ)
(h : x ≤ y)
: true :=
begin
(do v ← mk_mvar,
p ← to_expr ```(%%v + x ≤ y + %%v),
assert `h' p),
ac_mono := h,
trivial,
exact 3
end
example {α} [decidable_linear_order α]
(a b c d e : α) :
max a b ≤ e → b ≤ e :=
by { mono, apply le_max_right }
example (a b c d e : Prop)
(h : d → a) (h' : c → e) :
(a ∧ b → c) ∨ d → (d ∧ b → e) ∨ a :=
begin
mono,
mono,
mono,
end