|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Yaël Dillies. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Yaël Dillies |
| 5 | +-/ |
| 6 | +import data.set.lattice |
| 7 | + |
| 8 | +/-! |
| 9 | +# Formal concept analysis |
| 10 | +
|
| 11 | +This file defines concept lattices. A concept of a relation `r : α → β → Prop` is a pair of sets |
| 12 | +`s : set α` and `t : set β` such that `s` is the set of all `a : α` that are related to all elements |
| 13 | +of `t`, and `t` is the set of all `b : β` that are related to all elements of `s`. |
| 14 | +
|
| 15 | +Ordering the concepts of a relation `r` by inclusion on the first component gives rise to a |
| 16 | +*concept lattice*. Every concept lattice is complete and in fact every complete lattice arises as |
| 17 | +the concept lattice of its `≤`. |
| 18 | +
|
| 19 | +## Implementation notes |
| 20 | +
|
| 21 | +Concept lattices are usually defined from a *context*, that is the triple `(α, β, r)`, but the type |
| 22 | +of `r` determines `α` and `β` already, so we do not define contexts as a separate object. |
| 23 | +
|
| 24 | +## TODO |
| 25 | +
|
| 26 | +Prove the fundamental theorem of concept lattices. |
| 27 | +
|
| 28 | +## References |
| 29 | +
|
| 30 | +* [Davey, Priestley *Introduction to Lattices and Order*][davey_priestley] |
| 31 | +
|
| 32 | +## Tags |
| 33 | +
|
| 34 | +concept, formal concept analysis, intent, extend, attribute |
| 35 | +-/ |
| 36 | + |
| 37 | +open function order_dual set |
| 38 | + |
| 39 | +variables {ι : Sort*} {α β γ : Type*} {κ : ι → Sort*} (r : α → β → Prop) {s s₁ s₂ : set α} |
| 40 | + {t t₁ t₂ : set β} |
| 41 | + |
| 42 | +/-! ### Intent and extent -/ |
| 43 | + |
| 44 | +/-- The intent closure of `s : set α` along a relation `r : α → β → Prop` is the set of all elements |
| 45 | +which `r` relates to all elements of `s`. -/ |
| 46 | +def intent_closure (s : set α) : set β := {b | ∀ ⦃a⦄, a ∈ s → r a b} |
| 47 | + |
| 48 | +/-- The extent closure of `t : set β` along a relation `r : α → β → Prop` is the set of all elements |
| 49 | +which `r` relates to all elements of `t`. -/ |
| 50 | +def extent_closure (t : set β) : set α := {a | ∀ ⦃b⦄, b ∈ t → r a b} |
| 51 | + |
| 52 | +variables {r} |
| 53 | + |
| 54 | +lemma subset_intent_closure_iff_subset_extent_closure : |
| 55 | + t ⊆ intent_closure r s ↔ s ⊆ extent_closure r t := |
| 56 | +⟨λ h a ha b hb, h hb ha, λ h b hb a ha, h ha hb⟩ |
| 57 | + |
| 58 | +variables (r) |
| 59 | + |
| 60 | +lemma gc_intent_closure_extent_closure : |
| 61 | + galois_connection (to_dual ∘ intent_closure r) (extent_closure r ∘ of_dual) := |
| 62 | +λ s t, subset_intent_closure_iff_subset_extent_closure |
| 63 | + |
| 64 | +lemma intent_closure_swap (t : set β) : intent_closure (swap r) t = extent_closure r t := rfl |
| 65 | +lemma extent_closure_swap (s : set α) : extent_closure (swap r) s = intent_closure r s := rfl |
| 66 | + |
| 67 | +@[simp] lemma intent_closure_empty : intent_closure r ∅ = univ := |
| 68 | +eq_univ_of_forall $ λ _ _, false.elim |
| 69 | + |
| 70 | +@[simp] lemma extent_closure_empty : extent_closure r ∅ = univ := intent_closure_empty _ |
| 71 | + |
| 72 | +@[simp] lemma intent_closure_union (s₁ s₂ : set α) : |
| 73 | + intent_closure r (s₁ ∪ s₂) = intent_closure r s₁ ∩ intent_closure r s₂ := |
| 74 | +set.ext $ λ _, ball_or_left_distrib |
| 75 | + |
| 76 | +@[simp] lemma extent_closure_union (t₁ t₂ : set β) : |
| 77 | + extent_closure r (t₁ ∪ t₂) = extent_closure r t₁ ∩ extent_closure r t₂ := |
| 78 | +intent_closure_union _ _ _ |
| 79 | + |
| 80 | +@[simp] lemma intent_closure_Union (f : ι → set α) : |
| 81 | + intent_closure r (⋃ i, f i) = ⋂ i, intent_closure r (f i) := |
| 82 | +(gc_intent_closure_extent_closure r).l_supr |
| 83 | + |
| 84 | +@[simp] lemma extent_closure_Union (f : ι → set β) : |
| 85 | + extent_closure r (⋃ i, f i) = ⋂ i, extent_closure r (f i) := |
| 86 | +intent_closure_Union _ _ |
| 87 | + |
| 88 | +@[simp] lemma intent_closure_Union₂ (f : Π i, κ i → set α) : |
| 89 | + intent_closure r (⋃ i j, f i j) = ⋂ i j, intent_closure r (f i j) := |
| 90 | +(gc_intent_closure_extent_closure r).l_supr₂ |
| 91 | + |
| 92 | +@[simp] lemma extent_closure_Union₂ (f : Π i, κ i → set β) : |
| 93 | + extent_closure r (⋃ i j, f i j) = ⋂ i j, extent_closure r (f i j) := |
| 94 | +intent_closure_Union₂ _ _ |
| 95 | + |
| 96 | +lemma subset_extent_closure_intent_closure (s : set α) : |
| 97 | + s ⊆ extent_closure r (intent_closure r s) := |
| 98 | +(gc_intent_closure_extent_closure r).le_u_l _ |
| 99 | + |
| 100 | +lemma subset_intent_closure_extent_closure (t : set β) : |
| 101 | + t ⊆ intent_closure r (extent_closure r t) := |
| 102 | +subset_extent_closure_intent_closure _ t |
| 103 | + |
| 104 | +@[simp] lemma intent_closure_extent_closure_intent_closure (s : set α) : |
| 105 | + intent_closure r (extent_closure r $ intent_closure r s) = intent_closure r s := |
| 106 | +(gc_intent_closure_extent_closure r).l_u_l_eq_l _ |
| 107 | + |
| 108 | +@[simp] lemma extent_closure_intent_closure_extent_closure (t : set β) : |
| 109 | + extent_closure r (intent_closure r $ extent_closure r t) = extent_closure r t := |
| 110 | +intent_closure_extent_closure_intent_closure _ t |
| 111 | + |
| 112 | +lemma intent_closure_anti : antitone (intent_closure r) := |
| 113 | +(gc_intent_closure_extent_closure r).monotone_l |
| 114 | + |
| 115 | +lemma extent_closure_anti : antitone (extent_closure r) := intent_closure_anti _ |
| 116 | + |
| 117 | +/-! ### Concepts -/ |
| 118 | + |
| 119 | +variables (α β) |
| 120 | + |
| 121 | +/-- The formal concepts of a relation. A concept of `r : α → β → Prop` is a pair of sets `s`, `t` |
| 122 | +such that `s` is the set of all elements that are `r`-related to all of `t` and `t` is the set of |
| 123 | +all elements that are `r`-related to all of `s`. -/ |
| 124 | +structure concept extends set α × set β := |
| 125 | +(closure_fst : intent_closure r fst = snd) |
| 126 | +(closure_snd : extent_closure r snd = fst) |
| 127 | + |
| 128 | +namespace concept |
| 129 | +variables {r α β} {c d : concept α β r} |
| 130 | + |
| 131 | +attribute [simp] closure_fst closure_snd |
| 132 | + |
| 133 | +@[ext] lemma ext (h : c.fst = d.fst) : c = d := |
| 134 | +begin |
| 135 | + obtain ⟨⟨s₁, t₁⟩, h₁, _⟩ := c, |
| 136 | + obtain ⟨⟨s₂, t₂⟩, h₂, _⟩ := d, |
| 137 | + dsimp at h₁ h₂ h, |
| 138 | + subst h, |
| 139 | + subst h₁, |
| 140 | + subst h₂, |
| 141 | +end |
| 142 | + |
| 143 | +lemma ext' (h : c.snd = d.snd) : c = d := |
| 144 | +begin |
| 145 | + obtain ⟨⟨s₁, t₁⟩, _, h₁⟩ := c, |
| 146 | + obtain ⟨⟨s₂, t₂⟩, _, h₂⟩ := d, |
| 147 | + dsimp at h₁ h₂ h, |
| 148 | + subst h, |
| 149 | + subst h₁, |
| 150 | + subst h₂, |
| 151 | +end |
| 152 | + |
| 153 | +lemma fst_injective : injective (λ c : concept α β r, c.fst) := λ c d, ext |
| 154 | +lemma snd_injective : injective (λ c : concept α β r, c.snd) := λ c d, ext' |
| 155 | + |
| 156 | +instance : has_sup (concept α β r) := |
| 157 | +⟨λ c d, { fst := extent_closure r (c.snd ∩ d.snd), |
| 158 | + snd := c.snd ∩ d.snd, |
| 159 | + closure_fst := by rw [←c.closure_fst, ←d.closure_fst, ←intent_closure_union, |
| 160 | + intent_closure_extent_closure_intent_closure], |
| 161 | + closure_snd := rfl }⟩ |
| 162 | + |
| 163 | +instance : has_inf (concept α β r) := |
| 164 | +⟨λ c d, { fst := c.fst ∩ d.fst, |
| 165 | + snd := intent_closure r (c.fst ∩ d.fst), |
| 166 | + closure_fst := rfl, |
| 167 | + closure_snd := by rw [←c.closure_snd, ←d.closure_snd, ←extent_closure_union, |
| 168 | + extent_closure_intent_closure_extent_closure] }⟩ |
| 169 | + |
| 170 | +instance : semilattice_inf (concept α β r) := fst_injective.semilattice_inf _ $ λ _ _, rfl |
| 171 | + |
| 172 | +@[simp] lemma fst_subset_fst_iff : c.fst ⊆ d.fst ↔ c ≤ d := iff.rfl |
| 173 | +@[simp] lemma fst_ssubset_fst_iff : c.fst ⊂ d.fst ↔ c < d := iff.rfl |
| 174 | + |
| 175 | +@[simp] lemma snd_subset_snd_iff : c.snd ⊆ d.snd ↔ d ≤ c := |
| 176 | +begin |
| 177 | + refine ⟨λ h, _, λ h, _⟩, |
| 178 | + { rw [←fst_subset_fst_iff, ←c.closure_snd, ←d.closure_snd], |
| 179 | + exact extent_closure_anti _ h }, |
| 180 | + { rw [←c.closure_fst, ←d.closure_fst], |
| 181 | + exact intent_closure_anti _ h } |
| 182 | +end |
| 183 | + |
| 184 | +@[simp] lemma snd_ssubset_snd_iff : c.snd ⊂ d.snd ↔ d < c := |
| 185 | +by rw [ssubset_iff_subset_not_subset, lt_iff_le_not_le, snd_subset_snd_iff, snd_subset_snd_iff] |
| 186 | + |
| 187 | +lemma strict_mono_fst : strict_mono (prod.fst ∘ to_prod : concept α β r → set α) := |
| 188 | +λ c d, fst_ssubset_fst_iff.2 |
| 189 | + |
| 190 | +lemma strict_anti_snd : strict_anti (prod.snd ∘ to_prod : concept α β r → set β) := |
| 191 | +λ c d, snd_ssubset_snd_iff.2 |
| 192 | + |
| 193 | +instance : lattice (concept α β r) := |
| 194 | +{ sup := (⊔), |
| 195 | + le_sup_left := λ c d, snd_subset_snd_iff.1 $ inter_subset_left _ _, |
| 196 | + le_sup_right := λ c d, snd_subset_snd_iff.1 $ inter_subset_right _ _, |
| 197 | + sup_le := λ c d e, by { simp_rw ←snd_subset_snd_iff, exact subset_inter }, |
| 198 | + ..concept.semilattice_inf } |
| 199 | + |
| 200 | +instance : bounded_order (concept α β r) := |
| 201 | +{ top := ⟨⟨univ, intent_closure r univ⟩, rfl, eq_univ_of_forall $ λ a b hb, hb trivial⟩, |
| 202 | + le_top := λ _, subset_univ _, |
| 203 | + bot := ⟨⟨extent_closure r univ, univ⟩, eq_univ_of_forall $ λ b a ha, ha trivial, rfl⟩, |
| 204 | + bot_le := λ _, snd_subset_snd_iff.1 $ subset_univ _ } |
| 205 | + |
| 206 | +instance : has_Sup (concept α β r) := |
| 207 | +⟨λ S, { fst := extent_closure r (⋂ c ∈ S, (c : concept _ _ _).snd), |
| 208 | + snd := ⋂ c ∈ S, (c : concept _ _ _).snd, |
| 209 | + closure_fst := by simp_rw [←closure_fst, ←intent_closure_Union₂, |
| 210 | + intent_closure_extent_closure_intent_closure], |
| 211 | + closure_snd := rfl }⟩ |
| 212 | + |
| 213 | +instance : has_Inf (concept α β r) := |
| 214 | +⟨λ S, { fst := ⋂ c ∈ S, (c : concept _ _ _).fst, |
| 215 | + snd := intent_closure r (⋂ c ∈ S, (c : concept _ _ _).fst), |
| 216 | + closure_fst := rfl, |
| 217 | + closure_snd := by simp_rw [←closure_snd, ←extent_closure_Union₂, |
| 218 | + extent_closure_intent_closure_extent_closure] }⟩ |
| 219 | + |
| 220 | +instance : complete_lattice (concept α β r) := |
| 221 | +{ Sup := Sup, |
| 222 | + le_Sup := λ S c hc, snd_subset_snd_iff.1 $ bInter_subset_of_mem hc, |
| 223 | + Sup_le := λ S c hc, snd_subset_snd_iff.1 $ subset_Inter₂ $ λ d hd, snd_subset_snd_iff.2 $ hc d hd, |
| 224 | + Inf := Inf, |
| 225 | + Inf_le := λ S c, bInter_subset_of_mem, |
| 226 | + le_Inf := λ S c, subset_Inter₂, |
| 227 | + ..concept.lattice, ..concept.bounded_order } |
| 228 | + |
| 229 | +@[simp] lemma top_fst : (⊤ : concept α β r).fst = univ := rfl |
| 230 | +@[simp] lemma top_snd : (⊤ : concept α β r).snd = intent_closure r univ := rfl |
| 231 | +@[simp] lemma bot_fst : (⊥ : concept α β r).fst = extent_closure r univ := rfl |
| 232 | +@[simp] lemma bot_snd : (⊥ : concept α β r).snd = univ := rfl |
| 233 | +@[simp] lemma sup_fst (c d : concept α β r) : (c ⊔ d).fst = extent_closure r (c.snd ∩ d.snd) := rfl |
| 234 | +@[simp] lemma sup_snd (c d : concept α β r) : (c ⊔ d).snd = c.snd ∩ d.snd := rfl |
| 235 | +@[simp] lemma inf_fst (c d : concept α β r) : (c ⊓ d).fst = c.fst ∩ d.fst := rfl |
| 236 | +@[simp] lemma inf_snd (c d : concept α β r) : (c ⊓ d).snd = intent_closure r (c.fst ∩ d.fst) := rfl |
| 237 | +@[simp] lemma Sup_fst (S : set (concept α β r)) : |
| 238 | + (Sup S).fst = extent_closure r ⋂ c ∈ S, (c : concept _ _ _).snd := rfl |
| 239 | +@[simp] lemma Sup_snd (S : set (concept α β r)) : (Sup S).snd = ⋂ c ∈ S, (c : concept _ _ _).snd := |
| 240 | +rfl |
| 241 | +@[simp] lemma Inf_fst (S : set (concept α β r)) : (Inf S).fst = ⋂ c ∈ S, (c : concept _ _ _).fst := |
| 242 | +rfl |
| 243 | +@[simp] lemma Inf_snd (S : set (concept α β r)) : |
| 244 | + (Inf S).snd = intent_closure r ⋂ c ∈ S, (c : concept _ _ _).fst := rfl |
| 245 | + |
| 246 | +instance : inhabited (concept α β r) := ⟨⊥⟩ |
| 247 | + |
| 248 | +/-- Swap the sets of a concept to make it a concept of the dual context. -/ |
| 249 | +@[simps] def swap (c : concept α β r) : concept β α (swap r) := |
| 250 | +⟨c.to_prod.swap, c.closure_snd, c.closure_fst⟩ |
| 251 | + |
| 252 | +@[simp] lemma swap_swap (c : concept α β r) : c.swap.swap = c := ext rfl |
| 253 | + |
| 254 | +@[simp] lemma swap_le_swap_iff : c.swap ≤ d.swap ↔ d ≤ c := snd_subset_snd_iff |
| 255 | +@[simp] lemma swap_lt_swap_iff : c.swap < d.swap ↔ d < c := snd_ssubset_snd_iff |
| 256 | + |
| 257 | +/-- The dual of a concept lattice is isomorphic to the concept lattice of the dual context. -/ |
| 258 | +@[simps] def swap_equiv : order_dual (concept α β r) ≃o concept β α (function.swap r) := |
| 259 | +{ to_fun := swap ∘ of_dual, |
| 260 | + inv_fun := to_dual ∘ swap, |
| 261 | + left_inv := swap_swap, |
| 262 | + right_inv := swap_swap, |
| 263 | + map_rel_iff' := λ c d, swap_le_swap_iff } |
| 264 | + |
| 265 | +end concept |
0 commit comments