1
$\begingroup$

Here is an example of a problem I'm having. Consider that I have defined:

omega={{p[t]},{q[t]},{r[t]}}

x={{a},{b},{c}}

R={{1,2,3},{4,5,6},{7,8,d}}

What I would like to do is the calculation:

h=(R.omega+x).x

My problem: the output I would like to get is:

h=R.omega.x+x.x

However, mathematica by default will expand everything and just give me the resulting scalar number - I do not want this. Using //HoldForm will give me just:

h=(R.omega+x).x

Which does not help either. So how do I get the output h=R.omega.x+x.x where the expression is expanded but the variables are retained, i.e. not expanded themselves?

Thanks a lot! I appreciate it.

$\endgroup$
  • $\begingroup$ If you only want the expanded expression, why do you need to Set your variables to begin with? Simply do h = Distribute[(R.omega + x).x] before the three lines where you Set them to be matrices... Then you can of course use @march's method to replace them a posteriori if you want. $\endgroup$ – Marius Ladegård Meyer Jul 20 '15 at 20:03
  • $\begingroup$ @MariusLadegårdMeyer because eventually I want to switch between the developed version (where the R, omega and x get substituted with what they really are) and the undeveloped version. What you suggest is a stupid constraint to put on a user, there must be a way. $\endgroup$ – space_voyager Jul 20 '15 at 20:37
  • $\begingroup$ Would you like to accept one of the answers below (even if it's your own)? That way, we can remove it from the unanswered list. $\endgroup$ – march Aug 20 '15 at 3:03
  • $\begingroup$ @march Done, thanks for reminding me. $\endgroup$ – space_voyager Aug 20 '15 at 16:03
6
$\begingroup$

There will be more clever answers from people who better understand Mathematica's order of evaluation and how to use Hold and such, and so I can't answer your question in exactly the way that you've phrased it, but here's how I go about doing these types of things.

First, instead of declaring the values of x, omega, and R as you've done, make a list of rules:

Clear[x, omega, R]
rules = {omega -> {p[t], q[t], r[t]
  , x -> {a, b, c}
  , R -> {{1, 2, 3}, {4, 5, 6}, {7, 8, d}}
 }

Then, your expression (R.omega+x).x evaluates to itself, because, as shown in the documentation,

When its arguments are not lists or sparse arrays, Dot remains unevaluated.

Therefore, we have to tell Mathematica to distribute the Dot through the parantheses:

h = Distribute[(R.omega+x).x]

results in

R.omega.x + x.x

Now, to replace these quantities with your defined quantities above, merely do

h /. rules

resulting in

a^2 + b^2 + c^2
  + a (p[t] + 2 q[t] + 3 r[t])
  + b (4 p[t] + 5 q[t] + 6 r[t])
  + c (7 p[t] + 8 q[t] + d r[t])

Aside on notation

Typically, you want to define both "row vectors" and "column vectors" the same in mathematica, i.e.

rowVector = {a, b, c}
columnVector = {d, e, f}

The Dot operation will understand what you want:

rowVector.columVector

results in

a*b + b*e + d*f

Of course, this is also the result of

columnVector.rowVector

so if you're interested in doing other operations, you have to use something other than Dot.

|improve this answer|||||
$\endgroup$
4
$\begingroup$

You can use Inactivate with TraditionalForm.

Inactivate[h = (R.omega + x).x] // TraditionalForm

enter image description here

Inactivate prevents the operations from executing and TraditionalForm gives the formatted output.

Hope this helps.

|improve this answer|||||
$\endgroup$
2
$\begingroup$

I like march's idea of automation but I think at the moment his updated code is not working. Perhaps this will serve the purpose:

SetAttributes[heldDistribute, HoldFirst]
heldDistribute[expr_] := 
  Unevaluated[expr] /. 
    Cases[Unevaluated[expr], x_Symbol :> (HoldPattern[x] :> Defer[x]), {-1}, 
      Heads -> False] // Distribute

Now with the question definitions in place:

heldDistribute[(R.omega + x).x]
x.x + R.omega.x
|improve this answer|||||
$\endgroup$
0
$\begingroup$

Thank you for your replies, they will be useful in the future. I found the solution to my specific problem however. One can use:

Distribute[(HoldForm[R].HoldForm[omega]+HoldForm[x]).HoldForm[x]]

Albeit cumbersome, it does the trick. To avoid it one can use @march or @MariusLadegårdMeyer solutions! Thank you.

|improve this answer|||||
$\endgroup$
0
$\begingroup$

Here's a completely different take (from my other answer, which I think justifies a separate answer) that somewhat automates the idea of using HoldForm on the variables. It works as long as you name the variables consistently. It's still not perfect, since, you need to make the List of replacements, but once that's done, you don't need to do the cumbersome thing of adding HoldForm to each Symbol in each expression that you create.

replacements = {HoldPattern[R] -> HoldForm[R], HoldPattern[x] -> HoldForm[x], HoldPattern[omega] -> HoldForm[omega]}
SetAttributes[heldDistribute, HoldFirst]
heldDistribute[expr_] := Distribute@ReleaseHold[Hold[expr] /. replacements]

Then

heldDistribute[(R.omega + x).x]

results in

x.x + R.omega.x
|improve this answer|||||
$\endgroup$
  • $\begingroup$ Your updated version does not appear to work properly, and I cannot see how it would without additional measures of expression holding. I think you should check it again. $\endgroup$ – Mr.Wizard Jan 13 '16 at 22:56
  • $\begingroup$ @Mr.Wizard. You're right. I tested it with the symbols undefined. I will roll back the changes until I have a working version (although since you have a version, I am unlikely to work on this much; we'll see). Thanks for the heads-up. $\endgroup$ – march Jan 13 '16 at 23:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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