@@ -6,108 +6,126 @@ Authors: Fabrizio Montesi, Xueying Qin
66
77import Mathlib.Data.Finset.Basic
88
9- /-! # Finite Functions
9+ /-! # Finite functions
1010
11- *Note:* the API and notation of `FinFun` is still unstable.
12-
13- A `FinFun α β` is a function from `α` to `β` with a finite domain of definition .
11+ Given types `α` and `β`, and assuming that `β` has a `Zero` element,
12+ a `FinFun α β` is a function from `α` to `β` where only a finite number of elements
13+ in `α` are mapped to non-zero elements .
1414-/
1515
1616namespace Cslib
1717
18- /-- A finite function FinFun is a function `f` equipped with a domain of definition `dom`. -/
19- structure FinFun (α : Type u) (β : Type v) where
20- f : α → β
21- dom : Finset α
22-
23- notation :50 α " ⇀ " β => FinFun α β
24- notation :50 f "↾" dom => FinFun.mk f dom
25-
26- abbrev CompleteDom [Zero β] (f : α ⇀ β) := ∀ x, x ∉ f.dom → f.f x = 0
27-
28- def FinFun.defined (f : α ⇀ β) (x : α) : Prop := x ∈ f.dom
29-
30- @[simp]
31- abbrev FinFun.apply (f : α ⇀ β) (x : α) : β := f.f x
32-
33- /- Conversion from FinFun to a function. -/
34- @[coe] def FinFun.toFun [DecidableEq α] [Zero β] (f : α ⇀ β) : (α → β) :=
35- fun x => if x ∈ f.dom then f.f x else Zero.zero
36-
37- instance [DecidableEq α] [Zero β] : Coe (α ⇀ β) (α → β) where
38- coe := FinFun.toFun
39-
40- theorem FinFun.toFun_char [DecidableEq α] [Zero β]
41- {f g : α ⇀ β} (h : (f : α → β) = (g : α → β)) (x) :
42- (x ∈ (f.dom ∩ g.dom) →
43- f.apply x = g.apply x) ∧ (x ∈ (f.dom \ g.dom) →
44- f.apply x = Zero.zero) ∧ (x ∈ (g.dom \ f.dom) → g.apply x = Zero.zero) := by
45- have happlyx : f.toFun x = g.toFun x := by simp [h]
46- grind [FinFun.toFun]
47-
48- theorem FinFun.toFun_dom [DecidableEq α] [Zero β] {f : α ⇀ β}
49- (h : ∀ x, x ∉ f.dom → f.apply x = Zero.zero) : (f : α → β) = f.f := by
50- grind [FinFun.toFun]
51-
52- def FinFun.mapBin [DecidableEq α] (f g : α ⇀ β) (op : Option β → Option β → Option β) :
53- Option (α ⇀ β) :=
54- if f.dom = g.dom ∧ ∀ x ∈ f.dom, (op (some (f.f x)) (some (g.f x))).isSome then
55- some {
56- f := fun x =>
57- match op (some (f.f x)) (some (g.f x)) with
58- | some y => y
59- | none => f.f x
60- dom := f.dom
61- }
62- else
63- none
64-
65- theorem FinFun.mapBin_dom [DecidableEq α] (f g : α ⇀ β)
66- (op : Option β → Option β → Option β) (h : FinFun.mapBin f g op = some fg) :
67- fg.dom = f.dom ∧ fg.dom = g.dom := by grind [mapBin]
68-
69- theorem FinFun.mapBin_char₁ [DecidableEq α] (f g : α ⇀ β)
70- (op : Option β → Option β → Option β) (h : FinFun.mapBin f g op = some fg) :
71- ∀ x ∈ fg.dom, fg.apply x = y ↔ (op (some (f.f x)) (some (g.f x))) = some y := by
72- intro x hxdom
73- constructor
74- <;> simp only [mapBin, Option.ite_none_right_eq_some] at h
75- <;> rcases h with ⟨_, _, _, _⟩
76- <;> grind
77-
78- theorem FinFun.mapBin_char₂ [DecidableEq α] (f g : α ⇀ β)
79- (op : Option β → Option β → Option β) (hdom : f.dom = g.dom)
80- (hop : ∀ x ∈ f.dom, (op (some (f.f x)) (some (g.f x))).isSome)
81- : (FinFun.mapBin f g op).isSome := by grind [mapBin]
82-
83- -- Fun to FinFun
84- def Function.toFinFun [DecidableEq α] (f : α → β) (dom : Finset α) : α ⇀ β := FinFun.mk f dom
85-
86- lemma Function.toFinFun_eq [DecidableEq α] [Zero β] (f : α → β) (dom : Finset α)
87- (h : ∀ x, x ∉ dom → f x = 0 ) : f = (Function.toFinFun f dom) := by
88- funext p
89- by_cases hp : p ∈ dom <;> simp only [toFinFun, FinFun.toFun, hp, reduceIte]
90- exact h p hp
91-
92- @[coe] def FinFun.toDomFun (f : α ⇀ β) : {x // x ∈ f.dom} → β :=
93- fun x => f.f x
94-
95- theorem FinFun.toDomFun_char (f : α ⇀ β) (h : x ∈ f.dom) : f.toDomFun ⟨ x, h ⟩ = f.f x := by
96- simp [FinFun.toDomFun]
97-
98- theorem FinFun.congrFinFun [DecidableEq α] [Zero β] {f g : α ⇀ β} (h : f = g) (a : α) :
99- f.apply a = g.apply a := congrFun (congrArg apply h) a
100-
101- theorem FinFun.eq_char₁ [DecidableEq α] [Zero β] {f g : α ⇀ β} (h : f = g) :
102- f.f = g.f ∧ f.dom = g.dom := ⟨congrArg FinFun.f h, congrArg dom h⟩
103-
104- theorem FinFun.eq_char₂ [DecidableEq α] [Zero β] {f g : α ⇀ β} (heq : f.f = g.f ∧ f.dom = g.dom) :
105- f = g := by
106- cases f
107- cases g
18+ /-- A `FinFun` is a function `fn` with a finite `support`.
19+
20+ This is similar to `Finsupp` in Mathlib, but definitions are computable. -/
21+ structure FinFun (α : Type _) (β : Type _) [Zero β] where
22+ /-- The underlying function. -/
23+ fn : α → β
24+ /-- The finite support of the function. -/
25+ support : Finset α
26+ /-- Proof that `support` is the support of the underlying function. -/
27+ mem_support_fn {a : α} : a ∈ support ↔ fn a ≠ 0
28+
29+ attribute [scoped grind _=_] FinFun.mem_support_fn
30+
31+ namespace FinFun
32+
33+ @[inherit_doc]
34+ scoped infixr :25 " →₀ " => FinFun
35+
36+ /-- Constructs a `FinFun` by restricting a function to a given support, filtering out all elements
37+ not mapped to 0 in the support. -/
38+ @[scoped grind .]
39+ private def fromFun {α β : Type _} [Zero β] [DecidableEq α]
40+ [∀ y : β, Decidable (y = 0 )] (fn : α → β) (support : Finset α) : α →₀ β where
41+ fn := (fun a => if a ∈ support then fn a else 0 )
42+ support := support.filter (fn · ≠ 0 )
43+ mem_support_fn := by grind
44+
45+ @[inherit_doc]
46+ scoped notation f:25 "↾₀" support:51 => FinFun.fromFun f support
47+
48+ instance instFunLike [Zero β] : FunLike (α →₀ β) α β where
49+ coe f := f.fn
50+ coe_injective' := by
51+ rintro ⟨_, _⟩ ⟨_, _⟩
52+ simp_all [Finset.ext_iff]
53+
54+ @[scoped grind =]
55+ theorem coe_fn [Zero β] {f : α →₀ β} : (f : α → β) = f.fn := by simp [DFunLike.coe]
56+
57+ @[scoped grind =]
58+ theorem coe_eq_fn [Zero β] {f : α →₀ β} : f a = f.fn a := by
59+ simp [DFunLike.coe]
60+
61+ /-- Extensional equality for `FinFun`. -/
62+ @[scoped grind ←=]
63+ theorem ext [Zero β] {f g : α →₀ β} (h : ∀ (a : α), f a = g a) : f = g :=
64+ DFunLike.ext (f := f) (g := g) h
65+
66+ @[scoped grind _=_]
67+ theorem mem_support_not_zero [Zero β] {f : α →₀ β} : a ∈ f.support ↔ f a ≠ 0 := by
68+ grind
69+
70+ @[scoped grind _=_]
71+ theorem not_mem_support_zero [Zero β] {f : α →₀ β} : a ∉ f.support ↔ f a = 0 := by
72+ grind
73+
74+ /-- If two `FinFun`s are equal, their underlying functions and supports are equal. -/
75+ @[scoped grind .]
76+ theorem eq_fields_eq [DecidableEq α] [Zero β] {f g : α →₀ β} :
77+ f = g → (f.fn = g.fn ∧ f.support = g.support) := by grind
78+
79+ /-- If two functions are equal, two `FinFun`s respectively using them as underlying functions
80+ are equal. -/
81+ @[scoped grind .]
82+ theorem fn_eq_eq [DecidableEq α] [Zero β] {f g : α →₀ β} (h : f.fn = g.fn) : f = g :=
83+ ext (congrFun h)
84+
85+ @[scoped grind =>]
86+ theorem congrFinFun [DecidableEq α] [Zero β] {f g : α →₀ β} (h : f = g) (a : α) :
87+ f a = g a := by grind
88+
89+ @[scoped grind =]
90+ theorem fromFun_eq [Zero β] [DecidableEq α] [∀ y : β, Decidable (y = 0 )]
91+ (f : α → β) (support : Finset α) (h : ∀ a, a ∉ support → f a = 0 ) :
92+ (f ↾₀ support) = f := by grind
93+
94+ @[scoped grind =]
95+ theorem fromFun_fn [Zero β] [DecidableEq α] [∀ y : β, Decidable (y = 0 )]
96+ (f : α → β) (support : Finset α) :
97+ (f ↾₀ support).fn = (fun a => if a ∈ support then f a else 0 ) := by
98+ grind
99+
100+ @[scoped grind =]
101+ theorem fromFun_support [Zero β] [DecidableEq α] [∀ y : β, Decidable (y = 0 )]
102+ (f : α → β) (support : Finset α) :
103+ (f ↾₀ support).support = support.filter (f · ≠ 0 ) := by
108104 grind
109105
110- theorem FinFun.eq_char [DecidableEq α] [Zero β] {f g : α ⇀ β} :
111- f = g ↔ f.f = g.f ∧ f.dom = g.dom := by grind [FinFun.eq_char₁, FinFun.eq_char₂]
106+ /-- Restricting a function twice to the same support is idempotent. -/
107+ @[scoped grind =]
108+ theorem fromFun_idem [Zero β] [DecidableEq α]
109+ [∀ y : β, Decidable (y = 0 )] {f : α → β} {support : Finset α} :
110+ (f ↾₀ support) ↾₀ support = f ↾₀ support := by grind
111+
112+ /-- Restricting a `FinFun` to its own support is the identity. -/
113+ @[scoped grind =]
114+ theorem coe_fromFun_id [Zero β] [DecidableEq α] [∀ y : β, Decidable (y = 0 )] {f : α →₀ β} :
115+ (f ↾₀ f.support) = f := by grind
116+
117+ /-- Restricting a function twice to two supports is equal to restricting to their intersection. -/
118+ @[scoped grind =]
119+ theorem fromFun_inter [Zero β] [DecidableEq α]
120+ [∀ y : β, Decidable (y = 0 )] {f : α → β} {support1 support2 : Finset α} :
121+ (f ↾₀ support1) ↾₀ support2 = f ↾₀ (support1 ∩ support2) := by grind
122+
123+ /-- Restricting a function is commutative. -/
124+ @[scoped grind =]
125+ theorem fromFun_comm [Zero β] [DecidableEq α]
126+ [∀ y : β, Decidable (y = 0 )] {f : α → β} {support1 support2 : Finset α} :
127+ (f ↾₀ support1) ↾₀ support2 = (f ↾₀ support2) ↾₀ support1 := by grind
128+
129+ end FinFun
112130
113131end Cslib
0 commit comments