Zulip Chat Archive
Stream: Is there code for X?
Topic: Kaminski's Equation
Aaron Bies (May 15 2022 at 11:10):
Hi, I would like to add the following identity to the mathlib, but I'm unsure what to call it.
@[simp] theorem kaminski (f : bool → bool) (x : bool) : f (f (f x)) = f x :=
by cases x; cases h₁ : f tt; cases h₂ : f ff; simp only [h₁, h₂]
I guess by #naming, it should be bool.f_f_f_eq_f
or bool.f_of_f_f_f
or maybe just bool.f_f_f
?
Yaël Dillies (May 15 2022 at 11:16):
... except that f
is the name of a free variable. I would rather call it bool.apply_apply_apply
or bool.apply_apply_apply_eq_apply
Eric Wieser (May 15 2022 at 11:25):
Yeah, naming things after a free variable is generally not so good
Aaron Bies (May 15 2022 at 11:29):
Fair point, bool.apply_apply_apply
it is
Patrick Johnson (May 15 2022 at 11:35):
An alternative proof using fin_cases
:
example {f : bool → bool} {x : bool} : f (f (f x)) = f x :=
by fin_cases f; cases x; refl
Scott Morrison (May 15 2022 at 12:26):
Note that this can't be a @[simp]
lemma, as the head of the LHS is a metavariable.
Scott Morrison (May 15 2022 at 12:27):
Wow, I'm happy that fin_cases
works here. :-)
Scott Morrison (May 15 2022 at 12:30):
I'm curious, is this identity actually "good for anything"? Is it "true for any reason" besides case bashing? I want (being highly prejudiced) to say that because it isn't "true for any reason" it can't be "good for anything". Convince me I'm wrong. :-)
Kevin Buzzard (May 15 2022 at 12:30):
Is there an analogous statement for endomorphisms of finite types? Hmm, I guess by pure thought there exist smallest numbers a(n) < b(n) such that f^a = f^b for all f:fin n -> fin n and this proof above shows a(2)=1, b(2)=3.
Scott Morrison (May 15 2022 at 12:33):
Okay, I guess that general fact is more or less good for something. But since it was true by pure thought, that's okay. (I think we've exhausted this line of thought, sorry. :-)
Kevin Buzzard (May 15 2022 at 12:34):
Quick let's call it the Buzzard-Morrison Equation in case it's useful for something.
Kevin Buzzard (May 15 2022 at 12:34):
My guess is that a(n)=O(n) and b(n)=O(n!)
Eric Rodriguez (May 15 2022 at 12:37):
To me, it's because functions bool -> bool are involutive, constant, or identity, and only because of the constant functions does f(f(x)) = x not hold. I guess this means b(n) = lcm(1...n) which surely has a nice value
Yaël Dillies (May 15 2022 at 12:37):
... it is asymptotically
Eric Rodriguez (May 15 2022 at 12:38):
Wow, according to oeis: "An assertion equivalent to the Riemann hypothesis is: | log(a(n)) - n | < sqrt(n) * log(n)^2. " (for a(n) our b(n))
Yaël Dillies (May 15 2022 at 12:39):
Whoops :rofl:
Eric Rodriguez (May 15 2022 at 12:42):
Maybe you just solved RH, Yaël ;b
Scott Morrison (May 15 2022 at 12:44):
Who's going to PR it?
Yaël Dillies (May 15 2022 at 12:44):
RH? I skip my turn :grinning:
Eric Wieser (May 15 2022 at 13:06):
Patrick Johnson said:
An alternative proof using
fin_cases
:
Here's an even easier proof:
example : ∀ {f : bool → bool} {x : bool}, f (f (f x)) = f x :=
dec_trivial
Kevin Buzzard (May 15 2022 at 13:10):
The issue is not about the growth (which is equivalent to the prime number theorem), it's about the error bounds (which is equivalent to the Riemann Hypothesis).
Aaron Bies (May 15 2022 at 13:19):
Damn this thread exploded while I was doing the dishes
Aaron Bies (May 15 2022 at 13:19):
My PR for this is #14159
Eric Rodriguez (May 15 2022 at 13:38):
Where did you find this name for this equation, Aaron? I can't seem to find kaminski's equation on Google...
Aaron Bies (May 15 2022 at 13:50):
It was taught to me by Gert Smolka; He also mentions it in his script in chapter 3.8
Eric Wieser (May 15 2022 at 13:55):
It says there:
The equation was brought up as a proof challenge by Mark Kaminski in 2005 when he wrote
his Bachelor’s thesis on classical higher-order logic.
Eric Wieser (May 15 2022 at 13:58):
The thesis at at https://www.ps.uni-saarland.de/Publications/documents/kaminski-bthesis.pdf, but I can't find the thing being referenced
Aaron Bies (May 15 2022 at 14:11):
hmm, I guess it came up while he was writing his thesis, but it didn't actually make it into the thesis
Aaron Bies (May 15 2022 at 14:15):
The thesis does reason about functions on booleans a lot, so it makes sense he'd stumble across this identity
Eric Wieser (May 16 2022 at 13:04):
It's entirely possible it's in there, just not in a form that's easy to spot
Kyle Miller (May 16 2022 at 14:47):
It would have been funny if
example (f : Prop → Prop) (p : Prop) : f (f (f p)) ↔ f p := sorry
were constructively true, since then docs#not_of_not_not_not would just be a consequence.
It's not constructively true though. Using the Heyting algebra of open sets of the real line, f could be a translation one unit to the right, and that translation turns out not to have finite order.
Kevin Buzzard (May 16 2022 at 16:16):
so you can even prove that there's no distinct a and b with f^a=f^b :-(
Mario Carneiro (May 16 2022 at 17:29):
Something seems fishy about that argument; you can give the same counterexample for the boolean algebra of sets on the real line
Yaël Dillies (May 16 2022 at 17:32):
Well, I think that shows
example {α : Type*} [boolean_algebra α] (f : α → α) (a : α) : f (f (f a)) = f a := sorry
is false.
Mario Carneiro (May 16 2022 at 17:44):
I think I found a definable counterexample:
import tactic.itauto
def f (p : Prop) := ¬ p ∨ ¬ ¬ p
theorem T (p : Prop) : f (f (f p)) → f p :=
by unfold f; itauto -- fail
itauto
is super useful here for being a complete decision procedure for intuitionistic logic
Mario Carneiro (May 16 2022 at 17:50):
here's a more comprehensible explanation of why it fails:
theorem T (p : Prop) : f (f (f p)) → f p :=
begin
unfold f,
intro h,
cases h,
{ itauto },
{ simp only [show ¬ (¬ p ∨ ¬ ¬ p) ↔ false, by itauto, false_or, not_false_iff, not_true] at h,
-- the hypothesis was useless, the goal is now
-- h: true ⊢ ¬p ∨ ¬¬p
itauto, } -- fails
end
Mario Carneiro (May 16 2022 at 17:53):
alternatively:
import tactic.itauto
def f (p : Prop) := ¬ p ∨ ¬ ¬ p
example (p : Prop) (h : f (f (f p)) → f p) : ¬p ∨ ¬¬p :=
by unfold f at h; itauto -- ok
Aaron Bies (May 16 2022 at 19:01):
Related to the generalized case, how does one arrive at the conclusion that A0665500 is equivalent to ?
Kyle Miller (May 16 2022 at 19:36):
Mario Carneiro said:
Something seems fishy about that argument; you can give the same counterexample for the boolean algebra of sets on the real line
I was wondering about that -- I guess it comes down to what Prop -> Prop
is supposed to mean? The translation example is at least an isomorphism of Heyting algebras induced by a symmetric of the underlying space, but, beyond that, it seems like you might not want to allow arbitrary functions on a Heyting algebra...
Kyle Miller (May 16 2022 at 19:39):
That's cool that you can prove the weak law of the excluded middle with this.
Mauricio Collares (May 16 2022 at 20:33):
I've had this question for a while, apologies for jumping in with a slightly off-topic question: In intuitionistic logic, is the weak law of the excluded middle both unprovable and strictly weaker than actual excluded middle? It feels like that's the case but I've never seen a proof.
Kyle Miller (May 16 2022 at 20:37):
I don't know the answer, but at least itauto
can't prove it, and it can't prove em
from the weak em
applied to the same p
.
example (p : Prop) : ¬p ∨ ¬¬p :=
by itauto -- not ok
example (p : Prop) (h : p ∨ ¬p) : ¬p ∨ ¬¬p :=
by itauto -- ok
example (p : Prop) (h : ¬p ∨ ¬¬p) : p ∨ ¬p :=
by itauto -- not ok
Mauricio Collares (May 16 2022 at 20:43):
I guess the interesting alternative would be "weak EM => EM" being unprovable.
Eric Rodriguez (May 16 2022 at 20:46):
Afair, there's a hierarchy of Em's, but this isn't it. @Mario Carneiro sent me the link before.
Kyle Miller (May 16 2022 at 20:52):
@Eric RodriguezAre you referring to this? mario's post
Direct link to an illustration of the Rieger-Nishimura lattice
Eric Rodriguez (May 16 2022 at 20:54):
Yea, that's the one!!!
Yaël Dillies (May 16 2022 at 21:10):
Yep exactly. This is also the free lattice on three elements.
Mauricio Collares (May 16 2022 at 21:15):
This is very interesting! It seems to suggest that "weak EM => EM" is really unprovable, but I am not 100% sure this is the same question. In the lattice, it looks like everything is specialized to a particular proposition.
Mario Carneiro (May 16 2022 at 21:32):
yes, weak EM => EM is unprovable, but it's true that the distinctness of the relevant points in the Rieger-Nishimura lattice does not prove this, only that weak_EM(p) -> EM(p)
is unprovable (it could be that weak_EM(f(p)) -> EM(p)
for some f
)
Mario Carneiro (May 17 2022 at 00:19):
In fact, weak EM is the only thing you can deduce from kaminski's equation (on definable formulas f
). More precisely, if f
is a univariate function on propositions built from [p, ⊤, ⊥, →, ¬, ∧, ∨]
, then ¬p ∨ ¬¬p → f (f (f p)) ↔ f p
holds.
Proof: By cases on ¬p ∨ ¬¬p
.
- If
¬p
is true, thenp <-> false
so we are in thebool
subset of the logic and thereforef (f (f p)) ↔ f p
by evaluating it to true or false and observing that this is a classical theorem. - If
¬¬p
, we end up in a three-valued logic, because¬p <-> false
and all the other operators are closed in the set[p, ⊤, ⊥]
. There are only six reachable functions in this logic:⊥, ⊤, x, ¬x, ¬¬x, x ∨ ¬x
, and for all of these functions Kaminski's theorem holds:
@[derive [decidable_eq, fintype]] inductive val | true | false | p
def val.not : val → val
| val.true := val.false
| val.false := val.true
| val.p := val.false
def val.and : val → val → val
| val.true p := p
| p val.true := p
| val.false _ := val.false
| _ val.false := val.false
| val.p val.p := val.p
def val.or : val → val → val
| val.false p := p
| p val.false := p
| val.true _ := val.true
| _ val.true := val.true
| val.p val.p := val.p
def val.imp : val → val → val
| val.false p := val.true
| p val.false := val.not p
| val.true p := p
| _ val.true := val.true
| val.p val.p := val.true
@[derive decidable] def is_valid (f : val → val) : Prop :=
(∀ v, f v = val.p → v = val.p) ∧
(f = id ∨ f = (λ i, i.or i.not) ∨ f val.true = f val.p)
theorem true.is_valid : is_valid (λ _, val.true) := dec_trivial
theorem false.is_valid : is_valid (λ _, val.false) := dec_trivial
theorem id.is_valid : is_valid id := dec_trivial
theorem not.is_valid : ∀ (f : val → val),
is_valid f → is_valid (λ i, (f i).not) := dec_trivial
theorem and.is_valid : ∀ (f g : val → val),
is_valid f → is_valid g → is_valid (λ i, (f i).and (g i)) := dec_trivial
theorem or.is_valid : ∀ (f g : val → val),
is_valid f → is_valid g → is_valid (λ i, (f i).or (g i)) := dec_trivial
theorem imp.is_valid : ∀ (f g : val → val),
is_valid f → is_valid g → is_valid (λ i, (f i).imp (g i)) := dec_trivial
theorem kaminski : ∀ (f : val → val),
is_valid f → ∀ v, f (f (f v)) = f v := dec_trivial
Kevin Buzzard (May 17 2022 at 08:24):
ha ha this is funny because abstractly the answer for f : fin 3 -> fin 3 is: if it's a 3-cycles then f^3=f^0 and if it's not then the image has size <= 2 so Kaminski kicks in after one application and we deduce f^4=f^2, so always f^8=f^2 (in particular strictly worse).
Patrick Johnson (May 17 2022 at 12:53):
Kevin Buzzard said:
Is there an analogous statement for endomorphisms of finite types? Hmm, I guess by pure thought there exist smallest numbers a(n) < b(n) such that f^a = f^b for all f:fin n -> fin n and this proof above shows a(2)=1, b(2)=3.
Do we actually have this (or similar) in mathlib?
example {n : ℕ} : ∃ (a b : ℕ), a < b ∧ ∀ {f : fin n → fin n}, (f^[a]) = (f^[b]) :=
begin
sorry
end
Aaron Bies (May 17 2022 at 13:43):
I actually looked into a more generalised version of kaminski for my own practice and this is how far I got
Aaron Bies (May 17 2022 at 13:48):
(Also, if anyone here has an idea on how to prove the last statement, please let me know)
Floris van Doorn (May 17 2022 at 13:49):
Patrick Johnson said:
Do we actually have this (or similar) in mathlib?
example {n : ℕ} : ∃ (a b : ℕ), a < b ∧ ∀ {f : fin n → fin n}, (f^[a]) = (f^[b]) := begin sorry end
It's basically docs#not_injective_infinite_fintype applied to (fin n → fin n) → (fin n → fin n)
import data.fintype.basic
open function
lemma linear_order.injective_iff {α β} [linear_order α] {f : α → β} :
injective f ↔ ∀ a b, a < b → f a ≠ f b :=
⟨λ h a b hab hfab, hab.ne $ h hfab, λ h a b hfab, by_contra $ λ hab : a ≠ b,
hab.lt_or_lt.elim (λ hab, h a b hab hfab) (λ hba, h b a hba hfab.symm)⟩
example {n : ℕ} : ∃ (a b : ℕ), a < b ∧ ∀ {f : fin n → fin n}, (f^[a]) = (f^[b]) :=
begin
have : ¬ injective (λ (k : ℕ) (f : fin n → fin n), f^[k]) :=
not_injective_infinite_fintype _,
simp_rw [linear_order.injective_iff] at this,
push_neg at this,
simp only [funext_iff] at this {single_pass := tt},
exact this
end
Reid Barton (May 17 2022 at 13:50):
Or docs#fintype.exists_ne_map_eq_of_infinite
Floris van Doorn (May 17 2022 at 13:50):
Oh, that one is a little closer indeed (with the negation of injective
unfolded).
Alex J. Best (May 17 2022 at 14:00):
Reminds me of https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/.E2.9C.94.20f.5E.5Bn.5D.20x.20.3D.20x/near/266557825, so I ended up with:
import data.fintype.basic
import group_theory.exponent
import algebra.hom.iterate
import group_theory.group_action.defs
import data.set.finite
.
lemma key {M : Type*} [fintype M] (f : M → M) (a) : (id (f^[a]) : function.End M) = f ^ a :=
begin
simp,
induction a,
refl,
simpa [a_ih, pow_succ'],
end
open monoid
open_locale classical
noncomputable theory
instance {M : Type*} [fintype M] : fintype (function.End M) := by delta_instance function.End
example {M : Type*} [fintype M] : ∃ (a b : ℕ), a < b ∧ ∀ {f : M → M}, (f^[a]) = (f^[b]) :=
begin
suffices : ∃ (a b : ℕ), a < b ∧ (λ f : function.End M, f) ^ a = (λ f : function.End M, f) ^ b,
{ apply Exists₂.imp _ this,
rintros a b ⟨h₁, h₂⟩,
simp only [h₁, true_and],
intro f,
have := congr_fun h₂ f,
rwa [pi.pow_apply, pi.pow_apply, ← key, ← key] at this, },
simpa using set.infinite_univ.exists_lt_map_eq_of_maps_to (set.maps_to_univ (λ n : ℕ, (λ f : function.End M, f) ^ n) _) set.finite_univ,
end
Floris's is much cleaner!
Kyle Miller (May 17 2022 at 14:01):
@Patrick Johnson That reminded me that a while back I built out some theory as an exercise, and it could be used to prove this. The core idea is that for a fintype, there's some positive n such that f^[n]
is a bijection when restricted to its image, and then you can take the order k
of that permutation to get that f^[n] = f^[n+k]
.
Kyle Miller (May 17 2022 at 14:02):
Oh, that's in the same thread Alex just linked to.
Kyle Miller (May 17 2022 at 15:53):
I think the "Kaminski-Buzzard-Morrison" numbers can be found the following way:
Supposing a < b and f^a = f^b, then f restricted to f^a is a bijection. Hence b-a <= g(|im f^a|), where g(n) is the Landau function (the largest order of an element of the symmetric group).
Given any finite set X, subset S, and permutation p of S, then that permutation can be extended to be a function f : X -> X such that the image of some power of f is S. There is such an f such that the least such power is |X - S|, and this is the maximal least power over all f. In this case, a=|X-S| and b=a+order(p). So, one can maximize b by taking p with maximal order, getting a=|X-S| and b=a+g(|S|).
Hence, the set of all Kaminski-Buzzard-Morrison numbers for a particular set X of cardinality n is {(n-k, n-k+g(k)) | k in 1..n}. I'm defining the numbers to be pairs (a,b) from those equations f^a=f^b with a<b such that there is no smaller a for the given f and, for that a, no other f that can make b larger.
Kyle Miller (May 17 2022 at 15:55):
I just realized I made a mistake there -- these aren't the universal numbers since you do need to take the lcm of all the orders.
Kyle Miller (May 17 2022 at 16:01):
Anyway, you need a(n) = n-1 since f
could be pred
on fin n
, and then b(n) = lcm(1,2,...,n) + n - 1. That matches what Kevin said for the n=3 case (f^8 = f^2).
Kyle Miller (May 17 2022 at 16:10):
Aaron Bies said:
Related to the generalized case, how does one arrive at the conclusion that A0665500 is equivalent to ?
I see you already mentioned this formula. I think what's going on is that the only functions you can really define using the typed lambda calculus are iterates, so 1, f, f^1, f^2, ..., f^(b-1) are the only functions.
Mario Carneiro (May 17 2022 at 19:49):
Kevin Buzzard said:
ha ha this is funny because abstractly the answer for f : fin 3 -> fin 3 is: if it's a 3-cycles then f^3=f^0 and if it's not then the image has size <= 2 so Kaminski kicks in after one application and we deduce f^4=f^2, so always f^8=f^2 (in particular strictly worse).
Note that it's not really fin 3 -> fin 3
; although there are three values in the domain the third element is rather special since you can't just map it arbitrarily, and true
and false
can never map to p
. I ended up with the list of conditions in is_valid
more or less by seeing what things were preserved by the operations.
Kevin Buzzard (May 17 2022 at 20:06):
Yes exactly, the weird logic stuff saves you; the fin 3 argument is what you get for free but you teased more out of it
Patrick Johnson (Sep 30 2022 at 16:06):
Aaron Bies said:
I actually looked into a more generalised version of kaminski for my own practice and this is how far I got
(Also, if anyone here has an idea on how to prove the last statement, please let me know)
I proved it for a = n
and b = n + n.factorial
(proof). It's probably easy to reduce it to b = list.foldr nat.lcm 1 (list.iota n) + n
, but the problem is -1
both in a
and b
, which I didn't manage to prove.
Last updated: Dec 20 2023 at 11:08 UTC