(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below    *)
Require Import ZArith.
Require Import Rbase.
Require Import ZOdiv.
Require int.Int.
Require int.Abs.
Require int.ComputerDivision.

Parameter sum_multiple_3_5_lt: Z -> Z.

Axiom SumEmpty : ((sum_multiple_3_5_lt 0%Z) = 0%Z).

Axiom SumNo : forall (n:Z), (0%Z <= n)%Z -> (((~ ((ZOmod n 3%Z) = 0%Z)) /\
  ~ ((ZOmod n 5%Z) = 0%Z)) ->
  ((sum_multiple_3_5_lt (n + 1%Z)%Z) = (sum_multiple_3_5_lt n))).

Axiom SumYes : forall (n:Z), (0%Z <= n)%Z -> ((((ZOmod n 3%Z) = 0%Z) \/
  ((ZOmod n 5%Z) = 0%Z)) ->
  ((sum_multiple_3_5_lt (n + 1%Z)%Z) = ((sum_multiple_3_5_lt n) + n)%Z)).

Axiom div2 : forall (x:Z), exists y:Z, (x = (2%Z * y)%Z) \/
  (x = ((2%Z * y)%Z + 1%Z)%Z).

Axiom mod_div_unique : forall (x:Z) (y:Z) (q:Z) (r:Z), ((0%Z <= x)%Z /\
  ((0%Z < y)%Z /\ ((x = ((q * y)%Z + r)%Z) /\ ((0%Z <= r)%Z /\
  (r < y)%Z)))) -> ((q = (ZOdiv x y)) /\ (r = (ZOmod x y))).

Axiom mod_succ_1 : forall (x:Z) (y:Z), ((0%Z <= x)%Z /\ (0%Z < y)%Z) ->
  ((~ ((ZOmod (x + 1%Z)%Z y) = 0%Z)) ->
  ((ZOmod (x + 1%Z)%Z y) = ((ZOmod x y) + 1%Z)%Z)).

Axiom mod_succ_2 : forall (x:Z) (y:Z), ((0%Z <= x)%Z /\ (0%Z < y)%Z) ->
  (((ZOmod (x + 1%Z)%Z y) = 0%Z) -> ((ZOmod x y) = (y - 1%Z)%Z)).

Axiom div_succ_1 : forall (x:Z) (y:Z), ((0%Z <= x)%Z /\ (0%Z < y)%Z) ->
  (((ZOmod (x + 1%Z)%Z y) = 0%Z) ->
  ((ZOdiv (x + 1%Z)%Z y) = ((ZOdiv x y) + 1%Z)%Z)).

Axiom div_succ_2 : forall (x:Z) (y:Z), ((0%Z <= x)%Z /\ (0%Z < y)%Z) ->
  ((~ ((ZOmod (x + 1%Z)%Z y) = 0%Z)) ->
  ((ZOdiv (x + 1%Z)%Z y) = (ZOdiv x y))).

Axiom mod2_mul2 : forall (x:Z), ((ZOmod (2%Z * x)%Z 2%Z) = 0%Z).

Axiom mod2_mul2_aux : forall (x:Z) (y:Z),
  ((ZOmod (y * (2%Z * x)%Z)%Z 2%Z) = 0%Z).

Axiom mod2_mul2_aux2 : forall (x:Z) (y:Z) (z:Z) (t:Z),
  ((ZOmod ((y * (2%Z * x)%Z)%Z + (z * (2%Z * t)%Z)%Z)%Z 2%Z) = 0%Z).

Axiom div2_mul2 : forall (x:Z), ((ZOdiv (2%Z * x)%Z 2%Z) = x).

Axiom div2_mul2_aux : forall (x:Z) (y:Z),
  ((ZOdiv (y * (2%Z * x)%Z)%Z 2%Z) = (y * x)%Z).

Axiom div2_add : forall (x:Z) (y:Z), (((ZOmod x 2%Z) = 0%Z) /\
  ((ZOmod y 2%Z) = 0%Z)) ->
  ((ZOdiv (x + y)%Z 2%Z) = ((ZOdiv x 2%Z) + (ZOdiv y 2%Z))%Z).

Axiom div2_sub : forall (x:Z) (y:Z), (((ZOmod x 2%Z) = 0%Z) /\
  ((ZOmod y 2%Z) = 0%Z)) ->
  ((ZOdiv (x - y)%Z 2%Z) = ((ZOdiv x 2%Z) - (ZOdiv y 2%Z))%Z).

Axiom tr_mod_2 : forall (n:Z), (0%Z <= n)%Z ->
  ((ZOmod (n * (n + 1%Z)%Z)%Z 2%Z) = 0%Z).

(* Why3 assumption *)
Definition tr(n:Z): Z := (ZOdiv (n * (n + 1%Z)%Z)%Z 2%Z).

Axiom tr_repr : forall (n:Z), (0%Z <= n)%Z ->
  ((n * (n + 1%Z)%Z)%Z = (2%Z * (tr n))%Z).

Axiom tr_succ : forall (n:Z), (0%Z <= n)%Z ->
  ((tr (n + 1%Z)%Z) = (((tr n) + n)%Z + 1%Z)%Z).

(* Why3 assumption *)
Definition closed_formula_aux(n:Z): Z := let n3 := (ZOdiv n 3%Z) in let n5 :=
  (ZOdiv n 5%Z) in let n15 := (ZOdiv n 15%Z) in
  (((3%Z * (tr n3))%Z + (5%Z * (tr n5))%Z)%Z - (15%Z * (tr n15))%Z)%Z.

(* Why3 assumption *)
Definition p(n:Z): Prop :=
  ((sum_multiple_3_5_lt (n + 1%Z)%Z) = (closed_formula_aux n)).

Axiom mod_15 : forall (n:Z), ((ZOmod n 15%Z) = 0%Z) <->
  (((ZOmod n 3%Z) = 0%Z) /\ ((ZOmod n 5%Z) = 0%Z)).

Axiom Closed_formula_0 : (p 0%Z).

Axiom Closed_formula_n : forall (n:Z), (0%Z < n)%Z -> ((p (n - 1%Z)%Z) ->
  (((~ ((ZOmod n 3%Z) = 0%Z)) /\ ~ ((ZOmod n 5%Z) = 0%Z)) -> (p n))).

Axiom Closed_formula_n_3 : forall (n:Z), (0%Z < n)%Z -> ((p (n - 1%Z)%Z) ->
  ((((ZOmod n 3%Z) = 0%Z) /\ ~ ((ZOmod n 5%Z) = 0%Z)) -> (p n))).

Axiom Closed_formula_n_5 : forall (n:Z), (0%Z < n)%Z -> ((p (n - 1%Z)%Z) ->
  (((~ ((ZOmod n 3%Z) = 0%Z)) /\ ((ZOmod n 5%Z) = 0%Z)) -> (p n))).

Axiom Closed_formula_n_15 : forall (n:Z), (0%Z < n)%Z -> ((p (n - 1%Z)%Z) ->
  ((((ZOmod n 3%Z) = 0%Z) /\ ((ZOmod n 5%Z) = 0%Z)) -> (p n))).

Axiom Induction : (forall (n:Z), (0%Z <= n)%Z -> ((forall (k:Z),
  ((0%Z <= k)%Z /\ (k < n)%Z) -> (p k)) -> (p n))) -> forall (n:Z),
  (0%Z <= n)%Z -> (p n).

Axiom Induction_bound : (forall (n:Z), (0%Z <= n)%Z -> ((forall (k:Z),
  ((0%Z <= k)%Z /\ (k < n)%Z) -> (p k)) -> (p n))) -> forall (n:Z),
  (0%Z <= n)%Z -> (p n).

Axiom Closed_formula_ind : forall (n:Z), (0%Z <= n)%Z -> (p n).

(* Why3 assumption *)
Definition closed_formula(n:Z): Z := let n3 := (ZOdiv n 3%Z) in let n5 :=
  (ZOdiv n 5%Z) in let n15 := (ZOdiv n 15%Z) in
  (ZOdiv (((3%Z * (n3 * (n3 + 1%Z)%Z)%Z)%Z + (5%Z * (n5 * (n5 + 1%Z)%Z)%Z)%Z)%Z - (15%Z * (n15 * (n15 + 1%Z)%Z)%Z)%Z)%Z 2%Z).

Axiom div_15 : forall (n:Z), (0%Z <= n)%Z -> (0%Z <= (ZOdiv n 15%Z))%Z.

Axiom div_5 : forall (n:Z), (0%Z <= n)%Z -> (0%Z <= (ZOdiv n 5%Z))%Z.

Axiom div_3 : forall (n:Z), (0%Z <= n)%Z -> (0%Z <= (ZOdiv n 3%Z))%Z.

(* Why3 goal *)
Theorem Closed_Formula : forall (n:Z), (0%Z <= n)%Z ->
  ((sum_multiple_3_5_lt (n + 1%Z)%Z) = (closed_formula n)).
intros n Hn.
rewrite Closed_formula_ind; auto.
unfold closed_formula_aux, closed_formula.
repeat rewrite tr_repr.
rewrite div2_sub.
rewrite div2_mul2_aux.
rewrite div2_add.
do 2 rewrite div2_mul2_aux.
auto.
repeat rewrite mod2_mul2_aux; auto.
rewrite mod2_mul2_aux; auto.
rewrite mod2_mul2_aux2; auto.
apply div_15; auto.
apply div_5; auto.
apply div_3; auto.
Qed.


