import tactic.noncomm_ring

local notation `⁅`a`,` b`⁆` := a * b - b * a
local infix ` ⚬ `:70 := λ a b, a * b + b * a

variables {R : Type*} [ring R]
variables (a b c : R)

example : 0 = 0 := by noncomm_ring
example : a = a := by noncomm_ring

example : (a + b) * c = a * c + b * c := by noncomm_ring
example : a * (b + c) = a * b + a * c := by noncomm_ring
example : a - b = a + -b := by noncomm_ring
example : a * b * c = a * (b * c) := by noncomm_ring
example : a + a = a * 2 := by noncomm_ring
example : a + a = 2 * a := by noncomm_ring
example : -a = (-1) * a := by noncomm_ring
example : a + a + a = 3 * a := by noncomm_ring
example : a ^ 2 = a * a := by noncomm_ring
example : a ^ 3 = a * a * a := by noncomm_ring
example : (-a) * b = -(a * b) := by noncomm_ring
example : a * (-b) = -(a * b) := by noncomm_ring
example : a * (b + c + b + c - 2*b) = 2*a*c := by noncomm_ring
example : a * (b + c + b + c - (2 : ℕ) • b) = 2*a*c := by noncomm_ring
example : (a + b)^2 = a^2 + a*b + b*a + b^2 := by noncomm_ring
example : (a - b)^2 = a^2 - a*b - b*a + b^2 := by noncomm_ring
example : (a + b)^3 = a^3 + a^2*b + a*b*a + a*b^2 + b*a^2 + b*a*b + b^2*a + b^3 := by noncomm_ring
example : (a - b)^3 = a^3 - a^2*b - a*b*a + a*b^2 - b*a^2 + b*a*b + b^2*a - b^3 := by noncomm_ring

example : ⁅a, a⁆ = 0 := by noncomm_ring
example : ⁅a, b⁆ = -⁅b, a⁆ := by noncomm_ring
example : ⁅a + b, c⁆ = ⁅a, c⁆ + ⁅b, c⁆ := by noncomm_ring
example : ⁅a, b + c⁆ = ⁅a, b⁆ + ⁅a, c⁆ := by noncomm_ring
example : ⁅a, ⁅b, c⁆⁆ + ⁅b, ⁅c, a⁆⁆ + ⁅c, ⁅a, b⁆⁆ = 0 := by noncomm_ring
example : ⁅⁅a, b⁆, c⁆ + ⁅⁅b, c⁆, a⁆ + ⁅⁅c, a⁆, b⁆ = 0 := by noncomm_ring
example : ⁅a, ⁅b, c⁆⁆ = ⁅⁅a, b⁆, c⁆ + ⁅b, ⁅a, c⁆⁆ := by noncomm_ring
example : ⁅⁅a, b⁆, c⁆ = ⁅⁅a, c⁆, b⁆ + ⁅a, ⁅b, c⁆⁆ := by noncomm_ring
example : ⁅a * b, c⁆ = a * ⁅b, c⁆ + ⁅a, c⁆ * b := by noncomm_ring
example : ⁅a, b * c⁆ = ⁅a, b⁆ * c + b * ⁅a, c⁆ := by noncomm_ring
example : ⁅3 * a, a⁆ = 0 := by noncomm_ring
example : ⁅a * -5, a⁆ = 0 := by noncomm_ring
example : ⁅a^3, a⁆ = 0 := by noncomm_ring

example : a ⚬ a = 2*a^2 := by noncomm_ring
example : (2 * a) ⚬ a = 4*a^2 := by noncomm_ring
example : a ⚬ b = b ⚬ a := by noncomm_ring
example : a ⚬ (b + c) = a ⚬ b + a ⚬ c := by noncomm_ring
example : (a + b) ⚬ c = a ⚬ c + b ⚬ c := by noncomm_ring
example : (a ⚬ b) ⚬ (a ⚬ a) = a ⚬ (b ⚬ (a ⚬ a)) := by noncomm_ring

example : ⁅a, b ⚬ c⁆ = ⁅a, b⁆ ⚬ c + b ⚬ ⁅a, c⁆ := by noncomm_ring
example : ⁅a ⚬ b, c⁆ = a ⚬ ⁅b, c⁆ + ⁅a, c⁆ ⚬ b := by noncomm_ring
example : (a ⚬ b) ⚬ c - a ⚬ (b ⚬ c) = -⁅⁅a, b⁆, c⁆ + ⁅a, ⁅b, c⁆⁆ := by noncomm_ring

example : a + -b = -b + a := by noncomm_ring


/-
Copyright (c) 2018 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Jeremy Avigad, Simon Hudon
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.data.pfunctor.multivariate.W
import Mathlib.data.qpf.multivariate.basic
import Mathlib.PostPort

universes u u_1

namespace Mathlib

/-!
# The initial algebra of a multivariate qpf is again a qpf.

For a `(n+1)`-ary QPF `F (α₀,..,αₙ)`, we take the least fixed point of `F` with
regards to its last argument `αₙ`. The result is a `n`-ary functor: `fix F (α₀,..,αₙ₋₁)`.
Making `fix F` into a functor allows us to take the fixed point, compose with other functors
and take a fixed point again.

## Main definitions

 * `fix.mk`     - constructor
 * `fix.dest    - destructor
 * `fix.rec`    - recursor: basis for defining functions by structural recursion on `fix F α`
 * `fix.drec`   - dependent recursor: generalization of `fix.rec` where the result type of the function
                  is allowed to dependent on the `fix F α` value
 * `fix.rec_eq` - defining equation for `recursor`
 * `fix.ind`    - induction principle for `fix F α`

## Implementation notes

For `F` a QPF`, we define `fix F α` in terms of the W-type of the polynomial functor `P` of `F`.
We define the relation `Wequiv` and take its quotient as the definition of `fix F α`.

```lean
inductive Wequiv {α : typevec n} : q.P.W α → q.P.W α → Prop
| ind (a : q.P.A) (f' : q.P.drop.B a ⟹ α) (f₀ f₁ : q.P.last.B a → q.P.W α) :
    (∀ x, Wequiv (f₀ x) (f₁ x)) → Wequiv (q.P.W_mk a f' f₀) (q.P.W_mk a f' f₁)
| abs (a₀ : q.P.A) (f'₀ : q.P.drop.B a₀ ⟹ α) (f₀ : q.P.last.B a₀ → q.P.W α)
      (a₁ : q.P.A) (f'₁ : q.P.drop.B a₁ ⟹ α) (f₁ : q.P.last.B a₁ → q.P.W α) :
      abs ⟨a₀, q.P.append_contents f'₀ f₀⟩ = abs ⟨a₁, q.P.append_contents f'₁ f₁⟩ →
        Wequiv (q.P.W_mk a₀ f'₀ f₀) (q.P.W_mk a₁ f'₁ f₁)
| trans (u v w : q.P.W α) : Wequiv u v → Wequiv v w → Wequiv u w
```

See [avigad-carneiro-hudon2019] for more details.

## Reference

 * [Jeremy Avigad, Mario M. Carneiro and Simon Hudon, *Data Types as Quotients of Polynomial Functors*][avigad-carneiro-hudon2019]
-/

namespace mvqpf

/-- `recF` is used as a basis for defining the recursor on `fix F α`. `recF`
traverses recursively the W-type generated by `q.P` using a function on `F`
as a recursive step -/
def recF {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) : mvpfunctor.W (P F) α → β :=
  mvpfunctor.W_rec (P F)
    fun (a : mvpfunctor.A (P F)) (f' : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a) α)
      (f : pfunctor.B (mvpfunctor.last (P F)) a → mvpfunctor.W (P F) α)
      (rec : pfunctor.B (mvpfunctor.last (P F)) a → β) => g (abs (sigma.mk a (typevec.split_fun f' rec)))

theorem recF_eq {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) (a : mvpfunctor.A (P F)) (f' : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a) α) (f : pfunctor.B (mvpfunctor.last (P F)) a → mvpfunctor.W (P F) α) : recF g (mvpfunctor.W_mk (P F) a f' f) = g (abs (sigma.mk a (typevec.split_fun f' (recF g ∘ f)))) := sorry

theorem recF_eq' {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) (x : mvpfunctor.W (P F) α) : recF g x = g (abs (mvfunctor.map (typevec.id ::: recF g) (mvpfunctor.W_dest' (P F) x))) := sorry

/-- Equivalence relation on W-types that represent the same `fix F`
value -/
inductive Wequiv {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} : mvpfunctor.W (P F) α → mvpfunctor.W (P F) α → Prop
where
| ind : ∀ (a : mvpfunctor.A (P F)) (f' : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a) α)
  (f₀ f₁ : pfunctor.B (mvpfunctor.last (P F)) a → mvpfunctor.W (P F) α),
  (∀ (x : pfunctor.B (mvpfunctor.last (P F)) a), Wequiv (f₀ x) (f₁ x)) →
    Wequiv (mvpfunctor.W_mk (P F) a f' f₀) (mvpfunctor.W_mk (P F) a f' f₁)
| abs : ∀ (a₀ : mvpfunctor.A (P F)) (f'₀ : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a₀) α)
  (f₀ : pfunctor.B (mvpfunctor.last (P F)) a₀ → mvpfunctor.W (P F) α) (a₁ : mvpfunctor.A (P F))
  (f'₁ : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a₁) α)
  (f₁ : pfunctor.B (mvpfunctor.last (P F)) a₁ → mvpfunctor.W (P F) α),
  abs (sigma.mk a₀ (mvpfunctor.append_contents (P F) f'₀ f₀)) =
      abs (sigma.mk a₁ (mvpfunctor.append_contents (P F) f'₁ f₁)) →
    Wequiv (mvpfunctor.W_mk (P F) a₀ f'₀ f₀) (mvpfunctor.W_mk (P F) a₁ f'₁ f₁)
| trans : ∀ (u v w : mvpfunctor.W (P F) α), Wequiv u v → Wequiv v w → Wequiv u w

theorem recF_eq_of_Wequiv {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] (α : typevec n) {β : Type u} (u : F (α ::: β) → β) (x : mvpfunctor.W (P F) α) (y : mvpfunctor.W (P F) α) : Wequiv x y → recF u x = recF u y := sorry

theorem Wequiv.abs' {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : mvpfunctor.W (P F) α) (y : mvpfunctor.W (P F) α) (h : abs (mvpfunctor.W_dest' (P F) x) = abs (mvpfunctor.W_dest' (P F) y)) : Wequiv x y := sorry

theorem Wequiv.refl {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : mvpfunctor.W (P F) α) : Wequiv x x := sorry

theorem Wequiv.symm {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : mvpfunctor.W (P F) α) (y : mvpfunctor.W (P F) α) : Wequiv x y → Wequiv y x := sorry

/-- maps every element of the W type to a canonical representative -/
def Wrepr {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} : mvpfunctor.W (P F) α → mvpfunctor.W (P F) α :=
  recF (mvpfunctor.W_mk' (P F) ∘ repr)

theorem Wrepr_W_mk {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (a : mvpfunctor.A (P F)) (f' : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a) α) (f : pfunctor.B (mvpfunctor.last (P F)) a → mvpfunctor.W (P F) α) : Wrepr (mvpfunctor.W_mk (P F) a f' f) =
  mvpfunctor.W_mk' (P F)
    (repr (abs (mvfunctor.map (typevec.id ::: Wrepr) (sigma.mk a (mvpfunctor.append_contents (P F) f' f))))) := sorry

theorem Wrepr_equiv {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : mvpfunctor.W (P F) α) : Wequiv (Wrepr x) x := sorry

theorem Wequiv_map {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : typevec n} (g : typevec.arrow α β) (x : mvpfunctor.W (P F) α) (y : mvpfunctor.W (P F) α) : Wequiv x y → Wequiv (mvfunctor.map g x) (mvfunctor.map g y) := sorry

/--
Define the fixed point as the quotient of trees under the equivalence relation.
-/
def W_setoid {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] (α : typevec n) : setoid (mvpfunctor.W (P F) α) :=
  setoid.mk Wequiv sorry

/-- Least fixed point of functor F. The result is a functor with one fewer parameters
than the input. For `F a b c` a ternary functor, fix F is a binary functor such that

```lean
fix F a b = F a b (fix F a b)
```
-/
def fix {n : ℕ} (F : typevec (n + 1) → Type u_1) [mvfunctor F] [q : mvqpf F] (α : typevec n) :=
  quotient (W_setoid α)

/-- `fix F` is a functor -/
def fix.map {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : typevec n} (g : typevec.arrow α β) : fix F α → fix F β :=
  quotient.lift (fun (x : mvpfunctor.W (P F) α) => quotient.mk (mvpfunctor.W_map (P F) g x)) sorry

protected instance fix.mvfunctor {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] : mvfunctor (fix F) :=
  mvfunctor.mk fix.map

/-- Recursor for `fix F` -/
def fix.rec {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) : fix F α → β :=
  Quot.lift (recF g) (recF_eq_of_Wequiv α g)

/-- Access W-type underlying `fix F`  -/
def fix_to_W {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} : fix F α → mvpfunctor.W (P F) α :=
  quotient.lift Wrepr sorry

/-- Constructor for `fix F` -/
def fix.mk {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : F (α ::: fix F α)) : fix F α :=
  Quot.mk setoid.r (mvpfunctor.W_mk' (P F) (mvfunctor.map (typevec.id ::: fix_to_W) (repr x)))

/-- Destructor for `fix F` -/
def fix.dest {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} : fix F α → F (α ::: fix F α) :=
  fix.rec (mvfunctor.map (typevec.id ::: fix.mk))

theorem fix.rec_eq {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) (x : F (α ::: fix F α)) : fix.rec g (fix.mk x) = g (mvfunctor.map (typevec.id ::: fix.rec g) x) := sorry

theorem fix.ind_aux {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (a : mvpfunctor.A (P F)) (f' : typevec.arrow (mvpfunctor.B (mvpfunctor.drop (P F)) a) α) (f : pfunctor.B (mvpfunctor.last (P F)) a → mvpfunctor.W (P F) α) : fix.mk
    (abs
      (sigma.mk a
        (mvpfunctor.append_contents (P F) f' fun (x : pfunctor.B (mvpfunctor.last (P F)) a) => quotient.mk (f x)))) =
  quotient.mk (mvpfunctor.W_mk (P F) a f' f) := sorry

theorem fix.ind_rec {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g₁ : fix F α → β) (g₂ : fix F α → β) (h : ∀ (x : F (α ::: fix F α)),
  mvfunctor.map (typevec.id ::: g₁) x = mvfunctor.map (typevec.id ::: g₂) x → g₁ (fix.mk x) = g₂ (fix.mk x)) (x : fix F α) : g₁ x = g₂ x := sorry

theorem fix.rec_unique {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : Type u} (g : F (α ::: β) → β) (h : fix F α → β) (hyp : ∀ (x : F (α ::: fix F α)), h (fix.mk x) = g (mvfunctor.map (typevec.id ::: h) x)) : fix.rec g = h := sorry

theorem fix.mk_dest {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : fix F α) : fix.mk (fix.dest x) = x := sorry

theorem fix.dest_mk {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (x : F (α ::: fix F α)) : fix.dest (fix.mk x) = x := sorry

theorem fix.ind {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} (p : fix F α → Prop) (h : ∀ (x : F (α ::: fix F α)), mvfunctor.liftp (typevec.pred_last α p) x → p (fix.mk x)) (x : fix F α) : p x := sorry

protected instance mvqpf_fix {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] : mvqpf (fix F) :=
  mk (mvpfunctor.Wp (P F)) (fun (α : typevec n) => Quot.mk Wequiv) (fun (α : typevec n) => fix_to_W) sorry sorry

/-- Dependent recursor for `fix F` -/
def fix.drec {n : ℕ} {F : typevec (n + 1) → Type u} [mvfunctor F] [q : mvqpf F] {α : typevec n} {β : fix F α → Type u} (g : (x : F (α ::: sigma β)) → β (fix.mk (mvfunctor.map (typevec.id ::: sigma.fst) x))) (x : fix F α) : β x :=
  let y : sigma β :=
    fix.rec (fun (i : F (α ::: sigma β)) => sigma.mk (fix.mk (mvfunctor.map (typevec.id ::: sigma.fst) i)) (g i)) x;
  (fun (this : x = sigma.fst y) => cast sorry (sigma.snd y)) sorry


/-
Copyright (c) 2021 Aaron Anderson, Yaël Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Aaron Anderson, Kevin Buzzard, Yaël Dillies, Eric Wieser

! This file was ported from Lean 3 source module order.sup_indep
! leanprover-community/mathlib commit 1c857a1f6798cb054be942199463c2cf904cb937
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.Finset.Pairwise
import Mathbin.Data.Finset.Powerset
import Mathbin.Data.Fintype.Basic

/-!
# Supremum independence

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

In this file, we define supremum independence of indexed sets. An indexed family `f : ι → α` is
sup-independent if, for all `a`, `f a` and the supremum of the rest are disjoint.

## Main definitions

* `finset.sup_indep s f`: a family of elements `f` are supremum independent on the finite set `s`.
* `complete_lattice.set_independent s`: a set of elements are supremum independent.
* `complete_lattice.independent f`: a family of elements are supremum independent.

## Main statements

* In a distributive lattice, supremum independence is equivalent to pairwise disjointness:
  * `finset.sup_indep_iff_pairwise_disjoint`
  * `complete_lattice.set_independent_iff_pairwise_disjoint`
  * `complete_lattice.independent_iff_pairwise_disjoint`
* Otherwise, supremum independence is stronger than pairwise disjointness:
  * `finset.sup_indep.pairwise_disjoint`
  * `complete_lattice.set_independent.pairwise_disjoint`
  * `complete_lattice.independent.pairwise_disjoint`

## Implementation notes

For the finite version, we avoid the "obvious" definition
`∀ i ∈ s, disjoint (f i) ((s.erase i).sup f)` because `erase` would require decidable equality on
`ι`.
-/

variable {α β ι ι' : Type _}

/-! ### On lattices with a bottom element, via `finset.sup` -/

namespace Finset

section Lattice

variable [Lattice α] [OrderBot α]

#print Finset.SupIndep /-
/-- Supremum independence of finite sets. We avoid the "obvious" definition using `s.erase i`
because `erase` would require decidable equality on `ι`. -/
def SupIndep (s : Finset ι) (f : ι → α) : Prop :=
  ∀ ⦃t⦄, t ⊆ s → ∀ ⦃i⦄, i ∈ s → i ∉ t → Disjoint (f i) (t.sup f)
#align finset.sup_indep Finset.SupIndep
-/

variable {s t : Finset ι} {f : ι → α} {i : ι}

instance [DecidableEq ι] [DecidableEq α] : Decidable (SupIndep s f) :=
  by
  apply @Finset.decidableForallOfDecidableSubsets _ _ _ _
  intro t ht
  apply @Finset.decidableDforallFinset _ _ _ _
  exact fun i hi => @Implies.decidable _ _ _ (decidable_of_iff' (_ = ⊥) disjoint_iff)

/- warning: finset.sup_indep.subset -> Finset.SupIndep.subset is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] {s : Finset.{u2} ι} {t : Finset.{u2} ι} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 t f) -> (HasSubset.Subset.{u2} (Finset.{u2} ι) (Finset.hasSubset.{u2} ι) s t) -> (Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 s f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] {s : Finset.{u1} ι} {t : Finset.{u1} ι} {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 t f) -> (HasSubset.Subset.{u1} (Finset.{u1} ι) (Finset.instHasSubsetFinset.{u1} ι) s t) -> (Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 s f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.subset Finset.SupIndep.subsetₓ'. -/
theorem SupIndep.subset (ht : t.SupIndep f) (h : s ⊆ t) : s.SupIndep f := fun u hu i hi =>
  ht (hu.trans h) (h hi)
#align finset.sup_indep.subset Finset.SupIndep.subset

/- warning: finset.sup_indep_empty -> Finset.supIndep_empty is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] (f : ι -> α), Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 (EmptyCollection.emptyCollection.{u2} (Finset.{u2} ι) (Finset.hasEmptyc.{u2} ι)) f
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] (f : ι -> α), Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 (EmptyCollection.emptyCollection.{u1} (Finset.{u1} ι) (Finset.instEmptyCollectionFinset.{u1} ι)) f
Case conversion may be inaccurate. Consider using '#align finset.sup_indep_empty Finset.supIndep_emptyₓ'. -/
theorem supIndep_empty (f : ι → α) : (∅ : Finset ι).SupIndep f := fun _ _ a ha => ha.elim
#align finset.sup_indep_empty Finset.supIndep_empty

/- warning: finset.sup_indep_singleton -> Finset.supIndep_singleton is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] (i : ι) (f : ι -> α), Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 (Singleton.singleton.{u2, u2} ι (Finset.{u2} ι) (Finset.hasSingleton.{u2} ι) i) f
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] (i : ι) (f : ι -> α), Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 (Singleton.singleton.{u1, u1} ι (Finset.{u1} ι) (Finset.instSingletonFinset.{u1} ι) i) f
Case conversion may be inaccurate. Consider using '#align finset.sup_indep_singleton Finset.supIndep_singletonₓ'. -/
theorem supIndep_singleton (i : ι) (f : ι → α) : ({i} : Finset ι).SupIndep f := fun s hs j hji hj =>
  by
  rw [eq_empty_of_ssubset_singleton ⟨hs, fun h => hj (h hji)⟩, sup_empty]
  exact disjoint_bot_right
#align finset.sup_indep_singleton Finset.supIndep_singleton

/- warning: finset.sup_indep.pairwise_disjoint -> Finset.SupIndep.pairwiseDisjoint is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] {s : Finset.{u2} ι} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 s f) -> (Set.PairwiseDisjoint.{u1, u2} α ι (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1)) _inst_2 ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} ι) (Set.{u2} ι) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (Finset.Set.hasCoeT.{u2} ι))) s) f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] {s : Finset.{u1} ι} {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 s f) -> (Set.PairwiseDisjoint.{u2, u1} α ι (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1)) _inst_2 (Finset.toSet.{u1} ι s) f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.pairwise_disjoint Finset.SupIndep.pairwiseDisjointₓ'. -/
theorem SupIndep.pairwiseDisjoint (hs : s.SupIndep f) : (s : Set ι).PairwiseDisjoint f :=
  fun a ha b hb hab =>
  sup_singleton.subst <| hs (singleton_subset_iff.2 hb) ha <| not_mem_singleton.2 hab
#align finset.sup_indep.pairwise_disjoint Finset.SupIndep.pairwiseDisjoint

#print Finset.supIndep_iff_disjoint_erase /-
/-- The RHS looks like the definition of `complete_lattice.independent`. -/
theorem supIndep_iff_disjoint_erase [DecidableEq ι] :
    s.SupIndep f ↔ ∀ i ∈ s, Disjoint (f i) ((s.eraseₓ i).sup f) :=
  ⟨fun hs i hi => hs (erase_subset _ _) hi (not_mem_erase _ _), fun hs t ht i hi hit =>
    (hs i hi).mono_right (sup_mono fun j hj => mem_erase.2 ⟨ne_of_mem_of_not_mem hj hit, ht hj⟩)⟩
#align finset.sup_indep_iff_disjoint_erase Finset.supIndep_iff_disjoint_erase
-/

#print Finset.supIndep_pair /-
@[simp]
theorem supIndep_pair [DecidableEq ι] {i j : ι} (hij : i ≠ j) :
    ({i, j} : Finset ι).SupIndep f ↔ Disjoint (f i) (f j) :=
  ⟨fun h => h.PairwiseDisjoint (by simp) (by simp) hij, fun h =>
    by
    rw [sup_indep_iff_disjoint_erase]
    intro k hk
    rw [Finset.mem_insert, Finset.mem_singleton] at hk
    obtain rfl | rfl := hk
    · convert h using 1
      rw [Finset.erase_insert, Finset.sup_singleton]
      simpa using hij
    · convert h.symm using 1
      have : ({i, k} : Finset ι).eraseₓ k = {i} := by
        ext
        rw [mem_erase, mem_insert, mem_singleton, mem_singleton, and_or_left, Ne.def,
          not_and_self_iff, or_false_iff, and_iff_right_of_imp]
        rintro rfl
        exact hij
      rw [this, Finset.sup_singleton]⟩
#align finset.sup_indep_pair Finset.supIndep_pair
-/

#print Finset.supIndep_univ_bool /-
theorem supIndep_univ_bool (f : Bool → α) :
    (Finset.univ : Finset Bool).SupIndep f ↔ Disjoint (f false) (f true) :=
  haveI : tt ≠ ff := by simp only [Ne.def, not_false_iff]
  (sup_indep_pair this).trans disjoint_comm
#align finset.sup_indep_univ_bool Finset.supIndep_univ_bool
-/

/- warning: finset.sup_indep_univ_fin_two -> Finset.supIndep_univ_fin_two is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] (f : (Fin (OfNat.ofNat.{0} Nat 2 (OfNat.mk.{0} Nat 2 (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))))) -> α), Iff (Finset.SupIndep.{u1, 0} α (Fin (OfNat.ofNat.{0} Nat 2 (OfNat.mk.{0} Nat 2 (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))))) _inst_1 _inst_2 (Finset.univ.{0} (Fin (OfNat.ofNat.{0} Nat 2 (OfNat.mk.{0} Nat 2 (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))))) (Fin.fintype (OfNat.ofNat.{0} Nat 2 (OfNat.mk.{0} Nat 2 (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne)))))) f) (Disjoint.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1)) _inst_2 (f (OfNat.ofNat.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) 0 (OfNat.mk.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) 0 (Zero.zero.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) (Fin.hasZeroOfNeZero (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne)) (ZeroLEOneClass.NeZero.two.{0} Nat (AddCommMonoidWithOne.toAddMonoidWithOne.{0} Nat (NonAssocSemiring.toAddCommMonoidWithOne.{0} Nat (Semiring.toNonAssocSemiring.{0} Nat Nat.semiring))) (OrderedCancelAddCommMonoid.toPartialOrder.{0} Nat (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} Nat Nat.strictOrderedSemiring)) (OrderedSemiring.zeroLEOneClass.{0} Nat Nat.orderedSemiring) (NeZero.one.{0} Nat (NonAssocSemiring.toMulZeroOneClass.{0} Nat (Semiring.toNonAssocSemiring.{0} Nat Nat.semiring)) Nat.nontrivial) (OrderedAddCommMonoid.to_covariantClass_left.{0} Nat (OrderedSemiring.toOrderedAddCommMonoid.{0} Nat Nat.orderedSemiring)))))))) (f (OfNat.ofNat.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) 1 (OfNat.mk.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) 1 (One.one.{0} (Fin (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne))) (Fin.hasOneOfNeZero (bit0.{0} Nat Nat.hasAdd (One.one.{0} Nat Nat.hasOne)) (ZeroLEOneClass.NeZero.two.{0} Nat (AddCommMonoidWithOne.toAddMonoidWithOne.{0} Nat (NonAssocSemiring.toAddCommMonoidWithOne.{0} Nat (Semiring.toNonAssocSemiring.{0} Nat Nat.semiring))) (OrderedCancelAddCommMonoid.toPartialOrder.{0} Nat (StrictOrderedSemiring.toOrderedCancelAddCommMonoid.{0} Nat Nat.strictOrderedSemiring)) (OrderedSemiring.zeroLEOneClass.{0} Nat Nat.orderedSemiring) (NeZero.one.{0} Nat (NonAssocSemiring.toMulZeroOneClass.{0} Nat (Semiring.toNonAssocSemiring.{0} Nat Nat.semiring)) Nat.nontrivial) (OrderedAddCommMonoid.to_covariantClass_left.{0} Nat (OrderedSemiring.toOrderedAddCommMonoid.{0} Nat Nat.orderedSemiring)))))))))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] (f : (Fin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2))) -> α), Iff (Finset.SupIndep.{u1, 0} α (Fin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2))) _inst_1 _inst_2 (Finset.univ.{0} (Fin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2))) (Fin.fintype (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2)))) f) (Disjoint.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1)) _inst_2 (f (OfNat.ofNat.{0} (Fin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2))) 0 (Fin.instOfNatFin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2)) 0 (NeZero.succ (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))))) (f (OfNat.ofNat.{0} (Fin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2))) 1 (Fin.instOfNatFin (OfNat.ofNat.{0} Nat 2 (instOfNatNat 2)) 1 (NeZero.succ (OfNat.ofNat.{0} Nat 1 (instOfNatNat 1)))))))
Case conversion may be inaccurate. Consider using '#align finset.sup_indep_univ_fin_two Finset.supIndep_univ_fin_twoₓ'. -/
@[simp]
theorem supIndep_univ_fin_two (f : Fin 2 → α) :
    (Finset.univ : Finset (Fin 2)).SupIndep f ↔ Disjoint (f 0) (f 1) :=
  haveI : (0 : Fin 2) ≠ 1 := by simp
  sup_indep_pair this
#align finset.sup_indep_univ_fin_two Finset.supIndep_univ_fin_two

/- warning: finset.sup_indep.attach -> Finset.SupIndep.attach is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] {s : Finset.{u2} ι} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 s f) -> (Finset.SupIndep.{u1, u2} α (Subtype.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s)) _inst_1 _inst_2 (Finset.attach.{u2} ι s) (Function.comp.{succ u2, succ u2, succ u1} (Subtype.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s)) ι α f (Subtype.val.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s))))
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] {s : Finset.{u1} ι} {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 s f) -> (Finset.SupIndep.{u2, u1} α (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) _inst_1 _inst_2 (Finset.attach.{u1} ι s) (Function.comp.{succ u1, succ u1, succ u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) ι α f (Subtype.val.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s))))
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.attach Finset.SupIndep.attachₓ'. -/
theorem SupIndep.attach (hs : s.SupIndep f) : s.attach.SupIndep (f ∘ Subtype.val) :=
  by
  intro t ht i _ hi
  classical
    rw [← Finset.sup_image]
    refine' hs (image_subset_iff.2 fun (j : { x // x ∈ s }) _ => j.2) i.2 fun hi' => hi _
    rw [mem_image] at hi'
    obtain ⟨j, hj, hji⟩ := hi'
    rwa [Subtype.ext hji] at hj
#align finset.sup_indep.attach Finset.SupIndep.attach

end Lattice

section DistribLattice

variable [DistribLattice α] [OrderBot α] {s : Finset ι} {f : ι → α}

/- warning: finset.sup_indep_iff_pairwise_disjoint -> Finset.supIndep_iff_pairwiseDisjoint is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] {s : Finset.{u2} ι} {f : ι -> α}, Iff (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s f) (Set.PairwiseDisjoint.{u1, u2} α ι (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1))) _inst_2 ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} ι) (Set.{u2} ι) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (Finset.Set.hasCoeT.{u2} ι))) s) f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : DistribLattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (DistribLattice.toLattice.{u2} α _inst_1)))))] {s : Finset.{u1} ι} {f : ι -> α}, Iff (Finset.SupIndep.{u2, u1} α ι (DistribLattice.toLattice.{u2} α _inst_1) _inst_2 s f) (Set.PairwiseDisjoint.{u2, u1} α ι (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (DistribLattice.toLattice.{u2} α _inst_1))) _inst_2 (Finset.toSet.{u1} ι s) f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep_iff_pairwise_disjoint Finset.supIndep_iff_pairwiseDisjointₓ'. -/
theorem supIndep_iff_pairwiseDisjoint : s.SupIndep f ↔ (s : Set ι).PairwiseDisjoint f :=
  ⟨SupIndep.pairwiseDisjoint, fun hs t ht i hi hit =>
    Finset.disjoint_sup_right.2 fun j hj => hs hi (ht hj) (ne_of_mem_of_not_mem hj hit).symm⟩
#align finset.sup_indep_iff_pairwise_disjoint Finset.supIndep_iff_pairwiseDisjoint

/- warning: finset.sup_indep.pairwise_disjoint -> Finset.SupIndep.pairwiseDisjoint is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : Lattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1))))] {s : Finset.{u2} ι} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι _inst_1 _inst_2 s f) -> (Set.PairwiseDisjoint.{u1, u2} α ι (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α _inst_1)) _inst_2 ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} ι) (Set.{u2} ι) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (Finset.Set.hasCoeT.{u2} ι))) s) f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : Lattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1))))] {s : Finset.{u1} ι} {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι _inst_1 _inst_2 s f) -> (Set.PairwiseDisjoint.{u2, u1} α ι (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α _inst_1)) _inst_2 (Finset.toSet.{u1} ι s) f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.pairwise_disjoint Finset.SupIndep.pairwiseDisjointₓ'. -/
/- warning: set.pairwise_disjoint.sup_indep -> Set.PairwiseDisjoint.supIndep is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] {s : Finset.{u2} ι} {f : ι -> α}, (Set.PairwiseDisjoint.{u1, u2} α ι (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1))) _inst_2 ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (Finset.{u2} ι) (Set.{u2} ι) (HasLiftT.mk.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (CoeTCₓ.coe.{succ u2, succ u2} (Finset.{u2} ι) (Set.{u2} ι) (Finset.Set.hasCoeT.{u2} ι))) s) f) -> (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : DistribLattice.{u2} α] [_inst_2 : OrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (DistribLattice.toLattice.{u2} α _inst_1)))))] {s : Finset.{u1} ι} {f : ι -> α}, (Set.PairwiseDisjoint.{u2, u1} α ι (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (DistribLattice.toLattice.{u2} α _inst_1))) _inst_2 (Finset.toSet.{u1} ι s) f) -> (Finset.SupIndep.{u2, u1} α ι (DistribLattice.toLattice.{u2} α _inst_1) _inst_2 s f)
Case conversion may be inaccurate. Consider using '#align set.pairwise_disjoint.sup_indep Set.PairwiseDisjoint.supIndepₓ'. -/
alias sup_indep_iff_pairwise_disjoint ↔
  sup_indep.pairwise_disjoint _root_.set.pairwise_disjoint.sup_indep
#align finset.sup_indep.pairwise_disjoint Finset.SupIndep.pairwiseDisjoint
#align set.pairwise_disjoint.sup_indep Set.PairwiseDisjoint.supIndep

/- warning: finset.sup_indep.sup -> Finset.SupIndep.sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} {ι' : Type.{u3}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] [_inst_3 : DecidableEq.{succ u2} ι] {s : Finset.{u3} ι'} {g : ι' -> (Finset.{u2} ι)} {f : ι -> α}, (Finset.SupIndep.{u1, u3} α ι' (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s (fun (i : ι') => Finset.sup.{u1, u2} α ι (Lattice.toSemilatticeSup.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)) _inst_2 (g i) f)) -> (forall (i' : ι'), (Membership.Mem.{u3, u3} ι' (Finset.{u3} ι') (Finset.hasMem.{u3} ι') i' s) -> (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (g i') f)) -> (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (Finset.sup.{u2, u3} (Finset.{u2} ι) ι' (Lattice.toSemilatticeSup.{u2} (Finset.{u2} ι) (Finset.lattice.{u2} ι (fun (a : ι) (b : ι) => _inst_3 a b))) (Finset.orderBot.{u2} ι) s g) f)
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u3}} {ι' : Type.{u2}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] [_inst_3 : DecidableEq.{succ u3} ι] {s : Finset.{u2} ι'} {g : ι' -> (Finset.{u3} ι)} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι' (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s (fun (i : ι') => Finset.sup.{u1, u3} α ι (Lattice.toSemilatticeSup.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)) _inst_2 (g i) f)) -> (forall (i' : ι'), (Membership.mem.{u2, u2} ι' (Finset.{u2} ι') (Finset.instMembershipFinset.{u2} ι') i' s) -> (Finset.SupIndep.{u1, u3} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (g i') f)) -> (Finset.SupIndep.{u1, u3} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (Finset.sup.{u3, u2} (Finset.{u3} ι) ι' (Lattice.toSemilatticeSup.{u3} (Finset.{u3} ι) (Finset.instLatticeFinset.{u3} ι (fun (a : ι) (b : ι) => _inst_3 a b))) (Finset.instOrderBotFinsetToLEToPreorderPartialOrder.{u3} ι) s g) f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.sup Finset.SupIndep.supₓ'. -/
/-- Bind operation for `sup_indep`. -/
theorem SupIndep.sup [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α}
    (hs : s.SupIndep fun i => (g i).sup f) (hg : ∀ i' ∈ s, (g i').SupIndep f) :
    (s.sup g).SupIndep f :=
  by
  simp_rw [sup_indep_iff_pairwise_disjoint] at hs hg⊢
  rw [sup_eq_bUnion, coe_bUnion]
  exact hs.bUnion_finset hg
#align finset.sup_indep.sup Finset.SupIndep.sup

/- warning: finset.sup_indep.bUnion -> Finset.SupIndep.bunionᵢ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} {ι' : Type.{u3}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] [_inst_3 : DecidableEq.{succ u2} ι] {s : Finset.{u3} ι'} {g : ι' -> (Finset.{u2} ι)} {f : ι -> α}, (Finset.SupIndep.{u1, u3} α ι' (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s (fun (i : ι') => Finset.sup.{u1, u2} α ι (Lattice.toSemilatticeSup.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)) _inst_2 (g i) f)) -> (forall (i' : ι'), (Membership.Mem.{u3, u3} ι' (Finset.{u3} ι') (Finset.hasMem.{u3} ι') i' s) -> (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (g i') f)) -> (Finset.SupIndep.{u1, u2} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (Finset.bunionᵢ.{u3, u2} ι' ι (fun (a : ι) (b : ι) => _inst_3 a b) s g) f)
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u3}} {ι' : Type.{u2}} [_inst_1 : DistribLattice.{u1} α] [_inst_2 : OrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)))))] [_inst_3 : DecidableEq.{succ u3} ι] {s : Finset.{u2} ι'} {g : ι' -> (Finset.{u3} ι)} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι' (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 s (fun (i : ι') => Finset.sup.{u1, u3} α ι (Lattice.toSemilatticeSup.{u1} α (DistribLattice.toLattice.{u1} α _inst_1)) _inst_2 (g i) f)) -> (forall (i' : ι'), (Membership.mem.{u2, u2} ι' (Finset.{u2} ι') (Finset.instMembershipFinset.{u2} ι') i' s) -> (Finset.SupIndep.{u1, u3} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (g i') f)) -> (Finset.SupIndep.{u1, u3} α ι (DistribLattice.toLattice.{u1} α _inst_1) _inst_2 (Finset.bunionᵢ.{u2, u3} ι' ι (fun (a : ι) (b : ι) => _inst_3 a b) s g) f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.bUnion Finset.SupIndep.bunionᵢₓ'. -/
/-- Bind operation for `sup_indep`. -/
theorem SupIndep.bunionᵢ [DecidableEq ι] {s : Finset ι'} {g : ι' → Finset ι} {f : ι → α}
    (hs : s.SupIndep fun i => (g i).sup f) (hg : ∀ i' ∈ s, (g i').SupIndep f) :
    (s.bunionᵢ g).SupIndep f := by
  rw [← sup_eq_bUnion]
  exact hs.sup hg
#align finset.sup_indep.bUnion Finset.SupIndep.bunionᵢ

end DistribLattice

end Finset

/-! ### On complete lattices via `has_Sup.Sup` -/

namespace CompleteLattice

variable [CompleteLattice α]

open Set Function

#print CompleteLattice.SetIndependent /-
/-- An independent set of elements in a complete lattice is one in which every element is disjoint
  from the `Sup` of the rest. -/
def SetIndependent (s : Set α) : Prop :=
  ∀ ⦃a⦄, a ∈ s → Disjoint a (supₛ (s \ {a}))
#align complete_lattice.set_independent CompleteLattice.SetIndependent
-/

variable {s : Set α} (hs : SetIndependent s)

#print CompleteLattice.setIndependent_empty /-
@[simp]
theorem setIndependent_empty : SetIndependent (∅ : Set α) := fun x hx =>
  (Set.not_mem_empty x hx).elim
#align complete_lattice.set_independent_empty CompleteLattice.setIndependent_empty
-/

#print CompleteLattice.SetIndependent.mono /-
theorem SetIndependent.mono {t : Set α} (hst : t ⊆ s) : SetIndependent t := fun a ha =>
  (hs (hst ha)).mono_right (supₛ_le_supₛ (diff_subset_diff_left hst))
#align complete_lattice.set_independent.mono CompleteLattice.SetIndependent.mono
-/

#print CompleteLattice.SetIndependent.pairwiseDisjoint /-
/-- If the elements of a set are independent, then any pair within that set is disjoint. -/
theorem SetIndependent.pairwiseDisjoint : s.PairwiseDisjoint id := fun x hx y hy h =>
  disjoint_supₛ_right (hs hx) ((mem_diff y).mpr ⟨hy, h.symm⟩)
#align complete_lattice.set_independent.pairwise_disjoint CompleteLattice.SetIndependent.pairwiseDisjoint
-/

#print CompleteLattice.setIndependent_pair /-
theorem setIndependent_pair {a b : α} (hab : a ≠ b) :
    SetIndependent ({a, b} : Set α) ↔ Disjoint a b :=
  by
  constructor
  · intro h
    exact h.pairwise_disjoint (mem_insert _ _) (mem_insert_of_mem _ (mem_singleton _)) hab
  · rintro h c ((rfl : c = a) | (rfl : c = b))
    · convert h using 1
      simp [hab, supₛ_singleton]
    · convert h.symm using 1
      simp [hab, supₛ_singleton]
#align complete_lattice.set_independent_pair CompleteLattice.setIndependent_pair
-/

include hs

/- warning: complete_lattice.set_independent.disjoint_Sup -> CompleteLattice.SetIndependent.disjoint_supₛ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {s : Set.{u1} α}, (CompleteLattice.SetIndependent.{u1} α _inst_1 s) -> (forall {x : α} {y : Set.{u1} α}, (Membership.Mem.{u1, u1} α (Set.{u1} α) (Set.hasMem.{u1} α) x s) -> (HasSubset.Subset.{u1} (Set.{u1} α) (Set.hasSubset.{u1} α) y s) -> (Not (Membership.Mem.{u1, u1} α (Set.{u1} α) (Set.hasMem.{u1} α) x y)) -> (Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) x (SupSet.supₛ.{u1} α (CompleteSemilatticeSup.toHasSup.{u1} α (CompleteLattice.toCompleteSemilatticeSup.{u1} α _inst_1)) y)))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {s : Set.{u1} α}, (CompleteLattice.SetIndependent.{u1} α _inst_1 s) -> (forall {x : α} {y : Set.{u1} α}, (Membership.mem.{u1, u1} α (Set.{u1} α) (Set.instMembershipSet.{u1} α) x s) -> (HasSubset.Subset.{u1} (Set.{u1} α) (Set.instHasSubsetSet.{u1} α) y s) -> (Not (Membership.mem.{u1, u1} α (Set.{u1} α) (Set.instMembershipSet.{u1} α) x y)) -> (Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) x (SupSet.supₛ.{u1} α (CompleteLattice.toSupSet.{u1} α _inst_1) y)))
Case conversion may be inaccurate. Consider using '#align complete_lattice.set_independent.disjoint_Sup CompleteLattice.SetIndependent.disjoint_supₛₓ'. -/
/-- If the elements of a set are independent, then any element is disjoint from the `Sup` of some
subset of the rest. -/
theorem SetIndependent.disjoint_supₛ {x : α} {y : Set α} (hx : x ∈ s) (hy : y ⊆ s) (hxy : x ∉ y) :
    Disjoint x (supₛ y) :=
  by
  have := (hs.mono <| insert_subset.mpr ⟨hx, hy⟩) (mem_insert x _)
  rw [insert_diff_of_mem _ (mem_singleton _), diff_singleton_eq_self hxy] at this
  exact this
#align complete_lattice.set_independent.disjoint_Sup CompleteLattice.SetIndependent.disjoint_supₛ

omit hs

/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (j «expr ≠ » i) -/
#print CompleteLattice.Independent /-
/-- An independent indexed family of elements in a complete lattice is one in which every element
  is disjoint from the `supr` of the rest.

  Example: an indexed family of non-zero elements in a
  vector space is linearly independent iff the indexed family of subspaces they generate is
  independent in this sense.

  Example: an indexed family of submodules of a module is independent in this sense if
  and only the natural map from the direct sum of the submodules to the module is injective. -/
def Independent {ι : Sort _} {α : Type _} [CompleteLattice α] (t : ι → α) : Prop :=
  ∀ i : ι, Disjoint (t i) (⨆ (j) (_ : j ≠ i), t j)
#align complete_lattice.independent CompleteLattice.Independent
-/

#print CompleteLattice.setIndependent_iff /-
theorem setIndependent_iff {α : Type _} [CompleteLattice α] (s : Set α) :
    SetIndependent s ↔ Independent (coe : s → α) :=
  by
  simp_rw [independent, set_independent, SetCoe.forall, supₛ_eq_supᵢ]
  refine' forall₂_congr fun a ha => _
  congr 2
  convert supr_subtype.symm
  simp [supᵢ_and]
#align complete_lattice.set_independent_iff CompleteLattice.setIndependent_iff
-/

variable {t : ι → α} (ht : Independent t)

/- warning: complete_lattice.independent_def -> CompleteLattice.independent_def is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (supᵢ.{u1, succ u2} α (CompleteSemilatticeSup.toHasSup.{u1} α (CompleteLattice.toCompleteSemilatticeSup.{u1} α _inst_1)) ι (fun (j : ι) => supᵢ.{u1, 0} α (CompleteSemilatticeSup.toHasSup.{u1} α (CompleteLattice.toCompleteSemilatticeSup.{u1} α _inst_1)) (Ne.{succ u2} ι j i) (fun (H : Ne.{succ u2} ι j i) => t j))))
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (supᵢ.{u1, succ u2} α (CompleteLattice.toSupSet.{u1} α _inst_1) ι (fun (j : ι) => supᵢ.{u1, 0} α (CompleteLattice.toSupSet.{u1} α _inst_1) (Ne.{succ u2} ι j i) (fun (H : Ne.{succ u2} ι j i) => t j))))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_def CompleteLattice.independent_defₓ'. -/
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (j «expr ≠ » i) -/
theorem independent_def : Independent t ↔ ∀ i : ι, Disjoint (t i) (⨆ (j) (_ : j ≠ i), t j) :=
  Iff.rfl
#align complete_lattice.independent_def CompleteLattice.independent_def

/- warning: complete_lattice.independent_def' -> CompleteLattice.independent_def' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (SupSet.supₛ.{u1} α (CompleteSemilatticeSup.toHasSup.{u1} α (CompleteLattice.toCompleteSemilatticeSup.{u1} α _inst_1)) (Set.image.{u2, u1} ι α t (setOf.{u2} ι (fun (j : ι) => Ne.{succ u2} ι j i)))))
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (SupSet.supₛ.{u1} α (CompleteLattice.toSupSet.{u1} α _inst_1) (Set.image.{u2, u1} ι α t (setOf.{u2} ι (fun (j : ι) => Ne.{succ u2} ι j i)))))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_def' CompleteLattice.independent_def'ₓ'. -/
theorem independent_def' : Independent t ↔ ∀ i, Disjoint (t i) (supₛ (t '' { j | j ≠ i })) :=
  by
  simp_rw [supₛ_image]
  rfl
#align complete_lattice.independent_def' CompleteLattice.independent_def'

/- warning: complete_lattice.independent_def'' -> CompleteLattice.independent_def'' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (SupSet.supₛ.{u1} α (CompleteSemilatticeSup.toHasSup.{u1} α (CompleteLattice.toCompleteSemilatticeSup.{u1} α _inst_1)) (setOf.{u1} α (fun (a : α) => Exists.{succ u2} ι (fun (j : ι) => Exists.{0} (Ne.{succ u2} ι j i) (fun (H : Ne.{succ u2} ι j i) => Eq.{succ u1} α (t j) a))))))
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) (forall (i : ι), Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (t i) (SupSet.supₛ.{u1} α (CompleteLattice.toSupSet.{u1} α _inst_1) (setOf.{u1} α (fun (a : α) => Exists.{succ u2} ι (fun (j : ι) => Exists.{0} (Ne.{succ u2} ι j i) (fun (H : Ne.{succ u2} ι j i) => Eq.{succ u1} α (t j) a))))))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_def'' CompleteLattice.independent_def''ₓ'. -/
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (j «expr ≠ » i) -/
theorem independent_def'' :
    Independent t ↔ ∀ i, Disjoint (t i) (supₛ { a | ∃ (j : _)(_ : j ≠ i), t j = a }) :=
  by
  rw [independent_def']
  tidy
#align complete_lattice.independent_def'' CompleteLattice.independent_def''

#print CompleteLattice.independent_empty /-
@[simp]
theorem independent_empty (t : Empty → α) : Independent t :=
  fun.
#align complete_lattice.independent_empty CompleteLattice.independent_empty
-/

#print CompleteLattice.independent_pempty /-
@[simp]
theorem independent_pempty (t : PEmpty → α) : Independent t :=
  fun.
#align complete_lattice.independent_pempty CompleteLattice.independent_pempty
-/

#print CompleteLattice.Independent.pairwiseDisjoint /-
/-- If the elements of a set are independent, then any pair within that set is disjoint. -/
theorem Independent.pairwiseDisjoint : Pairwise (Disjoint on t) := fun x y h =>
  disjoint_supₛ_right (ht x) ⟨y, supᵢ_pos h.symm⟩
#align complete_lattice.independent.pairwise_disjoint CompleteLattice.Independent.pairwiseDisjoint
-/

#print CompleteLattice.Independent.mono /-
theorem Independent.mono {s t : ι → α} (hs : Independent s) (hst : t ≤ s) : Independent t :=
  fun i => (hs i).mono (hst i) <| supᵢ₂_mono fun j _ => hst j
#align complete_lattice.independent.mono CompleteLattice.Independent.mono
-/

/- warning: complete_lattice.independent.comp -> CompleteLattice.Independent.comp is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {ι : Sort.{u2}} {ι' : Sort.{u3}} {t : ι -> α} {f : ι' -> ι}, (CompleteLattice.Independent.{u2, u1} ι α _inst_1 t) -> (Function.Injective.{u3, u2} ι' ι f) -> (CompleteLattice.Independent.{u3, u1} ι' α _inst_1 (Function.comp.{u3, u2, succ u1} ι' ι α t f))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {ι : Sort.{u3}} {ι' : Sort.{u2}} {t : ι -> α} {f : ι' -> ι}, (CompleteLattice.Independent.{u3, u1} ι α _inst_1 t) -> (Function.Injective.{u2, u3} ι' ι f) -> (CompleteLattice.Independent.{u2, u1} ι' α _inst_1 (Function.comp.{u2, u3, succ u1} ι' ι α t f))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.comp CompleteLattice.Independent.compₓ'. -/
/-- Composing an independent indexed family with an injective function on the index results in
another indepedendent indexed family. -/
theorem Independent.comp {ι ι' : Sort _} {t : ι → α} {f : ι' → ι} (ht : Independent t)
    (hf : Injective f) : Independent (t ∘ f) := fun i =>
  (ht (f i)).mono_right <|
    by
    refine' (supᵢ_mono fun i => _).trans (supᵢ_comp_le _ f)
    exact supᵢ_const_mono hf.ne
#align complete_lattice.independent.comp CompleteLattice.Independent.comp

/- warning: complete_lattice.independent.comp' -> CompleteLattice.Independent.comp' is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {ι : Sort.{u2}} {ι' : Sort.{u3}} {t : ι -> α} {f : ι' -> ι}, (CompleteLattice.Independent.{u3, u1} ι' α _inst_1 (Function.comp.{u3, u2, succ u1} ι' ι α t f)) -> (Function.Surjective.{u3, u2} ι' ι f) -> (CompleteLattice.Independent.{u2, u1} ι α _inst_1 t)
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : CompleteLattice.{u1} α] {ι : Sort.{u3}} {ι' : Sort.{u2}} {t : ι -> α} {f : ι' -> ι}, (CompleteLattice.Independent.{u2, u1} ι' α _inst_1 (Function.comp.{u2, u3, succ u1} ι' ι α t f)) -> (Function.Surjective.{u2, u3} ι' ι f) -> (CompleteLattice.Independent.{u3, u1} ι α _inst_1 t)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.comp' CompleteLattice.Independent.comp'ₓ'. -/
theorem Independent.comp' {ι ι' : Sort _} {t : ι → α} {f : ι' → ι} (ht : Independent <| t ∘ f)
    (hf : Surjective f) : Independent t := by
  intro i
  obtain ⟨i', rfl⟩ := hf i
  rw [← hf.supr_comp]
  exact (ht i').mono_right (bsupᵢ_mono fun j' hij => mt (congr_arg f) hij)
#align complete_lattice.independent.comp' CompleteLattice.Independent.comp'

#print CompleteLattice.Independent.setIndependent_range /-
theorem Independent.setIndependent_range (ht : Independent t) : SetIndependent <| range t :=
  by
  rw [set_independent_iff]
  rw [← coe_comp_range_factorization t] at ht
  exact ht.comp' surjective_onto_range
#align complete_lattice.independent.set_independent_range CompleteLattice.Independent.setIndependent_range
-/

/- warning: complete_lattice.independent.injective -> CompleteLattice.Independent.injective is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) -> (forall (i : ι), Ne.{succ u1} α (t i) (Bot.bot.{u1} α (CompleteLattice.toHasBot.{u1} α _inst_1))) -> (Function.Injective.{succ u2, succ u1} ι α t)
but is expected to have type
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {t : ι -> α}, (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 t) -> (forall (i : ι), Ne.{succ u1} α (t i) (Bot.bot.{u1} α (CompleteLattice.toBot.{u1} α _inst_1))) -> (Function.Injective.{succ u2, succ u1} ι α t)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.injective CompleteLattice.Independent.injectiveₓ'. -/
theorem Independent.injective (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Injective t :=
  by
  intro i j h
  by_contra' contra
  apply h_ne_bot j
  suffices t j ≤ ⨆ (k) (hk : k ≠ i), t k
    by
    replace ht := (ht i).mono_right this
    rwa [h, disjoint_self] at ht
  replace contra : j ≠ i
  · exact Ne.symm contra
  exact le_supᵢ₂ j contra
#align complete_lattice.independent.injective CompleteLattice.Independent.injective

#print CompleteLattice.independent_pair /-
theorem independent_pair {i j : ι} (hij : i ≠ j) (huniv : ∀ k, k = i ∨ k = j) :
    Independent t ↔ Disjoint (t i) (t j) := by
  constructor
  · exact fun h => h.PairwiseDisjoint hij
  · rintro h k
    obtain rfl | rfl := huniv k
    · refine' h.mono_right (supᵢ_le fun i => supᵢ_le fun hi => Eq.le _)
      rw [(huniv i).resolve_left hi]
    · refine' h.symm.mono_right (supᵢ_le fun j => supᵢ_le fun hj => Eq.le _)
      rw [(huniv j).resolve_right hj]
#align complete_lattice.independent_pair CompleteLattice.independent_pair
-/

/- warning: complete_lattice.independent.map_order_iso -> CompleteLattice.Independent.map_orderIso is a dubious translation:
lean 3 declaration is
  forall {ι : Sort.{u1}} {α : Type.{u2}} {β : Type.{u3}} [_inst_2 : CompleteLattice.{u2} α] [_inst_3 : CompleteLattice.{u3} β] (f : OrderIso.{u2, u3} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3))))) {a : ι -> α}, (CompleteLattice.Independent.{u1, u2} ι α _inst_2 a) -> (CompleteLattice.Independent.{u1, u3} ι β _inst_3 (Function.comp.{u1, succ u2, succ u3} ι α β (coeFn.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (OrderIso.{u2, u3} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3))))) (fun (_x : RelIso.{u2, u3} α β (LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2))))) (LE.le.{u3} β (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3)))))) => α -> β) (RelIso.hasCoeToFun.{u2, u3} α β (LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2))))) (LE.le.{u3} β (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3)))))) f) a))
but is expected to have type
  forall {ι : Sort.{u3}} {α : Type.{u2}} {β : Type.{u1}} [_inst_2 : CompleteLattice.{u2} α] [_inst_3 : CompleteLattice.{u1} β] (f : OrderIso.{u2, u1} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3))))) {a : ι -> α}, (CompleteLattice.Independent.{u3, u2} ι α _inst_2 a) -> (CompleteLattice.Independent.{u3, u1} ι β _inst_3 (Function.comp.{u3, succ u2, succ u1} ι α β (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} α β) α (fun (_x : α) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : α) => β) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} α β) α β (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} α β)) (RelEmbedding.toEmbedding.{u2, u1} α β (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1281 : α) (x._@.Mathlib.Order.Hom.Basic._hyg.1283 : α) => LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) x._@.Mathlib.Order.Hom.Basic._hyg.1281 x._@.Mathlib.Order.Hom.Basic._hyg.1283) (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1296 : β) (x._@.Mathlib.Order.Hom.Basic._hyg.1298 : β) => LE.le.{u1} β (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3)))) x._@.Mathlib.Order.Hom.Basic._hyg.1296 x._@.Mathlib.Order.Hom.Basic._hyg.1298) (RelIso.toRelEmbedding.{u2, u1} α β (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1281 : α) (x._@.Mathlib.Order.Hom.Basic._hyg.1283 : α) => LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) x._@.Mathlib.Order.Hom.Basic._hyg.1281 x._@.Mathlib.Order.Hom.Basic._hyg.1283) (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1296 : β) (x._@.Mathlib.Order.Hom.Basic._hyg.1298 : β) => LE.le.{u1} β (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3)))) x._@.Mathlib.Order.Hom.Basic._hyg.1296 x._@.Mathlib.Order.Hom.Basic._hyg.1298) f))) a))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.map_order_iso CompleteLattice.Independent.map_orderIsoₓ'. -/
/-- Composing an indepedent indexed family with an order isomorphism on the elements results in
another indepedendent indexed family. -/
theorem Independent.map_orderIso {ι : Sort _} {α β : Type _} [CompleteLattice α] [CompleteLattice β]
    (f : α ≃o β) {a : ι → α} (ha : Independent a) : Independent (f ∘ a) := fun i =>
  ((ha i).map_orderIso f).mono_right (f.Monotone.le_map_supᵢ₂ _)
#align complete_lattice.independent.map_order_iso CompleteLattice.Independent.map_orderIso

/- warning: complete_lattice.independent_map_order_iso_iff -> CompleteLattice.independent_map_orderIso_iff is a dubious translation:
lean 3 declaration is
  forall {ι : Sort.{u1}} {α : Type.{u2}} {β : Type.{u3}} [_inst_2 : CompleteLattice.{u2} α] [_inst_3 : CompleteLattice.{u3} β] (f : OrderIso.{u2, u3} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3))))) {a : ι -> α}, Iff (CompleteLattice.Independent.{u1, u3} ι β _inst_3 (Function.comp.{u1, succ u2, succ u3} ι α β (coeFn.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (OrderIso.{u2, u3} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3))))) (fun (_x : RelIso.{u2, u3} α β (LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2))))) (LE.le.{u3} β (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3)))))) => α -> β) (RelIso.hasCoeToFun.{u2, u3} α β (LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2))))) (LE.le.{u3} β (Preorder.toLE.{u3} β (PartialOrder.toPreorder.{u3} β (CompleteSemilatticeInf.toPartialOrder.{u3} β (CompleteLattice.toCompleteSemilatticeInf.{u3} β _inst_3)))))) f) a)) (CompleteLattice.Independent.{u1, u2} ι α _inst_2 a)
but is expected to have type
  forall {ι : Sort.{u3}} {α : Type.{u2}} {β : Type.{u1}} [_inst_2 : CompleteLattice.{u2} α] [_inst_3 : CompleteLattice.{u1} β] (f : OrderIso.{u2, u1} α β (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3))))) {a : ι -> α}, Iff (CompleteLattice.Independent.{u3, u1} ι β _inst_3 (Function.comp.{u3, succ u2, succ u1} ι α β (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} α β) α (fun (_x : α) => (fun (x._@.Mathlib.Data.FunLike.Embedding._hyg.19 : α) => β) _x) (EmbeddingLike.toFunLike.{max (succ u2) (succ u1), succ u2, succ u1} (Function.Embedding.{succ u2, succ u1} α β) α β (Function.instEmbeddingLikeEmbedding.{succ u2, succ u1} α β)) (RelEmbedding.toEmbedding.{u2, u1} α β (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1281 : α) (x._@.Mathlib.Order.Hom.Basic._hyg.1283 : α) => LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) x._@.Mathlib.Order.Hom.Basic._hyg.1281 x._@.Mathlib.Order.Hom.Basic._hyg.1283) (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1296 : β) (x._@.Mathlib.Order.Hom.Basic._hyg.1298 : β) => LE.le.{u1} β (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3)))) x._@.Mathlib.Order.Hom.Basic._hyg.1296 x._@.Mathlib.Order.Hom.Basic._hyg.1298) (RelIso.toRelEmbedding.{u2, u1} α β (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1281 : α) (x._@.Mathlib.Order.Hom.Basic._hyg.1283 : α) => LE.le.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) x._@.Mathlib.Order.Hom.Basic._hyg.1281 x._@.Mathlib.Order.Hom.Basic._hyg.1283) (fun (x._@.Mathlib.Order.Hom.Basic._hyg.1296 : β) (x._@.Mathlib.Order.Hom.Basic._hyg.1298 : β) => LE.le.{u1} β (Preorder.toLE.{u1} β (PartialOrder.toPreorder.{u1} β (CompleteSemilatticeInf.toPartialOrder.{u1} β (CompleteLattice.toCompleteSemilatticeInf.{u1} β _inst_3)))) x._@.Mathlib.Order.Hom.Basic._hyg.1296 x._@.Mathlib.Order.Hom.Basic._hyg.1298) f))) a)) (CompleteLattice.Independent.{u3, u2} ι α _inst_2 a)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_map_order_iso_iff CompleteLattice.independent_map_orderIso_iffₓ'. -/
@[simp]
theorem independent_map_orderIso_iff {ι : Sort _} {α β : Type _} [CompleteLattice α]
    [CompleteLattice β] (f : α ≃o β) {a : ι → α} : Independent (f ∘ a) ↔ Independent a :=
  ⟨fun h =>
    have hf : f.symm ∘ f ∘ a = a := congr_arg (· ∘ a) f.left_inv.comp_eq_id
    hf ▸ h.map_orderIso f.symm,
    fun h => h.map_orderIso f⟩
#align complete_lattice.independent_map_order_iso_iff CompleteLattice.independent_map_orderIso_iff

/- warning: complete_lattice.independent.disjoint_bsupr -> CompleteLattice.Independent.disjoint_bsupᵢ is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : Type.{u2}} [_inst_2 : CompleteLattice.{u2} α] {t : ι -> α}, (CompleteLattice.Independent.{succ u1, u2} ι α _inst_2 t) -> (forall {x : ι} {y : Set.{u1} ι}, (Not (Membership.Mem.{u1, u1} ι (Set.{u1} ι) (Set.hasMem.{u1} ι) x y)) -> (Disjoint.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (CompleteSemilatticeInf.toPartialOrder.{u2} α (CompleteLattice.toCompleteSemilatticeInf.{u2} α _inst_2)))) (CompleteLattice.toBoundedOrder.{u2} α _inst_2)) (t x) (supᵢ.{u2, succ u1} α (CompleteSemilatticeSup.toHasSup.{u2} α (CompleteLattice.toCompleteSemilatticeSup.{u2} α _inst_2)) ι (fun (i : ι) => supᵢ.{u2, 0} α (CompleteSemilatticeSup.toHasSup.{u2} α (CompleteLattice.toCompleteSemilatticeSup.{u2} α _inst_2)) (Membership.Mem.{u1, u1} ι (Set.{u1} ι) (Set.hasMem.{u1} ι) i y) (fun (H : Membership.Mem.{u1, u1} ι (Set.{u1} ι) (Set.hasMem.{u1} ι) i y) => t i)))))
but is expected to have type
  forall {ι : Type.{u2}} {α : Type.{u1}} [_inst_2 : CompleteLattice.{u1} α] {t : ι -> α}, (CompleteLattice.Independent.{succ u2, u1} ι α _inst_2 t) -> (forall {x : ι} {y : Set.{u2} ι}, (Not (Membership.mem.{u2, u2} ι (Set.{u2} ι) (Set.instMembershipSet.{u2} ι) x y)) -> (Disjoint.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_2)) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (CompleteSemilatticeInf.toPartialOrder.{u1} α (CompleteLattice.toCompleteSemilatticeInf.{u1} α _inst_2)))) (CompleteLattice.toBoundedOrder.{u1} α _inst_2)) (t x) (supᵢ.{u1, succ u2} α (CompleteLattice.toSupSet.{u1} α _inst_2) ι (fun (i : ι) => supᵢ.{u1, 0} α (CompleteLattice.toSupSet.{u1} α _inst_2) (Membership.mem.{u2, u2} ι (Set.{u2} ι) (Set.instMembershipSet.{u2} ι) i y) (fun (H : Membership.mem.{u2, u2} ι (Set.{u2} ι) (Set.instMembershipSet.{u2} ι) i y) => t i)))))
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.disjoint_bsupr CompleteLattice.Independent.disjoint_bsupᵢₓ'. -/
/-- If the elements of a set are independent, then any element is disjoint from the `supr` of some
subset of the rest. -/
theorem Independent.disjoint_bsupᵢ {ι : Type _} {α : Type _} [CompleteLattice α] {t : ι → α}
    (ht : Independent t) {x : ι} {y : Set ι} (hx : x ∉ y) : Disjoint (t x) (⨆ i ∈ y, t i) :=
  Disjoint.mono_right (bsupᵢ_mono fun i hi => (ne_of_mem_of_not_mem hi hx : _)) (ht x)
#align complete_lattice.independent.disjoint_bsupr CompleteLattice.Independent.disjoint_bsupᵢ

end CompleteLattice

/- warning: complete_lattice.independent_iff_sup_indep -> CompleteLattice.independent_iff_supIndep is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {s : Finset.{u2} ι} {f : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) α _inst_1 (Function.comp.{succ u2, succ u2, succ u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι α f ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (HasLiftT.mk.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (CoeTCₓ.coe.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeBase.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeSubtype.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s)))))))) (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) s f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] {s : Finset.{u1} ι} {f : ι -> α}, Iff (CompleteLattice.Independent.{succ u1, u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) α _inst_1 (Function.comp.{succ u1, succ u1, succ u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) ι α f (Subtype.val.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)))) (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) s f)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_iff_sup_indep CompleteLattice.independent_iff_supIndepₓ'. -/
theorem CompleteLattice.independent_iff_supIndep [CompleteLattice α] {s : Finset ι} {f : ι → α} :
    CompleteLattice.Independent (f ∘ (coe : s → ι)) ↔ s.SupIndep f := by
  classical
    rw [Finset.supIndep_iff_disjoint_erase]
    refine' subtype.forall.trans (forall₂_congr fun a b => _)
    rw [Finset.sup_eq_supᵢ]
    congr 2
    refine' supr_subtype.trans _
    congr 1 with x
    simp [supᵢ_and, @supᵢ_comm _ (x ∈ s)]
#align complete_lattice.independent_iff_sup_indep CompleteLattice.independent_iff_supIndep

/- warning: complete_lattice.independent.sup_indep -> CompleteLattice.Independent.supIndep is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {s : Finset.{u2} ι} {f : ι -> α}, (CompleteLattice.Independent.{succ u2, u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) α _inst_1 (Function.comp.{succ u2, succ u2, succ u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι α f ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (HasLiftT.mk.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (CoeTCₓ.coe.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeBase.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeSubtype.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s)))))))) -> (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) s f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] {s : Finset.{u1} ι} {f : ι -> α}, (CompleteLattice.Independent.{succ u1, u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) α _inst_1 (Function.comp.{succ u1, succ u1, succ u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) ι α f (Subtype.val.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)))) -> (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) s f)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.sup_indep CompleteLattice.Independent.supIndepₓ'. -/
/- warning: finset.sup_indep.independent -> Finset.SupIndep.independent is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] {s : Finset.{u2} ι} {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) s f) -> (CompleteLattice.Independent.{succ u2, u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) α _inst_1 (Function.comp.{succ u2, succ u2, succ u1} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι α f ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (HasLiftT.mk.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (CoeTCₓ.coe.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeBase.{succ u2, succ u2} (coeSort.{succ u2, succ (succ u2)} (Finset.{u2} ι) Type.{u2} (Finset.hasCoeToSort.{u2} ι) s) ι (coeSubtype.{succ u2} ι (fun (x : ι) => Membership.Mem.{u2, u2} ι (Finset.{u2} ι) (Finset.hasMem.{u2} ι) x s))))))))
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] {s : Finset.{u1} ι} {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) s f) -> (CompleteLattice.Independent.{succ u1, u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) α _inst_1 (Function.comp.{succ u1, succ u1, succ u2} (Subtype.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s)) ι α f (Subtype.val.{succ u1} ι (fun (x : ι) => Membership.mem.{u1, u1} ι (Finset.{u1} ι) (Finset.instMembershipFinset.{u1} ι) x s))))
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.independent Finset.SupIndep.independentₓ'. -/
alias CompleteLattice.independent_iff_supIndep ↔
  CompleteLattice.Independent.supIndep Finset.SupIndep.independent
#align complete_lattice.independent.sup_indep CompleteLattice.Independent.supIndep
#align finset.sup_indep.independent Finset.SupIndep.independent

/- warning: complete_lattice.independent_iff_sup_indep_univ -> CompleteLattice.independent_iff_supIndep_univ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] [_inst_2 : Fintype.{u2} ι] {f : ι -> α}, Iff (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 f) (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (Finset.univ.{u2} ι _inst_2) f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] [_inst_2 : Fintype.{u1} ι] {f : ι -> α}, Iff (CompleteLattice.Independent.{succ u1, u2} ι α _inst_1 f) (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) (Finset.univ.{u1} ι _inst_2) f)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent_iff_sup_indep_univ CompleteLattice.independent_iff_supIndep_univₓ'. -/
/-- A variant of `complete_lattice.independent_iff_sup_indep` for `fintype`s. -/
theorem CompleteLattice.independent_iff_supIndep_univ [CompleteLattice α] [Fintype ι] {f : ι → α} :
    CompleteLattice.Independent f ↔ Finset.univ.SupIndep f := by
  classical simp [Finset.supIndep_iff_disjoint_erase, CompleteLattice.Independent,
      Finset.sup_eq_supᵢ]
#align complete_lattice.independent_iff_sup_indep_univ CompleteLattice.independent_iff_supIndep_univ

/- warning: complete_lattice.independent.sup_indep_univ -> CompleteLattice.Independent.sup_indep_univ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] [_inst_2 : Fintype.{u2} ι] {f : ι -> α}, (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 f) -> (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (Finset.univ.{u2} ι _inst_2) f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] [_inst_2 : Fintype.{u1} ι] {f : ι -> α}, (CompleteLattice.Independent.{succ u1, u2} ι α _inst_1 f) -> (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) (Finset.univ.{u1} ι _inst_2) f)
Case conversion may be inaccurate. Consider using '#align complete_lattice.independent.sup_indep_univ CompleteLattice.Independent.sup_indep_univₓ'. -/
/- warning: finset.sup_indep.independent_of_univ -> Finset.SupIndep.independent_of_univ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {ι : Type.{u2}} [_inst_1 : CompleteLattice.{u1} α] [_inst_2 : Fintype.{u2} ι] {f : ι -> α}, (Finset.SupIndep.{u1, u2} α ι (CompleteLattice.toLattice.{u1} α _inst_1) (BoundedOrder.toOrderBot.{u1} α (Preorder.toLE.{u1} α (PartialOrder.toPreorder.{u1} α (SemilatticeInf.toPartialOrder.{u1} α (Lattice.toSemilatticeInf.{u1} α (CompleteLattice.toLattice.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} α _inst_1)) (Finset.univ.{u2} ι _inst_2) f) -> (CompleteLattice.Independent.{succ u2, u1} ι α _inst_1 f)
but is expected to have type
  forall {α : Type.{u2}} {ι : Type.{u1}} [_inst_1 : CompleteLattice.{u2} α] [_inst_2 : Fintype.{u1} ι] {f : ι -> α}, (Finset.SupIndep.{u2, u1} α ι (CompleteLattice.toLattice.{u2} α _inst_1) (BoundedOrder.toOrderBot.{u2} α (Preorder.toLE.{u2} α (PartialOrder.toPreorder.{u2} α (SemilatticeInf.toPartialOrder.{u2} α (Lattice.toSemilatticeInf.{u2} α (CompleteLattice.toLattice.{u2} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u2} α _inst_1)) (Finset.univ.{u1} ι _inst_2) f) -> (CompleteLattice.Independent.{succ u1, u2} ι α _inst_1 f)
Case conversion may be inaccurate. Consider using '#align finset.sup_indep.independent_of_univ Finset.SupIndep.independent_of_univₓ'. -/
alias CompleteLattice.independent_iff_supIndep_univ ↔
  CompleteLattice.Independent.sup_indep_univ Finset.SupIndep.independent_of_univ
#align complete_lattice.independent.sup_indep_univ CompleteLattice.Independent.sup_indep_univ
#align finset.sup_indep.independent_of_univ Finset.SupIndep.independent_of_univ

section Frame

namespace CompleteLattice

variable [Order.Frame α]

#print CompleteLattice.setIndependent_iff_pairwiseDisjoint /-
theorem setIndependent_iff_pairwiseDisjoint {s : Set α} :
    SetIndependent s ↔ s.PairwiseDisjoint id :=
  ⟨SetIndependent.pairwiseDisjoint, fun hs i hi =>
    disjoint_supₛ_iff.2 fun j hj => hs hi hj.1 <| Ne.symm hj.2⟩
#align complete_lattice.set_independent_iff_pairwise_disjoint CompleteLattice.setIndependent_iff_pairwiseDisjoint
-/

alias set_independent_iff_pairwise_disjoint ↔ _ _root_.set.pairwise_disjoint.set_independent
#align set.pairwise_disjoint.set_independent Set.PairwiseDisjoint.setIndependent

#print CompleteLattice.independent_iff_pairwiseDisjoint /-
theorem independent_iff_pairwiseDisjoint {f : ι → α} : Independent f ↔ Pairwise (Disjoint on f) :=
  ⟨Independent.pairwiseDisjoint, fun hs i =>
    disjoint_supᵢ_iff.2 fun j => disjoint_supᵢ_iff.2 fun hij => hs hij.symm⟩
#align complete_lattice.independent_iff_pairwise_disjoint CompleteLattice.independent_iff_pairwiseDisjoint
-/

end CompleteLattice

end Frame


/-
Copyright (c) 2017 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison, Reid Barton
-/
import category_theory.functor.fully_faithful

/-!
# Induced categories and full subcategories

Given a category `D` and a function `F : C → D `from a type `C` to the
objects of `D`, there is an essentially unique way to give `C` a
category structure such that `F` becomes a fully faithful functor,
namely by taking $$ Hom_C(X, Y) = Hom_D(FX, FY) $$. We call this the
category induced from `D` along `F`.

As a special case, if `C` is a subtype of `D`,
this produces the full subcategory of `D` on the objects belonging to `C`.
In general the induced category is equivalent to the full subcategory of `D` on the
image of `F`.

## Implementation notes

It looks odd to make `D` an explicit argument of `induced_category`,
when it is determined by the argument `F` anyways. The reason to make `D`
explicit is in order to control its syntactic form, so that instances
like `induced_category.has_forget₂` (elsewhere) refer to the correct
form of D. This is used to set up several algebraic categories like

  def CommMon : Type (u+1) := induced_category Mon (bundled.map @comm_monoid.to_monoid)
  -- not `induced_category (bundled monoid) (bundled.map @comm_monoid.to_monoid)`,
  -- even though `Mon = bundled monoid`!
-/

namespace category_theory

universes v v₂ u₁ u₂ -- morphism levels before object levels. See note [category_theory universes].

section induced

variables {C : Type u₁} (D : Type u₂) [category.{v} D]
variables (F : C → D)
include F

/--
`induced_category D F`, where `F : C → D`, is a typeclass synonym for `C`,
which provides a category structure so that the morphisms `X ⟶ Y` are the morphisms
in `D` from `F X` to `F Y`.
-/
@[nolint has_inhabited_instance unused_arguments]
def induced_category : Type u₁ := C

variables {D}

instance induced_category.has_coe_to_sort {α : Sort*} [has_coe_to_sort D α] :
  has_coe_to_sort (induced_category D F) α :=
⟨λ c, ↥(F c)⟩

instance induced_category.category : category.{v} (induced_category D F) :=
{ hom  := λ X Y, F X ⟶ F Y,
  id   := λ X, 𝟙 (F X),
  comp := λ _ _ _ f g, f ≫ g }

/--
The forgetful functor from an induced category to the original category,
forgetting the extra data.
-/
@[simps] def induced_functor : induced_category D F ⥤ D :=
{ obj := F, map := λ x y f, f }

instance induced_category.full : full (induced_functor F) :=
{ preimage := λ x y f, f }
instance induced_category.faithful : faithful (induced_functor F) := {}

end induced

section full_subcategory
/- A full subcategory is the special case of an induced category with F = subtype.val. -/

variables {C : Type u₁} [category.{v} C]
variables (Z : C → Prop)

/--
The category structure on a subtype; morphisms just ignore the property.

See https://stacks.math.columbia.edu/tag/001D. We do not define 'strictly full' subcategories.
-/
instance full_subcategory : category.{v} {X : C // Z X} :=
induced_category.category subtype.val

/--
The forgetful functor from a full subcategory into the original category
("forgetting" the condition).
-/
def full_subcategory_inclusion : {X : C // Z X} ⥤ C :=
induced_functor subtype.val

@[simp] lemma full_subcategory_inclusion.obj {X} :
  (full_subcategory_inclusion Z).obj X = X.val := rfl
@[simp] lemma full_subcategory_inclusion.map {X Y} {f : X ⟶ Y} :
  (full_subcategory_inclusion Z).map f = f := rfl

instance full_subcategory.full : full (full_subcategory_inclusion Z) :=
induced_category.full subtype.val
instance full_subcategory.faithful : faithful (full_subcategory_inclusion Z) :=
induced_category.faithful subtype.val

variables {Z} {Z' : C → Prop}

/-- An implication of predicates `Z → Z'` induces a functor between full subcategories. -/
@[simps]
def full_subcategory.map (h : ∀ ⦃X⦄, Z X → Z' X) : {X // Z X} ⥤ {X // Z' X} :=
{ obj := λ X, ⟨X.1, h X.2⟩,
  map := λ X Y f, f }

instance (h : ∀ ⦃X⦄, Z X → Z' X) : full (full_subcategory.map h) :=
{ preimage := λ X Y f, f }

instance (h : ∀ ⦃X⦄, Z X → Z' X) : faithful (full_subcategory.map h) := {}

@[simp] lemma full_subcategory.map_inclusion (h : ∀ ⦃X⦄, Z X → Z' X) :
  full_subcategory.map h ⋙ full_subcategory_inclusion Z' = full_subcategory_inclusion Z :=
rfl

section lift
variables {D : Type u₂} [category.{v₂} D] (P Q : D → Prop)

/-- A functor which maps objects to objects satisfying a certain property induces a lift through
    the full subcategory of objects satisfying that property. -/
@[simps]
def full_subcategory.lift (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) : C ⥤ {X // P X} :=
{ obj := λ X, ⟨F.obj X, hF X⟩,
  map := λ X Y f, F.map f }

/-- Composing the lift of a functor through a full subcategory with the inclusion yields the
    original functor. Unfortunately, this is not true by definition, so we only get a natural
    isomorphism, but it is pointwise definitionally true, see
    `full_subcategory.inclusion_obj_lift_obj` and `full_subcategory.inclusion_map_lift_map`. -/
def full_subcategory.lift_comp_inclusion (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) :
  full_subcategory.lift P F hF ⋙ full_subcategory_inclusion P ≅ F :=
nat_iso.of_components (λ X, iso.refl _) (by simp)

@[simp]
lemma full_subcategory.inclusion_obj_lift_obj (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) {X : C} :
  (full_subcategory_inclusion P).obj ((full_subcategory.lift P F hF).obj X) = F.obj X :=
rfl

lemma full_subcategory.inclusion_map_lift_map (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) {X Y : C}
  (f : X ⟶ Y) :
  (full_subcategory_inclusion P).map ((full_subcategory.lift P F hF).map f) = F.map f :=
rfl

instance (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) [faithful F] :
  faithful (full_subcategory.lift P F hF) :=
faithful.of_comp_iso (full_subcategory.lift_comp_inclusion P F hF)

instance (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) [full F] : full (full_subcategory.lift P F hF) :=
full.of_comp_faithful_iso (full_subcategory.lift_comp_inclusion P F hF)

@[simp]
lemma full_subcategory.lift_comp_map (F : C ⥤ D) (hF : ∀ X, P (F.obj X)) (h : ∀ ⦃X⦄, P X → Q X) :
  full_subcategory.lift P F hF ⋙ full_subcategory.map h =
    full_subcategory.lift Q F (λ X, h (hF X)) :=
rfl

end lift

end full_subcategory

end category_theory


example (p q : Prop) : p ∨ q → q ∨ p :=
begin
  intro h,
  cases h with hp hq,
  right, exact hp,
  left, exact hq
end