feat(Analysis/Matrix): add Jacobian matrix for matrix-valued functions#33786
feat(Analysis/Matrix): add Jacobian matrix for matrix-valued functions#33786hdmkindom wants to merge 8 commits intoleanprover-community:masterfrom
Conversation
This PR introduces the Jacobian matrix for functions F : Matrix m n ℝ → Matrix p q ℝ. Main definitions: - `jacobianMatrix F X`: The Jacobian matrix at point X, indexed by (p × q) × (m × n) Main theorems: - `fderiv_eq_jacobian_mul`: Express fderiv in terms of Jacobian entries - `jacobianMatrix_comp`: Chain rule for Jacobian matrices - Basic rules: linearity, identity, constant, addition, scalar multiplication
This PR introduces the Jacobian matrix for functions F : Matrix m n ℝ → Matrix p q ℝ. Main definitions: - `jacobianMatrix F X`: The Jacobian matrix at point X, indexed by (p × q) × (m × n) Main theorems: - `fderiv_eq_jacobian_mul`: Express fderiv in terms of Jacobian entries - `jacobianMatrix_comp`: Chain rule for Jacobian matrices - Basic rules: linearity, identity, constant, addition, scalar multiplication
PR summary bd33e8d4d0Import changes for modified filesNo significant changes to the import graph Import changes for all files
|
This PR introduces the Jacobian matrix for functions F : Matrix m n ℝ → Matrix p q ℝ. Main definitions: - `jacobianMatrix F X`: The Jacobian matrix at point X, indexed by (p × q) × (m × n) Main theorems: - `fderiv_eq_jacobian_mul`: Express fderiv in terms of Jacobian entries - `jacobianMatrix_comp`: Chain rule for Jacobian matrices - Basic rules: linearity, identity, constant, addition, scalar multiplication
Please remove this line from the PR description. If you meant to indicate that you are adding a new file, please say that. |
| (F : Matrix m n ℝ → Matrix p q ℝ) | ||
| (G : Matrix p q ℝ → Matrix r s ℝ) | ||
| (X : Matrix m n ℝ) |
There was a problem hiding this comment.
Can you extract these into variable statement as well.
| `J[(i, k), (j, l)] = (fderiv ℝ F X (Matrix.single j l 1)) i k`. | ||
| -/ | ||
| noncomputable def jacobianMatrix | ||
| (F : Matrix m n ℝ → Matrix p q ℝ) (X : Matrix m n ℝ) : |
There was a problem hiding this comment.
Can you generalize this from ℝ to non-trivially normed fields?
| noncomputable def jacobianMatrix | ||
| (F : Matrix m n ℝ → Matrix p q ℝ) (X : Matrix m n ℝ) : | ||
| Matrix (p × q) (m × n) ℝ := | ||
| fun (i, k) (j, l) => (fderiv ℝ F X (Matrix.single j l (1 : ℝ))) i k |
There was a problem hiding this comment.
| fun (i, k) (j, l) => (fderiv ℝ F X (Matrix.single j l (1 : ℝ))) i k | |
| fun (i, k) (j, l) => fderiv ℝ F X (Matrix.single j l (1 : ℝ)) i k |
| -- unfold Jacobian entries | ||
| simp only [jacobianMatrix_eq_fderiv_basis] | ||
| -- decompose `H` into the standard basis | ||
| have h_decomp : H = ∑ j : m, ∑ l : n, Matrix.single j l (H j l) := by | ||
| simpa using (Matrix.matrix_eq_sum_single H) | ||
| conv_lhs => rw [h_decomp] | ||
| -- linearity through sums | ||
| simp only [map_sum] | ||
| -- pull out entries `(i, k)` | ||
| rw [Finset.sum_apply, Finset.sum_apply] | ||
| refine Finset.sum_congr rfl ?_ | ||
| intro j _ | ||
| rw [Finset.sum_apply, Finset.sum_apply] | ||
| refine Finset.sum_congr rfl ?_ | ||
| intro l _ | ||
| -- rewrite `single j l (H j l)` as a scalar multiple of `single j l 1` | ||
| have hs : Matrix.single j l (H j l) = (H j l) • Matrix.single j l (1 : ℝ) := by | ||
| simp only [smul_single, smul_eq_mul, mul_one] | ||
| -- apply `map_smul` and commute the scalar | ||
| calc | ||
| (fderiv ℝ F X) (Matrix.single j l (H j l)) i k | ||
| = (fderiv ℝ F X) ((H j l) • Matrix.single j l (1 : ℝ)) i k := by | ||
| rw [hs] | ||
| _ = (H j l) * (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k := by | ||
| rw [map_smul, smul_apply, smul_eq_mul] | ||
| _ = (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k * H j l := by | ||
| simp [mul_comm] |
There was a problem hiding this comment.
I think you can try to utilize simp more.
| -- unfold Jacobian entries | |
| simp only [jacobianMatrix_eq_fderiv_basis] | |
| -- decompose `H` into the standard basis | |
| have h_decomp : H = ∑ j : m, ∑ l : n, Matrix.single j l (H j l) := by | |
| simpa using (Matrix.matrix_eq_sum_single H) | |
| conv_lhs => rw [h_decomp] | |
| -- linearity through sums | |
| simp only [map_sum] | |
| -- pull out entries `(i, k)` | |
| rw [Finset.sum_apply, Finset.sum_apply] | |
| refine Finset.sum_congr rfl ?_ | |
| intro j _ | |
| rw [Finset.sum_apply, Finset.sum_apply] | |
| refine Finset.sum_congr rfl ?_ | |
| intro l _ | |
| -- rewrite `single j l (H j l)` as a scalar multiple of `single j l 1` | |
| have hs : Matrix.single j l (H j l) = (H j l) • Matrix.single j l (1 : ℝ) := by | |
| simp only [smul_single, smul_eq_mul, mul_one] | |
| -- apply `map_smul` and commute the scalar | |
| calc | |
| (fderiv ℝ F X) (Matrix.single j l (H j l)) i k | |
| = (fderiv ℝ F X) ((H j l) • Matrix.single j l (1 : ℝ)) i k := by | |
| rw [hs] | |
| _ = (H j l) * (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k := by | |
| rw [map_smul, smul_apply, smul_eq_mul] | |
| _ = (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k * H j l := by | |
| simp [mul_comm] | |
| -- decompose `H` into the standard basis | |
| have h_decomp : H = ∑ j : m, ∑ l : n, H j l • Matrix.single j l 1 := by | |
| simpa using Matrix.matrix_eq_sum_single H | |
| conv_lhs => rw [h_decomp] | |
| simp [-smul_single, Matrix.sum_apply, mul_comm] |
| @[simp] | ||
| theorem jacobianMatrix_eq_fderiv_basis | ||
| (F : Matrix m n ℝ → Matrix p q ℝ) (X : Matrix m n ℝ) | ||
| (i : p) (k : q) (j : m) (l : n) : | ||
| jacobianMatrix F X (i, k) (j, l) = | ||
| (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k := by | ||
| rfl |
There was a problem hiding this comment.
| @[simp] | |
| theorem jacobianMatrix_eq_fderiv_basis | |
| (F : Matrix m n ℝ → Matrix p q ℝ) (X : Matrix m n ℝ) | |
| (i : p) (k : q) (j : m) (l : n) : | |
| jacobianMatrix F X (i, k) (j, l) = | |
| (fderiv ℝ F X) (Matrix.single j l (1 : ℝ)) i k := by | |
| rfl | |
| @[simp] | |
| theorem jacobianMatrix_eq_fderiv_basis | |
| (F : Matrix m n ℝ → Matrix p q ℝ) (X : Matrix m n ℝ) | |
| (ik : p × q) (jl : m × n) : | |
| jacobianMatrix F X ik jl = fderiv ℝ F X (Matrix.single jl.1 jl.2 1) ik.1 ik.2 := rfl |
- The left hand side is syntactically more general when you do not assume it is applied to arguments of the form
(i, k)and applies more easily. rflas a proof is better thanby rflbecause the former proof registers the lemma as adsimplemma.
| if i = j ∧ k = l then (1 : ℝ) else 0 := by | ||
| classical | ||
| simp only [jacobianMatrix, fderiv_id, ContinuousLinearMap.coe_id', id_eq] | ||
| by_cases h : (i = j ∧ k = l) | ||
| · rcases h with ⟨rfl, rfl⟩ | ||
| simp only [Matrix.single_apply_same] | ||
| simp only [and_self, ↓reduceIte] | ||
| · have h' : ¬ (j = i ∧ l = k) := by | ||
| intro hji | ||
| apply h | ||
| exact ⟨hji.1.symm, hji.2.symm⟩ | ||
| simp only [h, Matrix.single_apply_of_ne (i := j) (j := l) (c := (1 : ℝ)) (i' := i) (j' := k) h'] | ||
| simp only [↓reduceIte] |
There was a problem hiding this comment.
| if i = j ∧ k = l then (1 : ℝ) else 0 := by | |
| classical | |
| simp only [jacobianMatrix, fderiv_id, ContinuousLinearMap.coe_id', id_eq] | |
| by_cases h : (i = j ∧ k = l) | |
| · rcases h with ⟨rfl, rfl⟩ | |
| simp only [Matrix.single_apply_same] | |
| simp only [and_self, ↓reduceIte] | |
| · have h' : ¬ (j = i ∧ l = k) := by | |
| intro hji | |
| apply h | |
| exact ⟨hji.1.symm, hji.2.symm⟩ | |
| simp only [h, Matrix.single_apply_of_ne (i := j) (j := l) (c := (1 : ℝ)) (i' := i) (j' := k) h'] | |
| simp only [↓reduceIte] | |
| if i = j ∧ k = l then 1 else 0 := by | |
| simp [Matrix.single_apply] | |
| grind |
| classical | ||
| simp only [jacobianMatrix, fderiv_fun_const, Pi.zero_apply, ContinuousLinearMap.zero_apply, | ||
| zero_apply] |
There was a problem hiding this comment.
| classical | |
| simp only [jacobianMatrix, fderiv_fun_const, Pi.zero_apply, ContinuousLinearMap.zero_apply, | |
| zero_apply] | |
| simp |
| jacobianMatrix F X (i, k) (j, l) + jacobianMatrix G X (i, k) (j, l) := by | ||
| unfold jacobianMatrix | ||
| have h_add : (fun Y => F Y + G Y) = fun Y => (F + G) Y := rfl | ||
| rw [h_add] | ||
| rw [fderiv_add hF hG] | ||
| simp only [ContinuousLinearMap.add_apply] | ||
| rfl |
There was a problem hiding this comment.
| jacobianMatrix F X (i, k) (j, l) + jacobianMatrix G X (i, k) (j, l) := by | |
| unfold jacobianMatrix | |
| have h_add : (fun Y => F Y + G Y) = fun Y => (F + G) Y := rfl | |
| rw [h_add] | |
| rw [fderiv_add hF hG] | |
| simp only [ContinuousLinearMap.add_apply] | |
| rfl | |
| jacobianMatrix F X (i, k) (j, l) + jacobianMatrix G X (i, k) (j, l) := by | |
| simp [fderiv_fun_add, *] |
| unfold jacobianMatrix | ||
| have h_smul : (fun Y => c • F Y) = fun Y => (c • F) Y := rfl | ||
| rw [h_smul] | ||
| rw [fderiv_const_smul hF] | ||
| simp only [ContinuousLinearMap.smul_apply] | ||
| rfl |
There was a problem hiding this comment.
| unfold jacobianMatrix | |
| have h_smul : (fun Y => c • F Y) = fun Y => (c • F) Y := rfl | |
| rw [h_smul] | |
| rw [fderiv_const_smul hF] | |
| simp only [ContinuousLinearMap.smul_apply] | |
| rfl | |
| simp [fderiv_fun_const_smul, *] |
This PR introduces the Jacobian matrix for matrix-valued functions
F : Matrix m n ℝ → Matrix p q ℝ.The Jacobian matrix
jacobianMatrix F Xat pointXis indexed by(p × q) × (m × n), where each entry represents the partial derivative with respect to a basis element. To handle instance-mismatch issues with matrix norms, we use local Frobenius norm instances.mkdir Analysis/Matrix/Jacobian.lean
Main definitions
jacobianMatrix F X: The Jacobian matrix at pointX, defined byjacobianMatrix F X (i, k) (j, l) = (fderiv ℝ F X (Matrix.single j l 1)) i kMain theorems
fderiv_eq_jacobian_mul: Express the Fréchet derivative as a contraction with the JacobianjacobianMatrix_comp: Chain rule for Jacobian matricesjacobianMatrix_linear,jacobianMatrix_id,jacobianMatrix_const: Basic propertiesjacobianMatrix_add,jacobianMatrix_smul: Linearity properties