(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) Require Import ssreflect. Require Import dataset. Require Import real. Require Import realsyntax. Require Import Setoid. Require Import realprop. Set Implicit Arguments. Unset Strict Implicit. Section IMO. Open Scope real_scope. Variable R : real_model. (* Because of the limitations of Coq v8.1 Setoid tactics, we need to repeat *) (* some of the boilerplate from file realprop.v. here. *) Hint Resolve eqr_refl leqrr ltrW. Let ltr01 := (ltr01 R). Let ltr02 := (ltr02 R). Add Relation (real_carrier R) (@eqr R) transitivity proved by (@eqr_trans R) reflexivity proved by (@eqr_refl R) symmetry proved by (@eqr_sym R) as eqr_theory_approx. Add Morphism (@leqr R) with signature (@eqr R) ==> (@eqr R) ==> iff as leqr_morphism_approx. Proof. exact: leqr_morphism. Qed. Add Morphism (@addr R) with signature (@eqr R) ==> (@eqr R) ==> (@eqr R) as addr_morphism_approx. Proof. exact: addr_morphism. Qed. Add Morphism (@oppr R) with signature (@eqr R) ==> (@eqr R) as oppr_morphism_approx. Proof. exact: oppr_morphism. Qed. Add Morphism (@mulr R) with signature (@eqr R) ==> (@eqr R) ==> (@eqr R) as mulr_morphism_approx. Proof. exact: mulr_morphism. Qed. Add Morphism (@maxr R) with signature (@eqr R) ==> (@eqr R) ==> (@eqr R) as maxr_morphism_approx. Proof. exact: maxr_morphism. Qed. Definition absr (x : R) := max x (-x). Add Morphism absr with signature (@eqr R) ==> (@eqr R) as absr_morphism. Proof. by rewrite /absr => ? ? ->. Qed. Notation "`| x |" := (absr x) (at level 0, x at level 70, format "`| x |"). Lemma leqr_add : forall x1 y1 x2 y2 : R, x1 <= x2 -> y1 <= y2 -> x1 + y1 <= x2 + y2. Proof. move=> x1 y1 x2 y2; rewrite -(leqr_add2r y1) -(leqr_add2l x2 y1). exact: leqr_trans. Qed. Lemma leqr_0add : forall x y : R, 0 <= x -> 0 <= y -> 0 <= x + y. Proof. move=> *; rewrite -(addr0 0); exact: leqr_add. Qed. Lemma leqr_0mul : forall x y : R, 0 <= x -> 0 <= y -> 0 <= x * y. Proof. move=> x *; rewrite -(mulr0 x); exact: (mulr_monotony R). Qed. Lemma absr_cases : forall x : R, 0 <= x \/ 0 <= -x. Proof. move=> x; rewrite -(leqr_opp2 _ 0) oppr0; exact: leqr_total. Qed. Lemma maxrC : forall x y : R, maxr x y == maxr y x. Proof. suff: forall x y : R, max x y <= max y x by split. move=> x y; rewrite leqr_max; split; [exact: leqr_maxr | exact: leqr_maxl]. Qed. Lemma absr_opp : forall x, `|-x| == `|x|. Proof. by move=> x; rewrite /absr maxrC oppr_opp. Qed. Lemma leqr_abs : forall x, x <= `|x|. Proof. by move=> x; exact: leqr_maxl. Qed. Lemma leqr_0abs : forall x, 0 <= `|x|. Proof. move=> x; wlog ?: x / x >= 0; last exact: leqr_trans (leqr_abs _). by case: (absr_cases x) => *; last rewrite -absr_opp; auto. Qed. Lemma absr_eq : forall x, 0 <= x -> `|x| == x. Proof. move=> x Hx; split; [rewrite /absr leqr_max; split=> // | exact: leqr_abs]. by apply: leqr_trans (Hx); rewrite -oppr0 leqr_opp2. Qed. Lemma absr_eq0 : forall x, `|x| == 0 -> x == 0. Proof. move=> x; case (absr_cases x); last rewrite -absr_opp; move/absr_eq=> -> //. by move/oppr_morphism; rewrite oppr_opp oppr0. Qed. Lemma absr_mul: forall x y, `|x * y| == `|x| * `|y|. Proof. move=> x y; wlog Hx: x / x >= 0 => [Hpos|]. by case (absr_cases x); move/Hpos; last rewrite mulr_oppl !absr_opp. wlog Hy: y / y >= 0 => [Hpos|]. by case (absr_cases y); move/Hpos; last rewrite mulr_oppr !absr_opp. rewrite !absr_eq //; exact: leqr_0mul. Qed. Lemma absr_add: forall x y, `|x + y| <= `|x| + `|y|. Proof. move=> x y; wlog Hx: x y / x + y >= 0 => [Hpos|]. case (absr_cases (x + y)); last rewrite oppr_add; move/Hpos=> //. by rewrite -oppr_add !absr_opp. rewrite absr_eq //; apply: leqr_add; exact: leqr_abs. Qed. Implicit Arguments leqr_pmul2l [R x x1 x2]. Implicit Arguments leqr_pmul2r [R x x1 x2]. Lemma pdivrr : forall x : R, x > 0 -> x / x == 1. Proof. by move=> *; apply divrr => [[Hx _]]; eauto. Qed. Lemma pmulrK : forall x y : R, y > 0 -> x * y / y == x. Proof. by move=> *; rewrite -mulrA pdivrr ?mulr1. Qed. Lemma pdivrK : forall x y : R, y > 0 -> x / y * y == x. Proof. by move=> *; rewrite mulrC mulrCA mulrA pmulrK. Qed. Lemma leqr_pdivr : forall x1 x2 y : R, y > 0 -> (x1 <= x2 / y <-> x1 * y <= x2). Proof. by move=> ? ? ? Hy; rewrite -(leqr_pmul2r Hy) pdivrK. Qed. Lemma IMO : forall f g, (forall x y : R, f (x + y) + f (x - y) == 2 * f x * g y) -> ~ (forall x, f x == 0) -> (forall x, `|f x| <= 1) -> forall y, `|g y| <= 1. Proof. move=> f g Efg Hf0 Hf1 y. without loss Hgy: / `|g y| > 0. case: (leqr_total 1 `|g y|) => // Hy; apply; exact: ltr_leq_trans _ Hy. pose k := sup {z | exists x, z == `|f x|}. have{Hf1} Hfk: `|f _| <= k. by move=> x; apply: ubr_sup; [exists (1 : R) => _ [? ->] | exists x]. have{Hf0} Hk: k > 0. move=> Hk; elim: Hf0 => x; apply: absr_eq0. split; [exact: leqr_trans Hk | exact: leqr_0abs]. suffices: k <= k / `|g y| by rewrite leqr_pdivr // mulrC -leqr_pdivr // pdivrr. suffices: `|f _| <= k / `|g y| => [Hf|x]. by apply: leqr_sup_ub => [|_ [x ->]]; first by exists `|f y|; exists y. suffices: `|f x * g y| <= k by rewrite absr_mul -leqr_pdivr. have{Efg} Ek: `|2 * f x * g y| <= 2 * k. rewrite -Efg mul2r; apply: leqr_trans (absr_add _ _) _; exact: leqr_add. by do [rewrite -mulrA absr_mul absr_eq ?leqr_pmul2l; auto] in Ek. Qed. End IMO.