对于尺寸未知的矩阵,有没有办法在Mathematica中进行符号矩阵代数?例如,如果我有一个MxL矩阵A和一个LxN矩阵B,我希望能够输入
A.B
让它给我一个矩阵,其元素ab[i,j]
由
Sum[a[i,l]*b[l,j],{l,1,L}]
我正在研究的问题就像这个问题,但涉及12个矩阵的乘积,包括相同的矩阵(和它的转置)重复几次。可能有可能简化得到的矩阵的值,但是在我进行代数之后,这是否可行是不可能的。这可能是我必须手工解决的问题,但如果Mathematica能够在简化代数方面提供一些帮助,那就更容易了。
答案 0 :(得分:18)
这是我早上浪费的代码[死链接删除] ......它不完整,但它基本上有效。您可以从上一个链接[死]获取笔记本,也可以复制下面的代码。
请注意,不久前在ask.sagemath上出现了类似的问题。
几乎像Sasha的解决方案,您可以使用
定义符号矩阵A = SymbolicMatrix["A", {n, k}]
表示某些字符串"A"
不必与符号A
相同。好的,这是代码:
ClearAll[SymbolicMatrix]
Options[SymbolicMatrix] = {Transpose -> False, Conjugate -> False, MatrixPower -> 1};
输入方形矩阵的简短指针(可以使其适用于不同的头部......)
SymbolicMatrix[name_String, n:_Symbol|_Integer, opts : OptionsPattern[]] := SymbolicMatrix[name, {n, n}, opts]
Transpose,Conjugate,ConjugateTranspose和Inverse下的行为
SymbolicMatrix/:Transpose[SymbolicMatrix[name_String,{m_,n_},opts:OptionsPattern[]]]:=SymbolicMatrix[name,{n,m},
Transpose->!OptionValue[SymbolicMatrix,Transpose],Sequence@@FilterRules[{opts},Except[Transpose]]]
SymbolicMatrix/:Conjugate[SymbolicMatrix[name_String,{m_,n_},opts:OptionsPattern[]]]:=SymbolicMatrix[name,{m,n},
Conjugate->!OptionValue[SymbolicMatrix,Conjugate],Sequence@@FilterRules[{opts},Except[Conjugate]]]
SymbolicMatrix/:ConjugateTranspose[A:SymbolicMatrix[name_String,{m_,n_},opts:OptionsPattern[]]]:=Conjugate[Transpose[A]]
SymbolicMatrix/:Inverse[SymbolicMatrix[name_String,{n_,n_},opts:OptionsPattern[]]]:=SymbolicMatrix[name,{n,n},
MatrixPower->-OptionValue[SymbolicMatrix,MatrixPower],Sequence@@FilterRules[{opts},Except[MatrixPower]]]
SymbolicMatrix/:(Transpose|Conjugate|ConjugateTranspose|Inverse)[eye:SymbolicMatrix[IdentityMatrix,{n_,n_}]]:=eye
组合矩阵幂(包括单位矩阵)
SymbolicMatrix/:SymbolicMatrix[a_String,{n_,n_},opt1:OptionsPattern[]].SymbolicMatrix[a_,{n_,n_},opt2:OptionsPattern[]]:=SymbolicMatrix[a,{n,n},Sequence@@FilterRules[{opt1},Except[MatrixPower]],MatrixPower->Total[OptionValue[SymbolicMatrix,#,MatrixPower]&/@{{opt1},{opt2}}]]/;FilterRules[{opt1},Except[MatrixPower]]==FilterRules[{opt2},Except[MatrixPower]]
SymbolicMatrix[a_String,{n_,n_},opts:OptionsPattern[]]:=SymbolicMatrix[IdentityMatrix,{n,n}]/;OptionValue[SymbolicMatrix,{opts},MatrixPower]===0
SymbolicMatrix/:(A:SymbolicMatrix[a_String,{n_,m_},OptionsPattern[]]).SymbolicMatrix[IdentityMatrix,{m_,m_}]:=A
SymbolicMatrix/:SymbolicMatrix[IdentityMatrix,{n_,n_}].(A:SymbolicMatrix[a_String,{n_,m_},OptionsPattern[]]):=A
使用尺寸作为工具提示进行漂亮打印。
Format[SymbolicMatrix[name_String,{m_,n_},opts:OptionsPattern[]]]:=With[{
base=If[OptionValue[SymbolicMatrix,MatrixPower]===1,
StyleBox[name,FontWeight->Bold,FontColor->Darker@Brown],
SuperscriptBox[StyleBox[name,FontWeight->Bold,FontColor->Darker@Brown],OptionValue[SymbolicMatrix,MatrixPower]]],
c=Which[
OptionValue[SymbolicMatrix,Transpose]&&OptionValue[SymbolicMatrix,Conjugate],"\[ConjugateTranspose]",
OptionValue[SymbolicMatrix,Transpose],"\[Transpose]",
OptionValue[SymbolicMatrix,Conjugate],"\[Conjugate]",
True,Null]},
Interpretation[Tooltip[DisplayForm@RowBox[{base,c}/.Null->Sequence[]],{m,n}],SymbolicMatrix[name,{m,n},opts]]]
Format[SymbolicMatrix[IdentityMatrix,{n_,n_}]]:=Interpretation[Tooltip[Style[\[ScriptCapitalI],Bold,Darker@Brown],n],SymbolicMatrix[IdentityMatrix,{n,n}]]
为Dot定义一些规则。需要扩展,以便它可以处理标量等... 如果A.B是正方形,即使A和B都不是正方形,也可以采用A.B的反转。
SymbolicMatrix::dotdims = "The dimensions of `1` and `2` are not compatible";
Unprotect[Dot]; (*Clear[Dot];*)
Dot/:(a:SymbolicMatrix[_,{_,n_},___]).(b:SymbolicMatrix[_,{m_,_},___]):=(Message[SymbolicMatrix::dotdims,HoldForm[a],HoldForm[b]];Hold[a.b])/;Not[m===n]
Dot/:Conjugate[d:Dot[A_SymbolicMatrix,B__SymbolicMatrix]]:=Map[Conjugate,d]
Dot/:(t:Transpose|ConjugateTranspose)[d:Dot[A_SymbolicMatrix,B__SymbolicMatrix]]:=Dot@@Map[t,Reverse[List@@d]]
Dot/:Inverse[HoldPattern[d:Dot[SymbolicMatrix[_,{n_,n_},___]...]]]:=Reverse@Map[Inverse,d]
A_ .(B_+C__):=A.B+A.Plus[C]
(B_+C__).A_:=B.A+Plus[C].A
Protect[Dot];
使Transpose,Conjugate和ConjugateTranspose分布在Plus。
Unprotect[Transpose, Conjugate, ConjugateTranspose];
Clear[Transpose, Conjugate, ConjugateTranspose];
Do[With[{c = c}, c[p : Plus[a_, b__]] := c /@ p], {c, {Transpose, Conjugate, ConjugateTranspose}}]
Protect[Transpose, Conjugate, ConjugateTranspose];
这是一些简单的测试/示例
现在用于处理组件扩展的代码。像Sasha的解决方案一样,我会超载Part。
Clear[SymbolicMatrixComponent]
Options[SymbolicMatrixComponent]={Conjugate->False,MatrixPower->1};
一些符号
Format[SymbolicMatrixComponent[A_String,{i_,j_},opts:OptionsPattern[]]]:=Interpretation[DisplayForm[SubsuperscriptBox[StyleBox[A,Darker@Brown],RowBox[{i,",",j}],
RowBox[{If[OptionValue[SymbolicMatrixComponent,{opts},MatrixPower]===1,Null,OptionValue[SymbolicMatrixComponent,{opts},MatrixPower]],If[OptionValue[SymbolicMatrixComponent,{opts},Conjugate],"*",Null]}/.Null->Sequence[]]]],
SymbolicMatrixComponent[A,{i,j},opts]]
提取矩阵部分和Dot
矩阵乘积的代码
需要添加检查以确保明确的求和范围都是合理的。
SymbolicMatrix/:SymbolicMatrix[A_String,{m_,n_},opts:OptionsPattern[]][[i_,j_]]:=SymbolicMatrixComponent[A,If[OptionValue[SymbolicMatrix,{opts},Transpose],Reverse,Identity]@{i,j},Sequence@@FilterRules[{opts},Options[SymbolicMatrixComponent]]]
SymbolicMatrix/:SymbolicMatrix[IdentityMatrix,{m_,n_}][[i_,j_]]:=KroneckerDelta[i,j]
Unprotect[Part]; (*Clear[Part]*)
Part/:((c___.b:SymbolicMatrix[_,{o_,n_},OptionsPattern[]]).SymbolicMatrix[A_String,{n_,m_},opts:OptionsPattern[]])[[i_,j_]]:=With[{s=Unique["i",Temporary]},Sum[(c.b)[[i,s]]SymbolicMatrixComponent[A,If[OptionValue[SymbolicMatrix,{opts},Transpose],Reverse,Identity]@{s,j},Sequence @@ FilterRules[{opts}, Options[SymbolicMatrixComponent]]],{s,n}]]
Part/:(a_+b_)[[i_,j_]]:=a[[i,j]]+b[[i,j]]/;!And@@(FreeQ[#,SymbolicMatrix]&/@{a,b})
Part/:Hold[a_][[i_,j_]]:=Hold[a[[i,j]]]/;!FreeQ[a,SymbolicMatrix]
Protect[Part];
一些例子:
答案 1 :(得分:7)
我不确定这是否真的非常有用,但它可能是一个开始:
ClearAll[SymbolicMatrix]
SymbolicMatrix /: Transpose[SymbolicMatrix[a_, {m_, n_}]] :=
SymbolicMatrix[Evaluate[a[#2, #1]] & , {n, m}]
SymbolicMatrix /:
SymbolicMatrix[a_, {m_, n_}] . SymbolicMatrix[b_, {n_, p_}] :=
With[{s = Unique[\[FormalI], Temporary]},
SymbolicMatrix[Function[{\[FormalN], \[FormalM]},
Evaluate[Sum[a[\[FormalN], s]*b[s, \[FormalM]], {s, 1, n}]]], {m,
p}]]
SymbolicMatrix /: SymbolicMatrix[a_, {m_, n_}][[i_, j_]] := a[i, j]
In[109]:= amat = SymbolicMatrix[a, {n, k}];
bmat = SymbolicMatrix[b, {k, k}];
评估矩阵元素:
In[111]:= (amat . bmat . Transpose[amat])[[i, j]]
Out[111]= Sum[
a[j, \[FormalI]$1485]*
Sum[a[i, \[FormalI]$1464]*
b[\[FormalI]$1464, \[FormalI]$1485], {\[FormalI]$1464, 1, k}],
{\[FormalI]$1485, 1, k}]
答案 2 :(得分:2)
如果您愿意从Mathematica切换到Python,您需要的功能在SymPy的开发分支中。它应该在0.72版本中。
In [1]: from sympy import *
In [2]: X = MatrixSymbol('X', 2,3)
In [3]: Y = MatrixSymbol('Y', 3,3)
In [4]: X*Y*X.T
Out[4]: X⋅Y⋅X'
In [5]: (X*Y*X.T)[0,1]
Out[5]:
X₀₀⋅(X₁₀⋅Y₀₀ + X₁₁⋅Y₀₁ + X₁₂⋅Y₀₂) + X₀₁⋅(X₁₀⋅Y₁₀ + X₁₁⋅Y₁₁ + X₁₂⋅Y₁₂) + X₀₂⋅(X₁₀⋅Y₂₀ + X₁₁⋅Y₂₁ + X₁₂⋅Y₂₂)
这些纯粹的符号对象也可以使用明确定义的矩阵的所有标准矩阵算法
In [14]: X = MatrixSymbol('X', 2,2)
In [14]: X.as_explicit().det()
Out[14]: X₀₀⋅X₁₁ - X₀₁⋅X₁₀
符号形状的矩阵也是可行的
In [7]: n,m,k = symbols('n,m,k')
In [8]: X = MatrixSymbol('X', n,m)
In [9]: Y = MatrixSymbol('Y', m,k)
In [10]: (X*Y)[3,4]
Out[10]:
m - 1
___
╲
╲ X(3, k)⋅Y(k, 4)
╱
╱
‾‾‾
k = 0
答案 3 :(得分:0)
我使用这种方法:
SymbolicMatrix[symbol_String, m_Integer, n_Integer] := Table[
ToExpression[symbol <> ToString[i] <> ToString[j]],
{i, 1, m}, {j, 1, n}
];
SymbolicMatrix[symbol_Symbol, m_Integer, n_Integer] := SymbolicMatrix[ToString[symbol], m, n];
SymbolicMatrix[symbol_, m_Integer] := SymbolicMatrix[symbol, m, 1];
当调用A = SymbolicMatrix["a", 2, 3];
或A = SymbolicMatrix[a, 2, 3];
时,会创建矩阵
{{a11, a12, a13}, {a21, a22, a23}}
因此,它会创建m
x n
符号,但我发现它们具有描述性,而且整个内容都很容易使用(至少对我而言)。
答案 4 :(得分:0)
您可以使用NCAlgebra。例如:
MM = 3
LL = 2
NN = 3
AA = Table[Subscript[a, i, j], {i, 1, MM}, {j, 1, LL}]
BB = Table[Subscript[b, i, j], {i, 1, LL}, {j, 1, NN}]
将使用非交换条目$ a_ {i,j} $和$ b_ {i,j} $定义符号矩阵AA
和BB
。这些可以被操纵并产生您正在寻找的结果。例如:
NCDot[AA, BB]
将使用**
,
AA ** BB // NCMatrixExpand
也会这样做,
tp[AA ** BB] // NCMatrixExpand
将使用tp
进行转置。