Zulip Chat Archive
Stream: Is there code for X?
Topic: pointwise min and max
Yakov Pechersky (Sep 01 2021 at 16:01):
Do we have something like the following already? @Filippo A. E. Nuccio , you were asking about pointwise function inequality, so you might know...
import analysis.convex.basic
universes u v
open set linear_map submodule
variables {E : Type u} {β : Type v}
section pointwise_min
variables [linear_order β]
@[simp] def pointwise.min (f g : E → β) (x : E) : β := min (f x) (g x)
@[simp] def pointwise.max (f g : E → β) (x : E) : β := max (f x) (g x)
@[simp] def pointwise.abs [has_neg β] (f : E → β) : E → β := pointwise.max f (-f : E → β)
variables {f g : E → β}
lemma pointwise.min_eq_left (h : f ≤ g) : pointwise.min f g = f :=
funext $ λ x, min_eq_left (h x)
lemma pointwise.min_eq_right (h : g ≤ f) : pointwise.min f g = g :=
funext $ λ x, min_eq_right (h x)
lemma pointwise.max_eq_left (h : g ≤ f) : pointwise.max f g = f :=
funext $ λ x, max_eq_left (h x)
lemma pointwise.max_eq_right (h : f ≤ g) : pointwise.max f g = g :=
funext $ λ x, max_eq_right (h x)
end pointwise_min
section convex
variables [ordered_add_comm_group E] [linear_ordered_add_comm_monoid β] [module ℝ E] [module ℝ β]
[ordered_module ℝ E] [ordered_module ℝ β]
{s : set E} {f g : E → β}
lemma convex_on.pointwise_max (hf : convex_on s f) (hg : convex_on s g) :
convex_on s (pointwise.max f g) :=
begin
refine ⟨hf.left, λ x y hx hy a b ha hb hab, _⟩,
rw convex_on_iff_div at hf hg,
simp only [max_le_iff, pointwise.max],
split,
{ calc
f (a • x + b • y) ≤ a • f x + b • f y :
by simpa [hab] using hf.right hx hy ha hb (zero_lt_one.trans_le hab.ge)
... ≤ a • max (f x) (g x) + b • max (f y) (g y) :
add_le_add
(smul_le_smul_of_nonneg (le_max_left _ _) ha)
(smul_le_smul_of_nonneg (le_max_left _ _) hb) },
{ calc
g (a • x + b • y) ≤ a • g x + b • g y :
by simpa [hab] using hg.right hx hy ha hb (zero_lt_one.trans_le hab.ge)
... ≤ a • max (f x) (g x) + b • max (f y) (g y) :
add_le_add
(smul_le_smul_of_nonneg (le_max_right _ _) ha)
(smul_le_smul_of_nonneg (le_max_right _ _) hb) }
end
lemma concave_on.pointwise_min (hf : concave_on s f) (hg : concave_on s g) :
concave_on s (pointwise.min f g) :=
@convex_on.pointwise_max _ (order_dual β) _ _ _ _ _ _ _ _ _ hf hg
end convex
Filippo A. E. Nuccio (Sep 01 2021 at 16:07):
I am sorry, I really don't know. I was indeed looking for pointwise inequality, but the pi.le_def
lemma was enough for me and I haven't dug any deeper.
Yakov Pechersky (Sep 01 2021 at 16:07):
Do you think my pointwise.min
should be called pi.min
?
Filippo A. E. Nuccio (Sep 01 2021 at 16:10):
Well, I don't know. I would say that pi.min
should express the existence of a universal min
assuming all Types have a min
; but I think that there might be other definitions of min
, no?
Yakov Pechersky (Sep 01 2021 at 16:11):
Yes, I agree, good point. That's maybe indicates it should be called pointwise
.
Filippo A. E. Nuccio (Sep 01 2021 at 16:11):
I would rather argue that I'd call it pointwise_min
rather than with a dot
since it seems to me that no dot
-notation is involved.
Yakov Pechersky (Sep 01 2021 at 16:12):
Also makes sense. Maybe we will have a pointwise namespace at somepoint?
Filippo A. E. Nuccio (Sep 01 2021 at 16:12):
This seems a good idea.
Eric Wieser (Sep 01 2021 at 16:21):
We already have pointwise.min
, it's has_inf.inf
/ docs#pi.has_inf:
-- added on to your example above
example (f g : E → β) : pointwise.min f g = f ⊓ g := rfl
example (f g : E → β) : pointwise.max f g = f ⊔ g := rfl
Kyle Miller (Sep 01 2021 at 18:10):
Going off topic a bit, if there were J-like "verb trains" (which wouldn't make any sense for Lean to have), then λ x, min (f x) (g x)
could be written as f min g
, which I suppose is essentially what the has_inf.inf
instance is doing by using an operator version of min
. "Verb trains" are all just short-hand ways of doing common sorts of combinators, and I'm slightly surprised that this particular combinator doesn't already exist in function.lean
. Neither on_fun
nor combine
do quite the right thing (combine
is the "dyadic fork" in J-speak, but there's no "monadic fork").
I'm not suggesting adding the missing combinators though. Plain-old lambdas usually seem to be the clearer and more accessible choice, if there's not already a specialized meaningful notation.
Yakov Pechersky (Sep 01 2021 at 20:10):
Anne Baanen (Sep 02 2021 at 08:58):
Kyle Miller said:
I'm slightly surprised that this particular combinator doesn't already exist in
function.lean
.
They do already exist, kind of, in unassembled format:
import tactic.suggest
import logic.function.basic
variables {α β : Type} [linear_order β] (f g : α → β)
open combinator
-- If you like SKI-ing:
#reduce S (S (K min) f) g
-- Or alternatively, if you like Haskell:
/-- I didn't manage to put an instance on `(→) α`, so introduce a synonym. -/
def reader' (α β : Type*) := α → β
instance reader'.applicative : applicative (reader' α) :=
{ pure := λ β, combinator.K,
seq := λ β γ, combinator.S }
#reduce (min <$> f <*> g : reader' α β)
Kyle Miller (Sep 02 2021 at 17:14):
I guess K
could be used to turn 2-argument combine
into a 1-argument combine
. I might have run into an elaborator bug, though:
universes u v
open set
variables {E : Type u} {β : Type v}
section pointwise_min
variables [linear_order β]
open combinator
@[simp] def pointwise.min (f g : E → β) : E → β := (K f -[min]- K g) punit.star
/-
kernel failed to type check declaration 'pointwise.min' this is usually due to a buggy tactic or a bug in the builtin elaborator
elaborated type:
Π {E : Type u} {β : Type v} [_inst_1 : linear_order β], (E → β) → (E → β) → E → β
elaborated value:
λ {E : Type u} {β : Type v} [_inst_1 : linear_order β] (f g : E → β), (K f -[min]- K g) punit.star
nested exception message:
type mismatch at application
@K (E → β)
term
E → β
has type
Type (max u v)
but is expected to have type
Type u_1
-/
end pointwise_min
Last updated: Dec 20 2023 at 11:08 UTC