12
$\begingroup$

I am doing vector analysis. I have figured out that the following expression won't be simplified in Mathematica:

Simplify[Dot[x, y] - Dot[y, x]]

I think the reason is that x and y could be matrices, so generally the operation does not commute. But for a vector, the commutation relation should hold. What I don't know is how to tell Mathematica to consider x and y to be vectors.

Also, how can I expand Cross[x + y, z] to be Cross[x, y] + Cross[y, z]? I tried to use Expand and ExpandAll but neither worked.

BTW, in Mathematica, is it possible to define a abstract row/column vector without explicitly specifying the number of entries?

$\endgroup$
0

4 Answers 4

14
$\begingroup$

Here is a way to do all the things you asked for automatically, independently of Mathematica version. The approach relies on a special symbol to identify when we're dealing with a vector: Instead of using things like x, y etc. for vectors, the convention now is that vectors are written as vec[x], vec[y], etc.

You could also define the wrapper OverVector[x] for this purpose because it displays as $\vec{x}$. But for this post I want to keep it simple, and the arrows wouldn't display easily in the source code below.

ClearAll[scalarProduct, vec]; 
SetAttributes[scalarProduct, {Orderless}]
vec /: Dot[vec[x_], vec[y_]] := scalarProduct[vec[x], vec[y]]
vec /: Cross[vec[x_], HoldPattern[Plus[y__]]] := 
 Map[Cross[vec[x], #] &, Plus[y]]
vec /: Cross[HoldPattern[Plus[y__]], vec[x_]] := 
 Map[Cross[#, vec[x]] &, Plus[y]]
scalarProduct /: MakeBoxes[scalarProduct[x_, y_], _] := 
 RowBox[{ToBoxes[x], ".", ToBoxes[y]}]

vec[x].vec[y]

(* ==> vec[x].vec[y] *)

vec[x].vec[y] == vec[y].vec[x]

(* ==> True *)

Cross[vec[x], vec[a] + vec[b]]

(* ==> vec[x]\[Cross]vec[a] + vec[x]\[Cross]vec[b] *)

Cross[vec[a] + vec[b], vec[x]]

(* ==> vec[a]\[Cross]vec[x] + vec[b]\[Cross]vec[x] *)

For the Dot product, I defined the behavior of vec such that it gets evaluated as a new function scalarProduct whose only algebraic property is that it's Orderless as you were expecting for the dot product of vectors. Of course this is only true for Euclidean dot products, so this assumption is implicit here. For more information on how this definition works, look up TagSetDelayed.

In addition, scalarProduct is given a customized display format by defining that it should again display as if it were a dot product when it appears in the low-level formatting function MakeBoxes.

For the distributive property of the cross product, I give vec the additional property that when it appears in Cross together with an expression of head Plus, the sum is expanded. Here the TagSetDelayed definitions are done for both orders, and contain a HoldPattern to prevent Plus from being evaluated too early in the definition.

Now you may come back with many more wishes: e.g., what about multiplicative scalars in the dot or cross product, and what about matrices. However, that's a wide field that opens up a can of worms, so I would say just implement the bare minimum of features you can get away with symbolically, then proceed with a concrete working basis so that you can write vectors as lists instead.

Another approach would be to define a new symbol for a custom dot product. That is done in this question.

Using OverVector

As mentioned above, you can replace vec by Overvector everywhere in the above source code, to get a better formatted result. Assuming you have done that (I won't bother to repeat the definitions with that change), here are some examples:

formatted

To enter these vector expressions, refer to the Basic Math assistant palette. The cross product can be entered as EsccrossEsc.

Another thing you asked for is to use the antisymmetry of the cross product in simplifications. That's actually done already if you invoke FullSimplify:

antisymmetry

$\endgroup$
5
  • $\begingroup$ Yes, the definition of new operator looks good. But it is not that convenient to use additional head. I am looking for a vector operators to simply some complicate expression involving many vectors. Is that possible to redefine +, -, . and x so don't have to use something like Plus? $\endgroup$ Commented Mar 14, 2013 at 4:00
  • $\begingroup$ Sorry, I used Plus only because that was what I was thinking about while writing the definitions. Of course you can actually use +` and - with this setup. No modifications needed at all. I also mentioned you can get a simpler format using OverVector, and illustrated that in an update to the answer. As to redefining + etc.: it's not necessary, so don't do it. $\endgroup$
    – Jens
    Commented Mar 14, 2013 at 4:28
  • $\begingroup$ that's amazing. I never know that we can use mathematica in that way, I did learn something today. Thanks. $\endgroup$ Commented Mar 14, 2013 at 4:35
  • $\begingroup$ I find a new problem of using this definition, if I try to Cross[OverVector[x], 2*OverVector[y]] + Cross[OverVector[y], 2*OverVector[x]] but it is not zero $\endgroup$ Commented Apr 16, 2013 at 22:58
  • 1
    $\begingroup$ I already anticipated this comment in my answer, and mentioned that it opens up a wide field of additional definitions one could add. I may come back to that when I have time. $\endgroup$
    – Jens
    Commented Apr 16, 2013 at 23:26
13
$\begingroup$

If you have Mathematica Version 9, you can use Vectors and TensorReduce:

Assuming[(x | y) \[Element] Vectors[n] , TensorReduce[Dot[x, y] - Dot[y, x]]]
(* 0 *)
TensorReduce[Dot[x, y] - Dot[y, x], Assumptions -> (x | y) \[Element] Vectors[n]]
(* 0 *)
TensorReduce[Cross[x + y, z],  Assumptions -> (x | y | z) \[Element] Vectors[n]]
(* x\[Cross]z + y\[Cross]z *)
Distribute[Cross[x + y, z]] (* this should work in all previous versions *)
(* x\[Cross]z + y\[Cross]z *)
$\endgroup$
4
  • $\begingroup$ thanks, it works. But what about the first one, is that possible to define an abstract row/column vector so x.y-y.x will get zero? $\endgroup$ Commented Mar 13, 2013 at 3:11
  • $\begingroup$ Presumably these solutions are for version 9 and later, when TensorReduce and Vectors were introduced. $\endgroup$
    – whuber
    Commented Mar 13, 2013 at 4:42
  • $\begingroup$ @whuber, thank you. I updated with a note that TensorReduce and Vectors are version-9 functions. $\endgroup$
    – kglr
    Commented Mar 13, 2013 at 6:15
  • $\begingroup$ Thanks. Oh, I just saw that it only works on version 9 not my version 8 :( $\endgroup$ Commented Mar 13, 2013 at 6:37
2
$\begingroup$
$Assumptions = (x | y) ∈ Vectors[d, Complexes]
Dot[x, y] - Dot[y, x] // TensorExpand
$\endgroup$
0
$\begingroup$

Another way to achieve this, although possibly not the best (since it can have unintended consequences), is to use

SetAttributes[Dot, Orderless];

This will make all dot products commute (even matrices). However, if you only happen to be working with vectors, then this is by far the cleanest way.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.