|
| 1 | +Require Import Basics.Overture Basics.Decidable Spaces.Nat. |
| 2 | +Require Import Algebra.Rings.Ring. |
| 3 | +Require Import Classes.interfaces.abstract_algebra. |
| 4 | + |
| 5 | +(** ** Kronecker Delta *) |
| 6 | + |
| 7 | +Section AssumeDecidable. |
| 8 | + (** Throughout this section, we assume that we have a type [A] with decidable equality. This will be our indexing type and can be thought of as [nat] for reading purposes. *) |
| 9 | + |
| 10 | + Context {A : Type} `{DecidablePaths A}. |
| 11 | + |
| 12 | + (** The Kronecker delta function is a function of elements of [A] that is 1 when the two numbers are equal and 0 otherwise. It is useful for working with finite sums of ring elements. *) |
| 13 | + Definition kronecker_delta {R : Ring} (i j : A) : R |
| 14 | + := if dec (i = j) then 1 else 0. |
| 15 | + |
| 16 | + (** Kronecker delta with the same index is 1. *) |
| 17 | + Definition kronecker_delta_refl {R : Ring} (i : A) |
| 18 | + : kronecker_delta (R:=R) i i = 1. |
| 19 | + Proof. |
| 20 | + unfold kronecker_delta. |
| 21 | + generalize (dec (i = i)). |
| 22 | + by rapply decidable_paths_refl. |
| 23 | + Defined. |
| 24 | + |
| 25 | + (** Kronecker delta with differing indices is 0. *) |
| 26 | + Definition kronecker_delta_neq {R : Ring} {i j : A} (p : i <> j) |
| 27 | + : kronecker_delta (R:=R) i j = 0. |
| 28 | + Proof. |
| 29 | + unfold kronecker_delta. |
| 30 | + by decidable_false (dec (i = j)) p. |
| 31 | + Defined. |
| 32 | + |
| 33 | + (** Kronecker delta is symmetric in its arguments. *) |
| 34 | + Definition kronecker_delta_symm {R : Ring} (i j : A) |
| 35 | + : kronecker_delta (R:=R) i j = kronecker_delta j i. |
| 36 | + Proof. |
| 37 | + unfold kronecker_delta. |
| 38 | + destruct (dec (i = j)) as [p|q]. |
| 39 | + - by decidable_true (dec (j = i)) p^. |
| 40 | + - by decidable_false (dec (j = i)) (symmetric_neq q). |
| 41 | + Defined. |
| 42 | + |
| 43 | + (** An injective endofunction on [A] preserves the Kronecker delta. *) |
| 44 | + Definition kronecker_delta_map_inj {R : Ring} (i j : A) (f : A -> A) |
| 45 | + `{!IsInjective f} |
| 46 | + : kronecker_delta (R:=R) (f i) (f j) = kronecker_delta i j. |
| 47 | + Proof. |
| 48 | + unfold kronecker_delta. |
| 49 | + destruct (dec (i = j)) as [p|p]. |
| 50 | + - by decidable_true (dec (f i = f j)) (ap f p). |
| 51 | + - destruct (dec (f i = f j)) as [q|q]. |
| 52 | + + apply (injective f) in q. |
| 53 | + contradiction. |
| 54 | + + reflexivity. |
| 55 | + Defined. |
| 56 | + |
| 57 | + (** Kronecker delta commutes with any ring element. *) |
| 58 | + Definition kronecker_delta_comm {R : Ring} (i j : A) (r : R) |
| 59 | + : r * kronecker_delta i j = kronecker_delta i j * r. |
| 60 | + Proof. |
| 61 | + unfold kronecker_delta. |
| 62 | + destruct (dec (i = j)). |
| 63 | + - exact (rng_mult_one_r _ @ (rng_mult_one_l _)^). |
| 64 | + - exact (rng_mult_zero_r _ @ (rng_mult_zero_l _)^). |
| 65 | + Defined. |
| 66 | + |
| 67 | +End AssumeDecidable. |
| 68 | + |
| 69 | +(** The following lemmas are specialised to when the indexing type is [nat]. *) |
| 70 | + |
| 71 | +(** Kronecker delta where the first index is strictly less than the second is 0. *) |
| 72 | +Definition kronecker_delta_lt {R : Ring} {i j : nat} (p : (i < j)%nat) |
| 73 | + : kronecker_delta (R:=R) i j = 0. |
| 74 | +Proof. |
| 75 | + apply kronecker_delta_neq. |
| 76 | + intros q; destruct q. |
| 77 | + by apply not_lt_n_n in p. |
| 78 | +Defined. |
| 79 | + |
| 80 | +(** Kronecker delta where the first index is strictly greater than the second is 0. *) |
| 81 | +Definition kronecker_delta_gt {R : Ring} {i j : nat} (p : (j < i)%nat) |
| 82 | + : kronecker_delta (R:=R) i j = 0. |
| 83 | +Proof. |
| 84 | + apply kronecker_delta_neq. |
| 85 | + intros q; destruct q. |
| 86 | + by apply not_lt_n_n in p. |
| 87 | +Defined. |
| 88 | + |
| 89 | +(** Kronecker delta can be used to extract a single term from a finite sum. *) |
| 90 | +Definition rng_sum_kronecker_delta_l {R : Ring} (n i : nat) (Hi : (i < n)%nat) |
| 91 | + (f : forall k, (k < n)%nat -> R) |
| 92 | + : rng_sum n (fun j Hj => kronecker_delta i j * f j Hj) = f i Hi. |
| 93 | +Proof. |
| 94 | + induction n as [|n IHn] in i, Hi, f |- *. |
| 95 | + 1: destruct (not_leq_Sn_0 _ Hi). |
| 96 | + destruct (dec (i = n)) as [p|p]. |
| 97 | + - destruct p; simpl. |
| 98 | + rewrite kronecker_delta_refl. |
| 99 | + rewrite rng_mult_one_l. |
| 100 | + rewrite <- rng_plus_zero_r. |
| 101 | + f_ap; [f_ap; rapply path_ishprop|]. |
| 102 | + nrapply rng_sum_zero. |
| 103 | + intros k Hk. |
| 104 | + rewrite (kronecker_delta_gt Hk). |
| 105 | + apply rng_mult_zero_l. |
| 106 | + - simpl; lhs nrapply ap. |
| 107 | + + nrapply IHn. |
| 108 | + apply diseq_implies_lt in p. |
| 109 | + destruct p; [assumption|]. |
| 110 | + contradiction (lt_implies_not_geq Hi). |
| 111 | + + rewrite (kronecker_delta_neq p). |
| 112 | + rewrite rng_mult_zero_l. |
| 113 | + rewrite rng_plus_zero_l. |
| 114 | + f_ap; apply path_ishprop. |
| 115 | +Defined. |
| 116 | + |
| 117 | +(** Variant of [rng_sum_kronecker_delta_l] where the indexing is swapped. *) |
| 118 | +Definition rng_sum_kronecker_delta_l' {R : Ring} (n i : nat) (Hi : (i < n)%nat) |
| 119 | + (f : forall k, (k < n)%nat -> R) |
| 120 | + : rng_sum n (fun j Hj => kronecker_delta j i * f j Hj) = f i Hi. |
| 121 | +Proof. |
| 122 | + lhs nrapply path_rng_sum. |
| 123 | + 2: nrapply rng_sum_kronecker_delta_l. |
| 124 | + intros k Hk. |
| 125 | + cbn; f_ap; apply kronecker_delta_symm. |
| 126 | +Defined. |
| 127 | + |
| 128 | +(** Variant of [rng_sum_kronecker_delta_l] where the Kronecker delta appears on the right. *) |
| 129 | +Definition rng_sum_kronecker_delta_r {R : Ring} (n i : nat) (Hi : (i < n)%nat) |
| 130 | + (f : forall k, (k < n)%nat -> R) |
| 131 | + : rng_sum n (fun j Hj => f j Hj * kronecker_delta i j) = f i Hi. |
| 132 | +Proof. |
| 133 | + lhs nrapply path_rng_sum. |
| 134 | + 2: nrapply rng_sum_kronecker_delta_l. |
| 135 | + intros k Hk. |
| 136 | + apply kronecker_delta_comm. |
| 137 | +Defined. |
| 138 | + |
| 139 | +(** Variant of [rng_sum_kronecker_delta_r] where the indexing is swapped. *) |
| 140 | +Definition rng_sum_kronecker_delta_r' {R : Ring} (n i : nat) (Hi : (i < n)%nat) |
| 141 | + (f : forall k, (k < n)%nat -> R) |
| 142 | + : rng_sum n (fun j Hj => f j Hj * kronecker_delta j i) = f i Hi. |
| 143 | +Proof. |
| 144 | + lhs nrapply path_rng_sum. |
| 145 | + 2: nrapply rng_sum_kronecker_delta_l'. |
| 146 | + intros k Hk. |
| 147 | + apply kronecker_delta_comm. |
| 148 | +Defined. |
0 commit comments