I've been trying to write some simple code to let me use physics vector notation: $\hat{x}$, $\hat{y}$, $\hat{r}$, and $\hat{\theta}$.
Unprotect[Plus, Times, Dot];
Plus[Vector[xhat1_, yhat1_, rhat1_, ϕhat1_],
Vector[xhat2_, yhat2_, rhat2_, ϕhat2_]] :=
Vector[xhat1 + xhat2, yhat1 + yhat2,
rhat1 + rhat2, ϕhat1 + ϕhat2];
Times[c_, Vector[xhat_, yhat_, rhat_, ϕhat_]] :=
Vector[c xhat, c yhat, c rhat, c ϕhat];
Dot[Vector[xhat1_, yhat1_, rhat1_, ϕhat1_],
Vector[xhat2_, yhat2_, rhat2_, ϕhat2_]] :=
xhat1 xhat2 + yhat1 yhat2 + rhat1 rhat2 + ϕhat1 ϕhat2;
Dot[scalar1_ vector1_Vector,
scalar2_ vector2_Vector] := (scalar1 vector1).(scalar2 vector2);
Protect[Plus, Times, Dot];
Format[Vector[xhat_, yhat_, rhat_, ϕhat_]] :=
DisplayForm[
xhat OverscriptBox["x", "^"] + yhat OverscriptBox["y", "^"] +
rhat OverscriptBox["r", "^"] + ϕhat OverscriptBox["ϕ",
"^"]];
Overhat[x] = Vector[1, 0, 0, 0];
Overhat[y] = Vector[0, 1, 0, 0];
Overhat[r] = Vector[0, 0, 1, 0];
Overhat[θ] = Vector[0, 0, 0, 1];
I've been having trouble getting my dot product operation to work correctly. The source of the problem is that Dot
has a higher precedence than Times
so expressions such as
Overhat[x].y Overhat[y]
(that is $\hat{x}.y \hat{y}$) evaluates as Times[Dot[Overhat[x],y],Overhat[y]]
. I don't want to evaluate Dot[Overhat[x],y]
because that would be a vector dotted with a scalar. How can I prevent Mathematica from evaluating it in this way. If I could simply tell it to give precedence to Times over Dot then it would work, but this is probably impossible. Perhaps there is some clever pattern matching stuff I can to set how the expression evaluates before Mathematica can do anything with it. Such as
Times[Dot[v1_Vector, scalar_], v2_Vector] := scalar Dot[v1, v2];
.
Unfortunately this doesn't work though.
This is the second post, the first one being How can I use a unit vector notation found in physic texts?, though it is somewhat unrelated.
**Edit: ** Mr. Wizard's solution is pretty much what I am looking for. But I found some unusual behavior that I couldn't find the explanation for. If we set $Pre twice, the second time seems to unset it:
(*First set*)
$Pre = Function[, Unevaluated[#] /. a_.b_ c_ :> a.(b c), HoldAll];
Overhat[x] = {1, 2, 3, 4, 5}; Overhat[y] = {a, b, c, d, e};
Overhat[x].y Overhat[y]
(*Evaluates as expected*)
a y + 2 b y + 3 c y + 4 d y + 5 e y
(*Second set*)
$Pre = Function[, Unevaluated[#] /. a_.b_ c_ :> a.(b c), HoldAll];
Overhat[x] = {1, 2, 3, 4, 5}; Overhat[y] = {a, b, c, d, e};
Overhat[x].y Overhat[y]
(*Evaluates as if $Pre had never been set*)
{a {1, 2, 3, 4, 5}.y, b {1, 2, 3, 4, 5}.y, c {1, 2, 3, 4, 5}.y,
d {1, 2, 3, 4, 5}.y, e {1, 2, 3, 4, 5}.y}
Even stranger is that $Pre
doesn't appear to change between sets (now going into a new notebook):
$Pre
Outputs: $Pre
Now if we set it:
$Pre = Function[, Unevaluated[#] /. a_.b_ c_ :> a.(b c), HoldAll];
Then: $Pre
Outputs: Function[Null, Unevaluated[#1] /. (a_).(b_) c_ :> a.(b c), HoldAll]
And doing the setting process again:
$Pre = Function[, Unevaluated[#] /. a_.b_ c_ :> a.(b c), HoldAll];
Then: $Pre
Outputs: Function[Null, Unevaluated[#1] /. (a_).(b_) c_ :> a.(b c), HoldAll]
So it appears to be set, but $Pre doesn't apply to this expression as (at least as I) would expect:
Overhat[x] = {1, 2, 3, 4, 5}; Overhat[y] = {a, b, c, d, e};
Overhat[x].y Overhat[y]
Outputs:
a {1, 2, 3, 4, 5}.y, b {1, 2, 3, 4, 5}.y, c {1, 2, 3, 4, 5}.y, d {1, 2, 3, 4, 5}.y, e {1, 2, 3, 4, 5}.y}
Is there some hidden feature of $Pre interacting with itself that makes it difficult to get these successive evaluations to work as expected?
**Edit 2: ** Following the advice of Mr. Wizard, here is the solution:
If[ValueQ[$Pre], , $Pre =
Function[, Unevaluated[#] /. a_. b_ . c_ d_ :> (a b).(c d),
HoldAll]];
Insert this anywhere in the above code to resolve the dot product problem.
()
to control precedence. Can you not writeOverhat[x].(y Overhat[y])
for example? $\endgroup$y Overhat[y]
to be a vector; unlike Mathematica and (my implementation of)Vector
. Also (and this is a little lazy) I wanna avoid having to use parentheses with almost all applications ofDot
. $\endgroup$Plus
,Times
andDot
is always a bad idea. $\endgroup$CenterDot
,CircleTimes
, andCirclePlus
and it would solve that problem, and I probably will in the long run. But I am restricted in what I can use as operators by the preferences, and I think the same problem will remain because I am still stuck usingTimes
for multiplication by a scalar (unless I use something wacky as the dot product operator). I'm trying to avoid using something heavy duty like theNotation
package. Theres got to be some way to tell MMA how to evaluate an expression of the listed form. $\endgroup$