From Stdlib Require Import Strings.String.
From Stdlib Require Import String Ascii.
From Stdlib Require Arith.
From stdpp Require Import base.
From stdpp Require Import fin_maps.
From stdpp Require Import gmap.
From stdpp Require Import base gmultiset.
From Stdlib Require Classical.
From Stdlib Require Import ZArith.
From stdpp.bitvector Require Import definitions tactics.
From Stdlib Require Import Sorting.Sorted.
From Stdlib Require Import Reals.Rbasic_fun.
From Stdlib Require Import Reals.Abstract.ConstructiveAbs.
From Stdlib Require Import Reals.Rdefinitions.
From stdpp Require Import list_relations.
From stdpp Require Import list_numbers.
From stdpp Require Import functions.
From Stdlib Require Import ClassicalEpsilon.
From stdpp Require Import base decidable.
From Stdlib Require Import ZArith.Zeuclid.
From Stdlib Require Import ZArith.Znumtheory.
From stdpp Require Import propset.
From Stdlib Require Import Reals.
Require Import Why3.Base.
Require Import Why3.why3.Ref.Ref.
Require Import koda_ruskey_vcg.koda_ruskey.KodaRuskey_Spec.
Require Import koda_ruskey_vcg.koda_ruskey.Lemmas.
Open Scope Z_scope.
Theorem enum'vc (f0 : forest) (bits : list color) (st : list forest) (visited : list (Z -> color)) (fact0 : size_forest f0 = Z.of_nat (length bits)) (fact1 : valid_nums_forest f0 (Z.of_nat (length bits))) (fact2 : sub st f0 (nth_i bits)) (fact3 : ¬ st = ([] : list forest)) (fact4 : any_stack st (nth_i bits)) (fact5 : valid_coloring f0 (nth_i bits)) : match st with | [] => False | cons E st' => (match st' with | [] => (let o1 : Z -> color := nth_i bits in let o2 : list (Z -> color) := visited ++ [o1] in Z.of_nat (length o2) = 1%Z + Z.of_nat (length visited) ∧ nth (length visited) o2 inhabitant = o1 ∧ (∀(i : Z), 0%Z ≤ i ∧ i < Z.of_nat (length visited) -> nth (Z.to_nat i) o2 inhabitant = nth (Z.to_nat i) visited inhabitant) -> inverse st (nth_i bits) (nth_i bits) ∧ valid_coloring f0 (nth_i bits) ∧ stored_solutions f0 (nth_i bits) st visited o2) | _ => ((0%Z ≤ size_stack st ∧ size_stack st' < size_stack st ∨ size_stack st = size_stack st' ∧ (match st with | [] => False | cons _ f => f = st' end)) ∧ size_forest f0 = Z.of_nat (length bits) ∧ valid_nums_forest f0 (Z.of_nat (length bits)) ∧ sub st' f0 (nth_i bits) ∧ ¬ st' = ([] : list forest) ∧ any_stack st' (nth_i bits) ∧ valid_coloring f0 (nth_i bits)) ∧ (∀(bits1 : list color) (visited1 : list (Z -> color)), length bits1 = length bits -> (∀(i : Z), ¬ mem_stack i st' -> nth (Z.to_nat i) bits1 inhabitant = nth (Z.to_nat i) bits inhabitant) ∧ inverse st' (nth_i bits) (nth_i bits1) ∧ valid_coloring f0 (nth_i bits1) ∧ stored_solutions f0 (nth_i bits1) st' visited visited1 -> (∀(i : Z), ¬ mem_stack i st -> nth (Z.to_nat i) bits1 inhabitant = nth (Z.to_nat i) bits inhabitant) ∧ inverse st (nth_i bits) (nth_i bits1) ∧ valid_coloring f0 (nth_i bits1) ∧ stored_solutions f0 (nth_i bits1) st visited visited1) end) | cons (N i f1 f2 as f) st' => (0%Z ≤ i ∧ i < Z.of_nat (length bits)) ∧ (if decide (nth (Z.to_nat i) bits inhabitant = White) then let o1 : list forest := cons f2 st' in ((0%Z ≤ size_stack st ∧ size_stack o1 < size_stack st ∨ size_stack st = size_stack o1 ∧ (match st with | [] => False | cons _ f3 => f3 = o1 end)) ∧ size_forest f0 = Z.of_nat (length bits) ∧ valid_nums_forest f0 (Z.of_nat (length bits)) ∧ sub o1 f0 (nth_i bits) ∧ any_stack o1 (nth_i bits) ∧ valid_coloring f0 (nth_i bits)) ∧ (∀(bits1 : list color) (visited1 : list (Z -> color)), length bits1 = length bits -> (∀(i1 : Z), ¬ mem_stack i1 o1 -> nth (Z.to_nat i1) bits1 inhabitant = nth (Z.to_nat i1) bits inhabitant) ∧ inverse o1 (nth_i bits) (nth_i bits1) ∧ valid_coloring f0 (nth_i bits1) ∧ stored_solutions f0 (nth_i bits1) o1 visited visited1 -> (let o2 : color := Black in (0%Z ≤ i ∧ i < Z.of_nat (length bits1)) ∧ (length (set_list bits1 (Z.to_nat i) o2) = length bits1 -> nth_i (set_list bits1 (Z.to_nat i) o2) = fun_updt (nth_i bits1) i o2 -> (let o3 : list forest := cons f1 (cons f2 st') in ((0%Z ≤ size_stack st ∧ size_stack o3 < size_stack st ∨ size_stack st = size_stack o3 ∧ (match st with | [] => False | cons _ f3 => f3 = o3 end)) ∧ size_forest f0 = Z.of_nat (length (set_list bits1 (Z.to_nat i) o2)) ∧ valid_nums_forest f0 (Z.of_nat (length (set_list bits1 (Z.to_nat i) o2))) ∧ sub o3 f0 (nth_i (set_list bits1 (Z.to_nat i) o2)) ∧ any_stack o3 (nth_i (set_list bits1 (Z.to_nat i) o2)) ∧ valid_coloring f0 (nth_i (set_list bits1 (Z.to_nat i) o2))) ∧ (∀(bits2 : list color) (visited2 : list (Z -> color)), length bits2 = length (set_list bits1 (Z.to_nat i) o2) -> (∀(i1 : Z), ¬ mem_stack i1 o3 -> nth (Z.to_nat i1) bits2 inhabitant = nth (Z.to_nat i1) (set_list bits1 (Z.to_nat i) o2) inhabitant) ∧ inverse o3 (nth_i (set_list bits1 (Z.to_nat i) o2)) (nth_i bits2) ∧ valid_coloring f0 (nth_i bits2) ∧ stored_solutions f0 (nth_i bits2) o3 visited1 visited2 -> (∀(i1 : Z), ¬ mem_stack i1 st -> nth (Z.to_nat i1) bits2 inhabitant = nth (Z.to_nat i1) bits inhabitant) ∧ inverse st (nth_i bits) (nth_i bits2) ∧ valid_coloring f0 (nth_i bits2) ∧ stored_solutions f0 (nth_i bits2) st visited visited2))))) else let o1 : list forest := cons f1 (cons f2 st') in ((0%Z ≤ size_stack st ∧ size_stack o1 < size_stack st ∨ size_stack st = size_stack o1 ∧ (match st with | [] => False | cons _ f3 => f3 = o1 end)) ∧ size_forest f0 = Z.of_nat (length bits) ∧ valid_nums_forest f0 (Z.of_nat (length bits)) ∧ sub o1 f0 (nth_i bits) ∧ any_stack o1 (nth_i bits) ∧ valid_coloring f0 (nth_i bits)) ∧ (∀(bits1 : list color) (visited1 : list (Z -> color)), length bits1 = length bits -> (∀(i1 : Z), ¬ mem_stack i1 o1 -> nth (Z.to_nat i1) bits1 inhabitant = nth (Z.to_nat i1) bits inhabitant) ∧ inverse o1 (nth_i bits) (nth_i bits1) ∧ valid_coloring f0 (nth_i bits1) ∧ stored_solutions f0 (nth_i bits1) o1 visited visited1 -> (let o2 : color := White in (0%Z ≤ i ∧ i < Z.of_nat (length bits1)) ∧ (length (set_list bits1 (Z.to_nat i) o2) = length bits1 -> nth_i (set_list bits1 (Z.to_nat i) o2) = fun_updt (nth_i bits1) i o2 -> (let o3 : list forest := cons f2 st' in ((0%Z ≤ size_stack st ∧ size_stack o3 < size_stack st ∨ size_stack st = size_stack o3 ∧ (match st with | [] => False | cons _ f3 => f3 = o3 end)) ∧ size_forest f0 = Z.of_nat (length (set_list bits1 (Z.to_nat i) o2)) ∧ valid_nums_forest f0 (Z.of_nat (length (set_list bits1 (Z.to_nat i) o2))) ∧ sub o3 f0 (nth_i (set_list bits1 (Z.to_nat i) o2)) ∧ any_stack o3 (nth_i (set_list bits1 (Z.to_nat i) o2)) ∧ valid_coloring f0 (nth_i (set_list bits1 (Z.to_nat i) o2))) ∧ (∀(bits2 : list color) (visited2 : list (Z -> color)), length bits2 = length (set_list bits1 (Z.to_nat i) o2) -> (∀(i1 : Z), ¬ mem_stack i1 o3 -> nth (Z.to_nat i1) bits2 inhabitant = nth (Z.to_nat i1) (set_list bits1 (Z.to_nat i) o2) inhabitant) ∧ inverse o3 (nth_i (set_list bits1 (Z.to_nat i) o2)) (nth_i bits2) ∧ valid_coloring f0 (nth_i bits2) ∧ stored_solutions f0 (nth_i bits2) o3 visited1 visited2 -> (∀(i1 : Z), ¬ mem_stack i1 st -> nth (Z.to_nat i1) bits2 inhabitant = nth (Z.to_nat i1) bits inhabitant) ∧ inverse st (nth_i bits) (nth_i bits2) ∧ valid_coloring f0 (nth_i bits2) ∧ stored_solutions f0 (nth_i bits2) st visited visited2)))))) end.
Admitted.
