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.
Open Scope Z_scope.
Axiom prod : list Z -> Z -> Z -> Z.
Axiom prod'def : forall  (lo : Z) (hi : Z) (a : list Z) (fact0 : 0%Z ≤ lo) (fact1 : lo ≤ hi) (fact2 : hi ≤ Z.of_nat (length a)), if decide (lo = hi) then prod a lo hi = 1%Z else prod a lo hi = prod a lo (hi - 1%Z) * nth (Z.to_nat (hi - 1%Z)) a inhabitant.
Theorem maximum_subarray'vc (a : list Z) : let o1 : Z := Z.of_nat (length a) - 1%Z in (0%Z ≤ o1 + 1%Z -> ((0%Z ≤ 0%Z ∧ prod a 0%Z 0%Z = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ 0%Z -> 0%Z ≤ prod a l 0%Z -> prod a l 0%Z ≤ 1%Z) ∧ 0%Z ≤ 0%Z ∧ (0%Z < 0%Z -> 0%Z ≤ 0%Z ∧ prod a 0%Z 0%Z = 0%Z ∧ 0%Z < 0%Z) ∧ (0%Z < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ 0%Z -> prod a l 0%Z < 0%Z -> 0%Z ≤ prod a l 0%Z)) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ 0%Z -> 0%Z ≤ prod a l 0%Z) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ 0%Z -> prod a l h ≤ 1%Z) ∧ 0%Z ≤ 0%Z ∧ prod a 0%Z 0%Z = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(cln : Z) (clp : Z) (hi : Z) (lo : Z) (curmaxn : Z) (curmaxp : Z) (maxprd : Z), (∀(i : Z), (0%Z ≤ i ∧ i ≤ o1) ∧ ((0%Z ≤ clp ∧ clp ≤ i) ∧ prod a clp i = curmaxp ∧ 1%Z ≤ curmaxp) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i -> 0%Z ≤ prod a l i -> prod a l i ≤ curmaxp) ∧ curmaxn ≤ 0%Z ∧ (curmaxn < 0%Z -> (0%Z ≤ cln ∧ cln ≤ i) ∧ prod a cln i = curmaxn ∧ curmaxn < 0%Z) ∧ (curmaxn < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i -> prod a l i < 0%Z -> curmaxn ≤ prod a l i)) ∧ (curmaxn = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i -> 0%Z ≤ prod a l i)) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ i) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd -> (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (if decide (nth (Z.to_nat i) a inhabitant = 0%Z) then if decide (maxprd < 1%Z) then ((0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ 1%Z) ∧ 0%Z ≤ 0%Z ∧ (0%Z < 0%Z -> (0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 0%Z ∧ 0%Z < 0%Z) ∧ (0%Z < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z)) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ 1%Z) ∧ (0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z else ((0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ 1%Z) ∧ 0%Z ≤ 0%Z ∧ (0%Z < 0%Z -> (0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 0%Z ∧ 0%Z < 0%Z) ∧ (0%Z < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z)) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ i + 1%Z) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd else (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (if decide (0%Z < nth (Z.to_nat i) a inhabitant) then (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (if decide (maxprd < curmaxp * nth (Z.to_nat i) a inhabitant) then ((0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxp * nth (Z.to_nat i) a inhabitant) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ curmaxp * nth (Z.to_nat i) a inhabitant) ∧ curmaxn * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ cln ∧ cln ≤ i + 1%Z) ∧ prod a cln (i + 1%Z) = curmaxn * nth (Z.to_nat i) a inhabitant ∧ curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxn * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxn * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ curmaxp * nth (Z.to_nat i) a inhabitant) ∧ (0%Z ≤ clp ∧ clp ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxp * nth (Z.to_nat i) a inhabitant else ((0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxp * nth (Z.to_nat i) a inhabitant) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ curmaxp * nth (Z.to_nat i) a inhabitant) ∧ curmaxn * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ cln ∧ cln ≤ i + 1%Z) ∧ prod a cln (i + 1%Z) = curmaxn * nth (Z.to_nat i) a inhabitant ∧ curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxn * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxn * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxn * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ i + 1%Z) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd) else if decide (curmaxn < 0%Z) then (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (if decide (maxprd < curmaxn * nth (Z.to_nat i) a inhabitant) then ((0%Z ≤ cln ∧ cln ≤ i + 1%Z) ∧ prod a cln (i + 1%Z) = curmaxn * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxn * nth (Z.to_nat i) a inhabitant) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ curmaxn * nth (Z.to_nat i) a inhabitant) ∧ curmaxp * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxp * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ curmaxn * nth (Z.to_nat i) a inhabitant) ∧ (0%Z ≤ cln ∧ cln ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a cln (i + 1%Z) = curmaxn * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxn * nth (Z.to_nat i) a inhabitant else ((0%Z ≤ cln ∧ cln ≤ i + 1%Z) ∧ prod a cln (i + 1%Z) = curmaxn * nth (Z.to_nat i) a inhabitant ∧ 1%Z ≤ curmaxn * nth (Z.to_nat i) a inhabitant) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ curmaxn * nth (Z.to_nat i) a inhabitant) ∧ curmaxp * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxp * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ i + 1%Z) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd) else (0%Z ≤ i ∧ i < Z.of_nat (length a)) ∧ (if decide (maxprd < 1%Z) then ((0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ 1%Z) ∧ curmaxp * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxp * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ 1%Z) ∧ (0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z else ((0%Z ≤ i + 1%Z ∧ i + 1%Z ≤ i + 1%Z) ∧ prod a (i + 1%Z) (i + 1%Z) = 1%Z ∧ 1%Z ≤ 1%Z) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z) -> prod a l (i + 1%Z) ≤ 1%Z) ∧ curmaxp * nth (Z.to_nat i) a inhabitant ≤ 0%Z ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (0%Z ≤ clp ∧ clp ≤ i + 1%Z) ∧ prod a clp (i + 1%Z) = curmaxp * nth (Z.to_nat i) a inhabitant ∧ curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> prod a l (i + 1%Z) < 0%Z -> curmaxp * nth (Z.to_nat i) a inhabitant ≤ prod a l (i + 1%Z))) ∧ (curmaxp * nth (Z.to_nat i) a inhabitant = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ i + 1%Z -> 0%Z ≤ prod a l (i + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ i + 1%Z -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ i + 1%Z) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd)))) ∧ (((0%Z ≤ clp ∧ clp ≤ o1 + 1%Z) ∧ prod a clp (o1 + 1%Z) = curmaxp ∧ 1%Z ≤ curmaxp) ∧ (∀(l : Z), 0%Z ≤ l ∧ l ≤ o1 + 1%Z -> 0%Z ≤ prod a l (o1 + 1%Z) -> prod a l (o1 + 1%Z) ≤ curmaxp) ∧ curmaxn ≤ 0%Z ∧ (curmaxn < 0%Z -> (0%Z ≤ cln ∧ cln ≤ o1 + 1%Z) ∧ prod a cln (o1 + 1%Z) = curmaxn ∧ curmaxn < 0%Z) ∧ (curmaxn < 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ o1 + 1%Z -> prod a l (o1 + 1%Z) < 0%Z -> curmaxn ≤ prod a l (o1 + 1%Z))) ∧ (curmaxn = 0%Z -> (∀(l : Z), 0%Z ≤ l ∧ l ≤ o1 + 1%Z -> 0%Z ≤ prod a l (o1 + 1%Z))) ∧ (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ o1 + 1%Z -> prod a l h ≤ maxprd) ∧ (0%Z ≤ lo ∧ lo ≤ hi ∧ hi ≤ o1 + 1%Z) ∧ prod a lo hi = maxprd ∧ 1%Z ≤ maxprd -> (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ Z.of_nat (length a) -> prod a l h ≤ maxprd) ∧ (∃(l : Z) (h : Z), (0%Z ≤ l ∧ l ≤ h ∧ h ≤ Z.of_nat (length a)) ∧ prod a l h = maxprd)))) ∧ (o1 + 1%Z < 0%Z -> (∀(l : Z) (h : Z), 0%Z ≤ l ∧ l ≤ h ∧ h ≤ Z.of_nat (length a) -> prod a l h ≤ 1%Z) ∧ (∃(l : Z) (h : Z), (0%Z ≤ l ∧ l ≤ h ∧ h ≤ Z.of_nat (length a)) ∧ prod a l h = 1%Z)).
Admitted.
