module 1Lab.Function.Antiinjection where
Antiinjective functions🔗
A function is split antiinjective if it comes equipped with a choice of fibre that contains 2 distinct elements. Likewise, a function is antiinjective if it is merely split injective. This is constructively stronger than non-injective, as we actually know at least one obstruction to injectivity! Moreover, note that split antiinjectivity is a structure on a function, not a property; there may be obstructions to injectivity.
record split-antiinjective (f : A → B) : Type (level-of A ⊔ level-of B) where
no-eta-equality
field
: B
pt : A
x₀ : A
x₁ : f x₀ ≡ pt
map-to₀ : f x₁ ≡ pt
map-to₁ : ¬ (x₀ ≡ x₁)
distinct
: (A → B) → Type _
is-antiinjective = ∥ split-antiinjective f ∥ is-antiinjective f
As the name suggests, antiinjective functions are not injective.
split-antiinj→not-injective: {f : A → B}
→ split-antiinjective f
→ ¬ (injective f)
=
split-antiinj→not-injective f-antiinj f-inj .distinct (f-inj (f-antiinj .map-to₀ ∙ sym (f-antiinj .map-to₁)))
f-antiinj
is-antiinj→not-injective: {f : A → B}
→ is-antiinjective f
→ ¬ (injective f)
=
is-antiinj→not-injective f-antiinj rec! split-antiinj→not-injective f-antiinj
Precomposition by an (split) antinjective function always yields a (split) antiinjective function.
split-antiinj-∘r: {f : B → C} {g : A → B}
→ split-antiinjective g
→ split-antiinjective (f ∘ g)
{f = f} g-antiinj .pt = f (g-antiinj .pt)
split-antiinj-∘r {f = f} g-antiinj .x₀ = g-antiinj .x₀
split-antiinj-∘r {f = f} g-antiinj .x₁ = g-antiinj .x₁
split-antiinj-∘r {f = f} g-antiinj .map-to₀ = ap f (g-antiinj .map-to₀)
split-antiinj-∘r {f = f} g-antiinj .map-to₁ = ap f (g-antiinj .map-to₁)
split-antiinj-∘r {f = f} g-antiinj .distinct = g-antiinj .distinct
split-antiinj-∘r
is-antiinj-∘r: {f : B → C} {g : A → B}
→ is-antiinjective g
→ is-antiinjective (f ∘ g)
{f = f} = ∥-∥-map (split-antiinj-∘r {f = f}) is-antiinj-∘r
If is split antiinjective and can be equipped with a choice of fibres at the obstruction to injectivity, then is also antiinjective.
split-antiinj+in-image→split-antiinj: {f : B → C} {g : A → B}
→ (f-ai : split-antiinjective f)
→ fibre g (f-ai .x₀) → fibre g (f-ai .x₁)
→ split-antiinjective (f ∘ g)
{f = f} {g = g} f-ai (a₀ , p₀) (a₁ , p₁) = fg-ai
split-antiinj+in-image→split-antiinj where
: split-antiinjective (f ∘ g)
fg-ai .pt = f-ai .pt
fg-ai .x₀ = a₀
fg-ai .x₁ = a₁
fg-ai .map-to₀ = ap f p₀ ∙ f-ai .map-to₀
fg-ai .map-to₁ = ap f p₁ ∙ f-ai .map-to₁
fg-ai .distinct a₀=a₁ = f-ai .distinct (sym p₀ ·· ap g a₀=a₁ ·· p₁) fg-ai
In particular, this means that composing a (split) antiinjection with a (split) surjection yields a (split) antiinjection.
split-antiinj+split-surj→split-antiinj: {f : B → C} {g : A → B}
→ split-antiinjective f
→ split-surjective g
→ split-antiinjective (f ∘ g)
=
split-antiinj+split-surj→split-antiinj f-ai g-s (g-s (f-ai .x₀)) (g-s (f-ai .x₁))
split-antiinj+in-image→split-antiinj f-ai
is-antiinj+is-surj→is-antiinj: {f : B → C} {g : A → B}
→ is-antiinjective f
→ is-surjective g
→ is-antiinjective (f ∘ g)
= do
is-antiinj+is-surj→is-antiinj ∥f-ai∥ g-s
f-ai ← ∥f-ai∥(f-ai .x₀)
fib₀ ← g-s (f-ai .x₁)
fib₁ ← g-s (split-antiinj+in-image→split-antiinj f-ai fib₀ fib₁) pure
split-antiinj-cancell: {f : B → C} {g : A → B}
→ injective f
→ split-antiinjective (f ∘ g)
→ split-antiinjective g
{f = f} {g = g} f-inj fg-ai .pt =
split-antiinj-cancell (fg-ai .x₀)
g {f = f} {g = g} f-inj fg-ai .x₀ =
split-antiinj-cancell .x₀
fg-ai {f = f} {g = g} f-inj fg-ai .x₁ =
split-antiinj-cancell .x₁
fg-ai {f = f} {g = g} f-inj fg-ai .map-to₀ =
split-antiinj-cancell
refl{f = f} {g = g} f-inj fg-ai .map-to₁ =
split-antiinj-cancell (fg-ai .map-to₁ ∙ sym (fg-ai .map-to₀))
f-inj {f = f} {g = g} f-inj fg-ai .distinct =
split-antiinj-cancell .distinct
fg-ai
is-antiinj-cancell: {f : B → C} {g : A → B}
→ injective f
→ is-antiinjective (f ∘ g)
→ is-antiinjective g
= ∥-∥-map (split-antiinj-cancell f-inj) is-antiinj-cancell f-inj