Built with Alectryon, running vsrocq-language-server v9.4+alpha 5.4.1 / 2.5.0. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
(** Subtraction-based Euclid: complete baseline and supporting proofs. Start the guided walkthrough in L01_Baseline.v. This reference module contains the algorithm and every arithmetic lemma used by the lessons. Build everything with [python3 check.py] from this folder.*)From Corelib Require Import Init.Nat Program.Wf.Set Guard Checking.SetUniverseChecking.(* The ordinary structural termination checker rejects this program. Fail asserts rejection; it does not admit the definition. *)
The command has indeed failed with message:
Cannot guess decreasing argument of fix.
(* Elementary arithmetic support, requiring only Corelib. *)ModuleTerminationFacts.
n, m, p: nat
n <= m -> m <= p -> n <= p
n, m, p: nat
n <= m -> m <= p -> n <= p
n, m, p: nat Hnm: n <= m Hmp: m <= p
n <= p
n, m: nat Hnm: n <= m
n <= m
n, m: nat Hnm: n <= m m0: nat Hmp: m <= m0 IHHmp: n <= m0
n <= S m0
n, m: nat Hnm: n <= m
n <= m
exact Hnm.
n, m: nat Hnm: n <= m m0: nat Hmp: m <= m0 IHHmp: n <= m0
n <= S m0
n, m: nat Hnm: n <= m m0: nat Hmp: m <= m0 IHHmp: n <= m0
n: nat IH: forallm : nat, m < n -> Acc lt m m: nat Hm: m < S n
Acc lt m
m: nat Hm: m < 0
Acc lt m
inversion Hm.
n: nat IH: forallm : nat, m < n -> Acc lt m m: nat Hm: m < S n
Acc lt m
n: nat IH: forallm : nat, m < n -> Acc lt m m: nat Hm: m < S n
forally : nat, y < m -> Acc lt y
n: nat IH: forallm : nat, m < n -> Acc lt m m: nat Hm: m < S n k: nat Hk: k < m
Acc lt k
n: nat IH: forallm : nat, m < n -> Acc lt m m: nat Hm: m < S n k: nat Hk: k < m
k < n
n: nat IH: forallm : nat, S m <= n -> Acc (funnm0 : nat => S n <= m0) m m: nat Hm: S m <= S n k: nat Hk: S k <= m
S k <= n
n: nat IH: forallm : nat, S m <= n -> Acc (funnm0 : nat => S n <= m0) m m: nat Hm: S m <= S n k: nat Hk: S k <= m
m <= n
n: nat IH: forallm : nat, S m <= n -> Acc (funnm0 : nat => S n <= m0) m m: nat Hm: S m <= S n k: nat Hk: S k <= m
S m <= S n
exact Hm.
bounded: forallnm : nat, m < n -> Acc lt m
well_founded lt
bounded: forallnm : nat, m < n -> Acc lt m n: nat
Acc lt n
bounded: forallnm : nat, m < n -> Acc lt m n: nat
n < S n
apply le_n.Defined.EndTerminationFacts.(* The same algorithm, with measure a + b and checked proofs. In each positive-input branch, one argument stays unchanged while the other decreases. Neither decreases in every branch, but their sum does. The recursive calls are unchanged.*)#[local] Obligation Tactic := idtac.
euclid_sub_func has type-checked, generating 4 obligations
Solving obligations automatically...
4 obligations remaining
Obligation 1 of euclid_sub_func:
(forallab : nat,
(foralla0b0 : nat, a0 + b0 < a + b -> nat) ->
foralla'b' : nat, S a' = a -> S b' = b -> S a' + (S b' - S a') < a + b).
Obligation 2 of euclid_sub_func:
(forallab : nat,
(foralla0b0 : nat, a0 + b0 < a + b -> nat) ->
foralla'b' : nat, S a' = a -> S b' = b -> S a' - S b' + S b' < a + b).
Obligation 3 of euclid_sub_func:
(forall (ab : nat) (euclid_sub : foralla0b0 : nat, a0 + b0 < a + b -> nat),
letprogram_branch_0 :=
fun (wildcard' : nat) (_ : 0 = a) (_ : wildcard' = b) => b inletprogram_branch_1 :=
fun (wildcard' : nat)
(_ : forallwildcard'0 : nat, ~ (0 = wildcard' /\ wildcard'0 = 0))
(_ : wildcard' = a) (_ : 0 = b) =>
a inletprogram_branch_2 :=
fun (a'b' : nat) (Heq_a : S a' = a) (Heq_b : S b' = b) =>
if S a' <=? S b'
then
euclid_sub (S a') (S b' - S a')
(euclid_sub_func_obligation_1 a b euclid_sub a' b' Heq_a Heq_b)
else
euclid_sub (S a' - S b') (S b')
(euclid_sub_func_obligation_2 a b euclid_sub a' b' Heq_a Heq_b)
inforalln : nat,
letwildcard' := S n inforallwildcard'0 : nat, ~ (0 = wildcard' /\ wildcard'0 = 0)).
Obligation 4 of euclid_sub_func:
(well_founded
(MR lt
(funrecarg : {_ : nat & nat} =>
leta := projT1 recarg inletb := projT2 recarg in a + b))).
forallab : nat,
(foralla0b0 : nat, a0 + b0 < a + b -> nat) ->
foralla'b' : nat, S a' = a -> S b' = b -> S a' + (S b' - S a') < a + b
a, b: nat recurse: foralla0b0 : nat, a0 + b0 < a + b -> nat a', b': nat Ha: S a' = a Hb: S b' = b
S a' + (S b' - S a') < a + b
a', b': nat recurse: forallab : nat, a + b < S a' + S b' -> nat
S a' + (S b' - S a') < S a' + S b'
apply TerminationFacts.subtract_right_decreases.
3 obligations remaining
Solving obligations automatically...
3 obligations remaining
forallab : nat,
(foralla0b0 : nat, a0 + b0 < a + b -> nat) ->
foralla'b' : nat, S a' = a -> S b' = b -> S a' - S b' + S b' < a + b
a, b: nat recurse: foralla0b0 : nat, a0 + b0 < a + b -> nat a', b': nat Ha: S a' = a Hb: S b' = b
S a' - S b' + S b' < a + b
a', b': nat recurse: forallab : nat, a + b < S a' + S b' -> nat
S a' - S b' + S b' < S a' + S b'
apply TerminationFacts.subtract_left_decreases.
2 obligations remaining
Solving obligations automatically...
2 obligations remaining
forall (ab : nat) (euclid_sub : foralla0b0 : nat, a0 + b0 < a + b -> nat),
letprogram_branch_0 :=
fun (wildcard' : nat) (_ : 0 = a) (_ : wildcard' = b) => b inletprogram_branch_1 :=
fun (wildcard' : nat)
(_ : forallwildcard'0 : nat, ~ (0 = wildcard' /\ wildcard'0 = 0))
(_ : wildcard' = a) (_ : 0 = b) =>
a inletprogram_branch_2 :=
fun (a'b' : nat) (Heq_a : S a' = a) (Heq_b : S b' = b) =>
if S a' <=? S b'
then
euclid_sub (S a') (S b' - S a')
((fun (a0b0 : nat)
(recurse : foralla1b1 : nat, a1 + b1 < a0 + b0 -> nat)
(a'0b'0 : nat) (Ha : S a'0 = a0) (Hb : S b'0 = b0) =>
euclid_sub_func_obligation_1 a0 b0 recurse a'0 b'0 Ha Hb) a b
euclid_sub a' b' Heq_a Heq_b)
else
euclid_sub (S a' - S b') (S b')
((fun (a0b0 : nat)
(recurse : foralla1b1 : nat, a1 + b1 < a0 + b0 -> nat)
(a'0b'0 : nat) (Ha : S a'0 = a0) (Hb : S b'0 = b0) =>
euclid_sub_func_obligation_2 a0 b0 recurse a'0 b'0 Ha Hb) a b
euclid_sub a' b' Heq_a Heq_b)
inforalln : nat,
letwildcard' := S n inforallwildcard'0 : nat, ~ (0 = wildcard' /\ wildcard'0 = 0)
(* Pattern matching bookkeeping: zero is not a successor. *)intros; intuitiondiscriminate.
1 obligation remaining
well_founded
(MR lt
(funrecarg : {_ : nat & nat} =>
leta := projT1 recarg inletb := projT2 recarg in a + b))
(* There is no infinite descending chain of natural-number measures. *)
well_founded lt
exact TerminationFacts.nat_lt_wf.
No more obligations remaining
(* The accepted definition computes and has no axioms. *)
= 6
: nat
= 6
: nat
= 5
: nat
= 5
: nat
Fetching opaque proofs from disk for Corelib.Init.Peano