I have come up with some BlockMatrix Algebra for Mathematica to make notations easier.
I have the following:
Needs["Notation`"];
Notation[ParsedBoxWrapper[
RowBox[{"A_", "\[CenterDot]", "B_"}]] \[DoubleLongLeftRightArrow]
ParsedBoxWrapper[
RowBox[{"BlockMultiply", "[",
RowBox[{"A_", ",", "B_"}], "]"}]]];
Notation[ParsedBoxWrapper[
SuperscriptBox["A_", "Inv"]] \[DoubleLongLeftRightArrow]
ParsedBoxWrapper[
RowBox[{"BlockInv", "[", "A_", "]"}]]];
Notation[ParsedBoxWrapper[
SuperscriptBox[
RowBox[{"(", "A_", ")"}], "T"]] \[DoubleLongLeftRightArrow]
ParsedBoxWrapper[
RowBox[{"BlockTransp", "[", "A_", "]"}]]];
And the actual matrix algebra functions:
ClearAll[BlockTransp]
(*SetAttributes[BlockTransp,OneIdentity]*)
BlockTransp[M_List] := Map[BlockTransp[#] &, Transpose[M], {2}]
BlockTransp[M__ + B__ ] := BlockTransp[M] + BlockTransp[B]
BlockTransp[a_ /; NumberQ[a]] := a;
BlockTransp[a_Scalar ] := a;
BlockTransp[a_ M__ /; NumberQ[a]] := a BlockTransp[M];
BlockTransp[a_Scalar M__] := a BlockTransp[M];
BlockTransp[BlockMultiply[x_, y_] ] :=
BlockMultiply[BlockTransp[y], BlockTransp[x]]
BlockTransp[BlockTransp[x_]] := x
ClearAll[BlockMultiply]
BlockMultiply[mats1 : {{_ ..} ..}, mats2 : {{_ ..} ..}] :=
Inner[BlockMultiply, mats1, mats2]
(*For numbers*)
BlockMultiply[a_ A_ /; NumberQ[a], B_] := a BlockMultiply[A, B]
BlockMultiply[A_ , a_ B_ /; NumberQ[a]] := a BlockMultiply[A, B]
BlockMultiply[A__, a_ /; NumberQ[a]] := a A
BlockMultiply[a_ /; NumberQ[a], A__ ] := a A
(*For scalar symbols*)
BlockMultiply[a_Scalar A_, B_] := a BlockMultiply[A, B]
BlockMultiply[A_ , a_Scalar B_ ] := a BlockMultiply[A, B]
BlockMultiply[A__, a_Scalar ] := a A
BlockMultiply[a_Scalar, A__ ] := a A
ClearAll[BlockInv]
BlockInv[mats1 : {{_ ..} ..}] := Map[BlockInv[#] &, mats1, {2}];
BlockInv[ a_ /; NumberQ[a]] := a
(*Make some formatting expression*)
Scalar /: MakeBoxes[Scalar[a_], StandardForm] :=
MakeBoxes[a, StandardForm];
I can do now some funny cool thing like:
1. Example:
2. Example:
3. Example:
4. Example:
Remark:
Of course the BlockInverse
Function is sensless in the sense that it does not really invert correctly. The input to BlockInverse
should only be a diagonal block matrix! There is a general formula for block matrices Block Inversion, but it is not implemented here for the sake of simplicity.
I have two questions which I could not come up so far:
How can I make the 3. example such that the
scalar
variable is treated like a scalar? Can I overloadNumberQ[scalar]:= ...
? Or is there a better way? [SOLVED] See the above definitions with added_Scalar
that matches any pattern with headScalar
. See example 4!How can I pretty print these things such that superfluous brackets are neglected? Is there some elegant way for the function definitions such that, associativity and non-commutativity is handled well?