4
votes

How do you define a special operator in Mathematica, for example a special type of additive or multiplicative operator? I did that in the past but I can't recall where I put the code. I tried defining this filled small circle operator on two matrices :

A_\[FilledSmallCircle] B_ := 
  Which[(MatrixQ[A] || VectorQ[A]) && (MatrixQ[B] || VectorQ[B]), 
   A.B, ! (MatrixQ[A] || VectorQ[A]) && (MatrixQ[B] || VectorQ[B]), 
   A@B, (MatrixQ[A] || VectorQ[A]) && ! (MatrixQ[B] || VectorQ[B]), 
   Transpose[B@Transpose[A]]];

But it does not work. What am I doing wrong?

3
The left hand side is being interpreted (if you put a space between A_ and the \[FilledSmallCircle]) as Times[\[FilledSmallCircle], Pattern[A, Blank[]], Pattern[B, Blank[]]]. You need to create an infix notation. See the various answers below. - Simon

3 Answers

5
votes

So you are trying to make an operator with an infix action. If you compare it to the built-in infix operators +, *, **, \[CircleTimes], etc... you'' see that they are all interpreted into their FullForm: Plus, Times, NonCommutativeMultiply, CircleTimes, respectively.

You should probably try to create something similar. So start with

BigDot[A_, B_] := Which[
          (MatrixQ[A] || VectorQ[A]) &&  (MatrixQ[B] || VectorQ[B]), A.B, 
         !(MatrixQ[A] || VectorQ[A]) &&  (MatrixQ[B] || VectorQ[B]), A@B, 
          (MatrixQ[A] || VectorQ[A]) && !(MatrixQ[B] || VectorQ[B]), Transpose[B@Transpose[A]],
          True, HoldForm[BigDot[A, B]]];

Note that I added the last line as a catch-all for when neither A nor B are a matrix or a vector.

Then create the infix notation part. The hard way would be to make some MakeExpression and MakeBoxes definitions. The easy way is to use the NotationPackage

Needs["Notation`"]
InfixNotation[ParsedBoxWrapper["\[FilledSmallCircle]"], BigDot]
4
votes

Try (just cut and paste this):

Needs["Notation`"]

Notation[ParsedBoxWrapper[
RowBox[{"A_", " ", "\[FilledSmallCircle]", " ", 
     "B_"}]] \[DoubleLongLeftRightArrow] ParsedBoxWrapper[
RowBox[{"Which", "[", 
RowBox[{
RowBox[{
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "A_", "]"}], "||", 
RowBox[{"VectorQ", "[", "A_", "]"}]}], ")"}], "&&", 
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "B_", "]"}], "||", 
RowBox[{"VectorQ", "[", "B_", "]"}]}], ")"}]}], ",", 
RowBox[{"A_", " ", ".", "B_"}], ",", 
RowBox[{
RowBox[{"!", 
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "A_", "]"}], "||", 
RowBox[{"VectorQ", "[", "A_", "]"}]}], ")"}]}], "&&", 
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "B_", "]"}], "||", 
RowBox[{"VectorQ", "[", "B_", "]"}]}], ")"}]}], ",", 
RowBox[{"A_", "[", "B_", "]"}], ",", 
RowBox[{
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "A_", "]"}], "||", 
RowBox[{"VectorQ", "[", "A_", "]"}]}], ")"}], "&&", 
RowBox[{"!", 
RowBox[{"(", 
RowBox[{
RowBox[{"MatrixQ", "[", "B_", "]"}], "||", 
RowBox[{"VectorQ", "[", "B_", "]"}]}], ")"}]}]}], ",", 
RowBox[{"Transpose", "[", 
RowBox[{"B_", "[", 
RowBox[{"Transpose", "[", "A_", "]"}], "]"}], "]"}]}], "]"}]]]

Now I've entered this with the Notation palette, so actually it looks like this on screen: enter image description here (the palette inserts various boxes where necessary). It just looks horrible when I cut and paste due to the explicit string representation of everything.

EDIT: That is: type "Needs["Notation"]`, causing a palette to appear. Click on the first button, whereupon this

enter image description here

appears. Inside the first yellow box type A_ \[FilledSmallCircle] B_, and in the second,

Which[(MatrixQ[A_]||VectorQ[A_])&&(MatrixQ[B_]||VectorQ[B_]),A_ .B_,!(MatrixQ[A_]||VectorQ[A_])&&(MatrixQ[B_]||VectorQ[B_]),A_[B_],(MatrixQ[A_]||VectorQ[A_])&&!(MatrixQ[B_]||VectorQ[B_]),Transpose[B_[Transpose[A_]]]]

The result looks like this enter image description here

and, when evaluated, defines what you want. Alternatively, after the Needs bit, just cut and paste what I gave above.

2
votes

Mathematica has some operators without builtin definitions like CirclePlus and CircleTimes that you can define. I'm iPhoning now so I can't check, but I assume FilledSmallCircle is just a character and not an operator. It's less trivial to define that as an operator, but you might want to check the Notation package.