Zulip Chat Archive
Stream: new members
Topic: Proof that the |max f1 - max f2| <= max |f1 - f2|
Will Bradley (Feb 02 2025 at 23:15):
image.png
To practice, I formalized this proof that the absolute difference in the maxima of two real-valued functions on a finite, non-empty set is not greater than the maximum absolute difference between them. (Note that the WLOG inequality assumption at the end of the second line should be reversed in the informal proof.) What can I improve, especially with regards to using Classical
?
I wish I knew a way to both let
-assign a variable from an Exists.choose
and introduce a hypothesis that the variable satisfies the proposition of the Exists
, like in choose_spec
, but all in one step. In other words, I wish I could obtain x₁
with hx₁
and x₂
with hx₂
in one tactic or term-expression each.
import Mathlib.Data.Real.Basic
import Mathlib.Data.Set.Finite.Lemmas
attribute [local instance] Classical.propDecidable in
noncomputable def Set.liftFun {α: Type u} {β: Sort v} [Nonempty β] (X: Set α) (f: X → β): α → β :=
fun x =>
if hx: x ∈ X then
f ⟨x, hx⟩
else
Classical.arbitrary β
structure FiniteNonemptySet (α: Type u) where
set: Set α
h₁: set.Finite
h₂: set.Nonempty
namespace FiniteNonemptySet
variable (X: FiniteNonemptySet α) (f: X.set → ℝ)
theorem exists_argmax: ∃ x, ∀ y, f y ≤ f x := by
obtain ⟨x, hx_mem, hx_max⟩ := X.set.exists_max_image (X.set.liftFun f) X.h₁ X.h₂
exists ⟨x, hx_mem⟩
intro ⟨y, hy_mem⟩
have := hx_max y hy_mem
simp [Set.liftFun, hx_mem, hy_mem] at this
assumption
noncomputable def maxBy :=
f (exists_argmax X f).choose
theorem absolute_difference_of_maxima_le_maximum_absolute_distance (f₁ f₂: X.set → ℝ): |X.maxBy f₁ - X.maxBy f₂| ≤ X.maxBy (fun x => |f₁ x - f₂ x|)
:= by
wlog h : X.maxBy f₁ ≥ X.maxBy f₂
· rw [abs_sub_comm]
conv in (fun _ => _) =>
intro
rw [abs_sub_comm]
apply this
exact le_of_not_ge h
· let x₁ := (X.exists_argmax f₁).choose
have hx₁ := (X.exists_argmax f₁).choose_spec
let x₂ := (X.exists_argmax f₂).choose
have hx₂ := (X.exists_argmax f₂).choose_spec
calc |X.maxBy f₁ - X.maxBy f₂|
_ = X.maxBy f₁ - X.maxBy f₂ := by rwa [abs_eq_self, sub_nonneg]
--_ = f₁ x₁ - f₂ x₂ := rfl
_ ≤ f₁ x₁ - f₂ x₁ := tsub_le_tsub (hx₁ x₁) (hx₂ x₁)
_ ≤ |f₁ x₁ - f₂ x₁| := le_abs_self _
_ ≤ X.maxBy (fun x => |f₁ x - f₂ x|) := by
simp [maxBy, -Subtype.forall]
apply (X.exists_argmax (fun x => |f₁ x - f₂ x|)).choose_spec
end FiniteNonemptySet
Aaron Liu (Feb 02 2025 at 23:18):
let ⟨x, hx⟩ := Classical.indefiniteDescription _ ⋯
Will Bradley (Feb 02 2025 at 23:20):
@Aaron Liu Thank you! I was somehow just looking at that without connecting it to what I wanted
Aaron Liu (Feb 02 2025 at 23:21):
I have found this version to be harder to work with, due to both the higher-order unification problems it introduces (although that problem exists with Classical.choose
and Classical.choose_spec
too) and just that it is longer to type, and gives terms with match Classical.indefiniteDescription _ _ with | .mk x hx => ...
in it.
Will Bradley (Feb 02 2025 at 23:23):
Actually, @Aaron Liu, the hypothesis given by indefiniteDescription
for x₁
is different (x₁ ∈ X.set
) than the one I have using choose_spec
(∀ (y : ↑X.set), f₁ y ≤ f₁ ⋯.choose
)
Will Bradley (Feb 02 2025 at 23:24):
And x₁
is definitionally equal to that ⋯.choose
, I believe, so that's why it works
Aaron Liu (Feb 02 2025 at 23:29):
Not x₁
, but the (exists_argmax X f).choose
in the definition of maxBy
Kevin Buzzard (Feb 03 2025 at 15:08):
In this particular case you don't need to use choice at all; there is a better proof. To prove max|f-g|>=|max f - max g| it suffices to prove max|f-g| >= max f - max g and >= max g - max f, and by symmetry we only need to prove the first one. Rearranging, we need to prove max|f-g| + max g >= max f, but to prove something is >= max f, we only need to prove it's >= f(t) for all t (note that we're not using choice here, we're proving something for all t, not a special t) and this is obvious because max|f-g| >= |f(t)-g(t)| and max(g) >= g(t) by definition of max, and now the inequality follows from |f(t)-g(t)| >= f(t) - g(t).
Will Bradley (Feb 03 2025 at 21:22):
@Kevin Buzzard I'll try that, was following my written proof line-for-line. How do I even define the max of a finite, nonempty set constructively though?
Aaron Liu (Feb 03 2025 at 21:36):
You can use docs#Finset.max' or if you don't want to carry around proofs of nonempty then docs#Finset.max
Will Bradley (Feb 04 2025 at 05:50):
But @Aaron Liu I need the type parameter of the set to be a LinearOrder
for that
Aaron Liu (Feb 04 2025 at 11:57):
What does the maximum mean if you don't have a linear order?
Edward van de Meent (Feb 04 2025 at 16:53):
you can try using the supremum instead?
Edward van de Meent (Feb 04 2025 at 16:53):
i.e., the maximum is the supremum of two comparable values
Edward van de Meent (Feb 04 2025 at 16:57):
in mathlib, i think this is what max
or ⊔
refers to
Aaron Liu (Feb 04 2025 at 18:08):
That would be docs#Finset.sup, which works in a docs#SemilatticeSup with docs#OrderBot, and if you don't have a bottom element, then docs#Finset.sup' (but you need nonempty).
Will Bradley (Feb 04 2025 at 18:26):
Oh yeah lol. Sorry I forgot what my original goal was
Last updated: May 02 2025 at 03:31 UTC