Zulip Chat Archive
Stream: general
Topic: Proving fonction is decreasing
Alice Laroche (Dec 02 2021 at 00:29):
Lets say i have defined a function that's not trivially decreasing. For the sake of argument, the 3n + 1 function.
def collatz : ℕ -> ℕ -> ℕ
| flight_time 1 := flight_time
| flight_time n := if n % 2 = 0
then collatz (flight_time + 1) (n / 2)
else collatz (flight_time + 1) (3 * n + 1)
Lean will obviously say it failed to prove the function is decreasing. How can i give such a proof ?
Alex J. Best (Dec 02 2021 at 00:56):
If you can come up with a well founded relation for your function then you can do it with the using_well_founded
keyword.
You can find many examples in mathlib, but here is a made up one, saying how this would look for collatz is of course way harder than the question here
import tactic
def ex : ℕ -> ℕ -> ℕ
| flight_time 0 := flight_time
| flight_time (n+1) :=
if h : n % 2 = 0 then
have 2 * (n + 2) - ((n + 2) % 2) < 2 * (n + 1) - ((n + 1) % 2) := by simp [h]; sorry, -- showing that the function defined below is decreasing
ex (flight_time + 1) (n + 2)
else
have 2 * (n / 2) - ((n / 2) % 2) < 2 * (n + 1) - ((n + 1) % 2) := sorry,
ex (flight_time + 1) (n / 2)
using_well_founded { rel_tac := λ _ _, `[exact ⟨_, measure_wf (λ ⟨i, n⟩, 2 * n - n % 2)⟩],-- specifying that given i the flight time and n the second argument, that 2 * n - n % 2 is decreasing
dec_tac := `[assumption] } -- this is the default I believe, it says to try and fill in proofs that the relationg is decreasing using the assumption tactic, this means that we can just add the have's above to provide proofs, a tactic that can prove your goals above automatically is also possible here if there is one
this is the simplest possibility for a well founded relation, we give a map to the naturals and show it decreases with every recursive call, more complicated things are also possible.
P.s. I have no idea if the goals here are provable, but hopefully the structure is clear
Alice Laroche (Dec 02 2021 at 01:09):
Is there a way to use a mapping to transfinite ? I can easily define a function like
def size' : my_type -> ℕ := sorry
def size'' : my_type -> ℕ := sorry
def size : my_type -> transfinite
| val := (size' val) * ω + (size'' val)
Were size always decrease, but i don't think i can if i limit myself to naturals
Reid Barton (Dec 02 2021 at 03:23):
You could use ordinal
, but in this case it should be enough to use docs#prod.lex_wf
Mario Carneiro (Dec 02 2021 at 03:59):
Note that the collatz
function as written is definitely not well founded, as it diverges at 0
Mario Carneiro (Dec 02 2021 at 04:02):
If you special case 0 to make it terminate, then it becomes an open problem. In either case you aren't going to convince lean that this function terminates. But as long as there is a proof that the function terminates, even if it has a very high transfinite order type, it should be possible to construct the function in lean, either by induction on a suitable inductive type, or using the using_well_founded
mechanism to supply an inductive with even higher order type (like ordinal
).
Alice Laroche (Dec 02 2021 at 07:32):
The collatz function was just an exemple, I don't plan to solve it huhu
Kevin Buzzard (Dec 02 2021 at 07:48):
The problem might even be undecidable -- Conway's FRACTRAN is a generalisation of collatz and deciding whether a FRACTRAN program terminates is undecidable
Last updated: Dec 20 2023 at 11:08 UTC