(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2019       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(************************************************************************)
(** An interface for constructive and computable real numbers. All of its instances are isomorphic (see file ConstructiveRealsMorphisms). For example it is implemented by the Cauchy reals in file ConstructivecauchyReals and also implemented by the sumbool-based Dedekind reals defined by  Structure R := { (* The cuts are represented as propositional functions, rather than subsets, as there are no subsets in type theory. *)
lower : Q -> Prop;
upper : Q -> Prop;
(* The cuts respect equality on Q. *)
lower_proper : Proper (Qeq ==> iff) lower;
upper_proper : Proper (Qeq ==> iff) upper;
(* The cuts are inhabited. *)
lower_bound : { q : Q | lower q };
upper_bound : { r : Q | upper r };
(* The lower cut is a lower set. *)
lower_lower : forall q r, q < r -> lower r -> lower q;
(* The lower cut is open. *)
lower_open : forall q, lower q -> exists r, q < r /\ lower r;
(* The upper cut is an upper set. *)
upper_upper : forall q r, q < r -> upper q -> upper r;
(* The upper cut is open. *)
upper_open : forall r, upper r -> exists q,  q < r /\ upper q;
(* The cuts are disjoint. *)
disjoint : forall q, ~ (lower q /\ upper q);
(* There is no gap between the cuts. *)
located : forall q r, q < r -> { lower q } + { upper r }
}.
see github.com/andrejbauer/dedekind-reals for the Prop-based
version of those Dedekind reals (although Prop fails to make
them an instance of ConstructiveReals).
Any computation about constructive reals can be worked
in the fastest instance for it; we then transport the results
to all other instances by the isomorphisms. This way of working
is different from the usual interfaces, where we would rather
prove things abstractly, by quantifying universally on the instance.
The functions of ConstructiveReals do not have a direct impact
on performance, because algorithms will be extracted from instances,
and because fast ConstructiveReals morphisms should be coded
manually. However, since instances are forced to implement
those functions, it is probable that they will also use them
in their algorithms. So those functions hint at what we think
will yield fast and small extracted programs.
Constructive reals are setoids, which custom equality is defined as
x == y  iff  (x <= y /\ y <= x).
It is hard to quotient constructively to get the Leibniz equality
on the real numbers. In "Sheaves in Geometry and Logic",
MacLane and Moerdijk show a topos in which all functions R -> Z
are constant. Consequently all functions R -> Q are constant and
it is not possible to approximate real numbers by rational numbers.
WARNING: this file is experimental and likely to change in future releases.
*)
Definition isLinearOrder {X : Set} (Xlt : X -> X -> Set) : Set
:= (forall x y:X, Xlt x y -> Xlt y x -> False)
* (forall x y z : X, Xlt x y -> Xlt y z -> Xlt x z)
* (forall x y z : X, Xlt x z -> Xlt x y + Xlt y z).
Structure ConstructiveReals : Type :=
{
CRcarrier : Set;
(* Put this order relation in sort Set rather than Prop, to allow the definition of fast ConstructiveReals morphisms. For example, the Cauchy reals do store information in the proofs of CRlt, which is used in algorithms in sort Set. *)
CRlt : CRcarrier -> CRcarrier -> Set;
CRltLinear : isLinearOrder CRlt;
CRle (x y : CRcarrier) := CRlt y x -> False;
CReq (x y : CRcarrier) := CRle y x /\ CRle x y;
CRapart (x y : CRcarrier) := sum (CRlt x y) (CRlt y x);
(* The propositional truncation of CRlt. It facilitates proofs when computations are not considered important, for example in classical reals with extra logical axioms. *)
CRltProp : CRcarrier -> CRcarrier -> Prop;
(* This choice algorithm can be slow, keep it for the classical quotient of the reals, where computations are blocked by axioms like LPO. *)
CRltEpsilon : forall x y : CRcarrier, CRltProp x y -> CRlt x y;
CRltForget : forall x y : CRcarrier, CRlt x y -> CRltProp x y;
CRltDisjunctEpsilon : forall a b c d : CRcarrier,
(CRltProp a b \/ CRltProp c d) -> CRlt a b  +  CRlt c d;
(* The initial field morphism (in characteristic zero). The abstract definition by iteration of addition is probably the slowest. Let each instance implement a faster (and often simpler) version. *)
CR_of_Q : Q -> CRcarrier;
CR_of_Q_lt : forall q r : Q,
Qlt q r -> CRlt (CR_of_Q q) (CR_of_Q r);
lt_CR_of_Q : forall q r : Q,
CRlt (CR_of_Q q) (CR_of_Q r) -> Qlt q r;
(* Addition and multiplication *)
CRplus : CRcarrier -> CRcarrier -> CRcarrier;
CRopp : CRcarrier -> CRcarrier; (* Computable opposite,
stronger than Prop-existence of opposite *)
CRmult : CRcarrier -> CRcarrier -> CRcarrier;
CR_of_Q_plus : forall q r : Q, CReq (CR_of_Q (q+r))
(CRplus (CR_of_Q q) (CR_of_Q r));
CR_of_Q_mult : forall q r : Q, CReq (CR_of_Q (q*r))
(CRmult (CR_of_Q q) (CR_of_Q r));
CRisRing : ring_theory (CR_of_Q 0) (CR_of_Q 1) CRplus CRmult
(fun x y => CRplus x (CRopp y)) CRopp CReq;
CRisRingExt : ring_eq_ext CRplus CRmult CRopp CReq;
(* Compatibility with order *)
CRzero_lt_one : CRlt (CR_of_Q 0) (CR_of_Q 1);
CRplus_lt_compat_l : forall r r1 r2 : CRcarrier,
CRlt r1 r2 -> CRlt (CRplus r r1) (CRplus r r2);
CRplus_lt_reg_l : forall r r1 r2 : CRcarrier,
CRlt (CRplus r r1) (CRplus r r2) -> CRlt r1 r2;
CRmult_lt_0_compat : forall x y : CRcarrier,
CRlt (CR_of_Q 0) x -> CRlt (CR_of_Q 0) y -> CRlt (CR_of_Q 0) (CRmult x y);
(* A constructive total inverse function on F would need to be continuous, which is impossible because we cannot connect plus and minus infinities. Therefore it has to be a partial function, defined on non zero elements. For this reason we cannot use Coq's field_theory and field tactic.  To implement Finv by Cauchy sequences we need orderAppart, ~orderEq is not enough. *)
CRinv : forall x : CRcarrier, CRapart x (CR_of_Q 0) -> CRcarrier;
CRinv_l : forall (r:CRcarrier) (rnz : CRapart r (CR_of_Q 0)),
CReq (CRmult (CRinv r rnz) r) (CR_of_Q 1);
CRinv_0_lt_compat : forall (r : CRcarrier) (rnz : CRapart r (CR_of_Q 0)),
CRlt (CR_of_Q 0) r -> CRlt (CR_of_Q 0) (CRinv r rnz);
(* This function is very fast in both the Cauchy and Dedekind instances, because this rational number q is almost what the proof of CRlt x y contains. This function is also the heart of the computation of constructive real numbers : it approximates x to any requested precision y. *)
CR_Q_dense : forall x y : CRcarrier, CRlt x y ->
{ q : Q  &  prod (CRlt x (CR_of_Q q))
(CRlt (CR_of_Q q) y) };
CR_archimedean : forall x : CRcarrier,
{ n : positive  &  CRlt x (CR_of_Q (Z.pos n # 1)) };
CRminus (x y : CRcarrier) : CRcarrier
:= CRplus x (CRopp y);
(* Absolute value, CRabs x is the least upper bound of the pair x, -x. *)
CRabs : CRcarrier -> CRcarrier;
CRabs_def : forall x y : CRcarrier,
(CRle x y /\ CRle (CRopp x) y)
<-> CRle (CRabs x) y;
(* Definitions of convergence and Cauchy-ness. The formulas with orderLe or CRlt are logically equivalent, the choice of orderLe in sort Prop is a question of performance. It is very rare to turn back to the strict order to define functions in sort Set, so we prefer to discard those proofs during extraction. And even in those rare cases, it is easy to divide epsilon by 2 for example. *)
CR_cv (un : nat -> CRcarrier) (l : CRcarrier) : Set
:= forall p:positive,
{ n : nat  |  forall i:nat, le n i
-> CRle (CRabs (CRminus (un i) l))
(CR_of_Q (1#p)) };
CR_cauchy (un : nat -> CRcarrier) : Set
:= forall p : positive,
{ n : nat  |  forall i j:nat, le n i -> le n j
-> CRle (CRabs (CRminus (un i) (un j)))
(CR_of_Q (1#p)) };
(* For the Cauchy reals, this algorithm consists in building a Cauchy sequence of rationals un : nat -> Q that has the same limit as xn. For each n:nat, un n is a 1/n rational approximation of a point of xn that has converged within 1/n. *)
CR_complete :
forall xn : (nat -> CRcarrier),
CR_cauchy xn -> { l : CRcarrier  &  CR_cv xn l };
}.
Declare Scope ConstructiveReals.
Delimit Scope ConstructiveReals with ConstructiveReals.
Notation "x < y" := (CRlt _ x y) : ConstructiveReals.
Notation "x <= y" := (CRle _ x y) : ConstructiveReals.
Notation "x <= y <= z" := (CRle _ x y /\ CRle _ y z) : ConstructiveReals.
Notation "x < y < z"   := (prod (CRlt _ x y) (CRlt _ y z)) : ConstructiveReals.
Notation "x == y" := (CReq _ x y) : ConstructiveReals.
Notation "x ≶ y" := (CRapart _ x y) (at level 70, no associativity) : ConstructiveReals.
Notation "0" := (CR_of_Q _ 0) : ConstructiveReals.
Notation "1" := (CR_of_Q _ 1) : ConstructiveReals.
Notation "2" := (CR_of_Q _ 2) : ConstructiveReals.
Notation "3" := (CR_of_Q _ 3) : ConstructiveReals.
Notation "4" := (CR_of_Q _ 4) : ConstructiveReals.
Notation "5" := (CR_of_Q _ 5) : ConstructiveReals.
Notation "6" := (CR_of_Q _ 6) : ConstructiveReals.
Notation "7" := (CR_of_Q _ 7) : ConstructiveReals.
Notation "8" := (CR_of_Q _ 8) : ConstructiveReals.
Notation "9" := (CR_of_Q _ 9) : ConstructiveReals.
Notation "10" := (CR_of_Q _ 10) : ConstructiveReals.
Notation "x + y" := (CRplus _ x y) : ConstructiveReals.
Notation "- x" := (CRopp _ x) : ConstructiveReals.
Notation "x - y" := (CRminus _ x y) : ConstructiveReals.
Notation "x * y" := (CRmult _ x y) : ConstructiveReals.
Notation "/ x" := (CRinv _ x)  : ConstructiveReals.
Local Open Scope ConstructiveReals.

Lemma CRlt_trans_flip : forall {R : ConstructiveReals} (x y z : CRcarrier R),
y < z -> x < y -> x < z.