module 1Lab.Function.Antiinjection whereAntiinjective 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
pt : B
x₀ : A
x₁ : A
map-to₀ : f x₀ ≡ pt
map-to₁ : f x₁ ≡ pt
distinct : ¬ (x₀ ≡ x₁)
is-antiinjective : (A → B) → Type _
is-antiinjective f = ∥ split-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 =
f-antiinj .distinct (f-inj (f-antiinj .map-to₀ ∙ sym (f-antiinj .map-to₁)))
is-antiinj→not-injective
: {f : A → B}
→ is-antiinjective f
→ ¬ (injective f)
is-antiinj→not-injective f-antiinj =
rec! split-antiinj→not-injective f-antiinjPrecomposition 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)
split-antiinj-∘r {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
is-antiinj-∘r
: {f : B → C} {g : A → B}
→ is-antiinjective g
→ is-antiinjective (f ∘ g)
is-antiinj-∘r {f = f} = ∥-∥-map (split-antiinj-∘r {f = f})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)
split-antiinj+in-image→split-antiinj {f = f} {g = g} f-ai (a₀ , p₀) (a₁ , p₁) = fg-ai
where
fg-ai : 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₁)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 =
split-antiinj+in-image→split-antiinj f-ai (g-s (f-ai .x₀)) (g-s (f-ai .x₁))
is-antiinj+is-surj→is-antiinj
: {f : B → C} {g : A → B}
→ is-antiinjective f
→ is-surjective g
→ is-antiinjective (f ∘ g)
is-antiinj+is-surj→is-antiinj ∥f-ai∥ g-s = do
f-ai ← ∥f-ai∥
fib₀ ← g-s (f-ai .x₀)
fib₁ ← g-s (f-ai .x₁)
pure (split-antiinj+in-image→split-antiinj f-ai fib₀ fib₁)split-antiinj-cancell
: {f : B → C} {g : A → B}
→ injective f
→ split-antiinjective (f ∘ g)
→ split-antiinjective g
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .pt =
g (fg-ai .x₀)
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .x₀ =
fg-ai .x₀
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .x₁ =
fg-ai .x₁
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .map-to₀ =
refl
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .map-to₁ =
f-inj (fg-ai .map-to₁ ∙ sym (fg-ai .map-to₀))
split-antiinj-cancell {f = f} {g = g} f-inj fg-ai .distinct =
fg-ai .distinct
is-antiinj-cancell
: {f : B → C} {g : A → B}
→ injective f
→ is-antiinjective (f ∘ g)
→ is-antiinjective g
is-antiinj-cancell f-inj = ∥-∥-map (split-antiinj-cancell f-inj)