Group Abstract Group Abstract

Message Boards Message Boards

A problem with List and Vector

GROUPS:
First, a=1;b=2;c=3; {a,b}+c will be {a+c,b+c}, i.e.{4,5}. This is the Distributive property of List.
Second, a={1,1}; b={1,2}; a+b will be {1+1, 1+2} i.e. {2, 3}. This is Plus between Vectors.
But the problem comes when I try to combine these two features.
a = {1, 1}; b = {1, 2}; c = {1, 2};
{a + c, b + c}
{a, b} + c
Result:
{{2, 3}, {2, 4}} (* Right *)
{{2, 2}, {3, 4}} (* Wrong *)
it seems that Mathematica interprets {a, b} as a matrix here.
How can I fix this problem?
I can fix this simple problem by Plus[#, c]&/@{a,b}
But I want a universal solution. Anyone can help?
POSTED BY: Moon Liu
Answer
10 months ago
I see no problem at all. It is all consistent behavior. It is based on element by element operation.

When you write
{a, b} + {x, y}
Then the first element "a" is added to the first element "x". Then the second element "b" is added to the second element "y".
{a + x, b + y}
This you first case, which you say is right. (simply let a=1,b=1,x=1,y=2.

Now lets look at the second case, where now "a" happend to be a list of 2 elements. No problem. The same thing will happen
{{a1, a2}, {b1, b2}} + {x, y}
Mathematica will now do the same thing. It will add "x" to the first element which happend to be {a1, a2}.  Giving
{a1 + x, a2 + x}
which I am sure you agree is correct. Next it go to the next element, and adds "y" to {b1, b2} giving {b1 + y, b2 + y} so you end up with
{{a1 + x, a2 + x}, {b1 + y, b2 + y}}
Replace a1=1, a2=1,b1=1,b2=2,x=1,x=2 and you get the second case.

And if you had 3 elements in the list, the same thing will happen. Each term is added to each other term, one by one.
{{a1, a2, a2}, {b1, b2, b3}} + {x, y}
(*   {    {a1 + x, a2 + x, a2 + x}    ,      {b1 + y, b2 + y, b3 + y}    }  *)
POSTED BY: Nasser
Answer
10 months ago
Thanks for your reply. You're right.
{{a1, a2}, {b1, b2}} + {x, y} == {{a1 + x, a2 + x}, {b1 + y, b2 + y}}
and this is indeed a consistent behavior.
However, in my case, a different task is concerned.
{{a1, a2}, {b1, b2}} [op] {x, y} == {{a1 + x, a2 + y}, {b1 + x, b2 + y}}
How can I deal with it? Which is the right ?

More precisely, in the first caseMathematica regards {a1, a2} and x in the same level.
In my case, however, I want {a1, a2} and {x, y} in the same level.

The following code may illustrate my problem
 OffsetPoint[a_, b_] := a + b;
 a = {1, 1}; b = {1, 2}; c = {1, 2};
 A = OffsetPoint[a, c]
 B = OffsetPoint[b, c]
 {A, B} = OffsetPoint[{a, b}, c]; (* I just want to simplify my code here *)
 A
 B
 (* Result: *)
 {2, 3}
{2, 4}
{2, 2}(* But I got wrong answer here *)
{3, 4}
POSTED BY: Moon Liu
Answer
10 months ago
Not sure if this is exactly what you're looking for, but you can use Thread:

a = {1, 1}; b = {1, 2}; c = {1, 2};
Thread[{a, b} + c]
Answer
10 months ago
Thanks for your reply. I've tried Thread, but it seems not to be the answer.
a = {a1, a2}; b = {b1, b2}; c = {c1, c2};

Thread[{a, b} + c]
(*
Result:
{{a1 + c1, b1 + c2}, {a2 + c1, b2 + c2}}
But I want {{a1 + c1, a2 + c2}, {b1 + c1, b2 + c2}}
*)

Actually the closest answer I've tried is Table.
 a = {a1, a2}; b = {b1, b2}; c = {c1, c2};
 ans1 = Table[Plus[x, y], {x, {a}}, {y, {c}}]   (* First discrepancy: apparently listed input {a,b} needs curly braces, but the simply input "a" ought not to need them. *)
 ans2 = Table[Plus[x, y], {x, {a, b}}, {y, {c}}]
 (*
 Result:
 {{{a1 + c1, a2 + c2}}}
 {{{a1 + c1, a2 + c2}}, {{b1 + c1, b2 + c2}}}
 One step further, Flatten is needed to get the right answer.
 *)
Flatten[ans1, 2] (* Second discrepency: flatten levels differ *)
Flatten[ans2, 1]
(*
Result:
{a1 + c1, a2 + c2}
{{a1 + c1, a2 + c2}, {b1 + c1, b2 + c2}}
*)
The reason why I don't see Table as the best answer is that, as you can see, I'm not satisfied with the discrepancy between simple input and Listed input.

I think my purpose is simple. I just want {a, b} + c always equals {a + c, b + c}. But this relation doesn't hold if a, b and c are vectors. TAT
POSTED BY: Moon Liu
Answer
10 months ago
 Clear["`*"];
 
 a = {1, 1}; b = {3, 2}; ref1 = {1, 2}; ref2 = {3, 2};
 OffsetPoint[a_, b_] := a + b;
 OffsetPointEx[a_, b_] := Module[{bool1, bool2, para1, para2, ans},
    para1 = a; para2 = b;
    bool1 = If[Depth[a] == 2, 1, 0];
    bool2 = If[Depth[b] == 2, 1, 0];
    If[bool1 == 1, para1 = {a}]; (* fix the first discrepancy *)
   If[bool2 == 1, para2 = {b}];
   ans = Table[Plus[x, y], {y, para2}, {x, para1}]; (* Notice the sequence here *)
   Flatten[ans, bool1 + bool2] (* fix the second discrepancy *)
   ];
oA = OffsetPoint[a, ref1];
oB = OffsetPoint[b, ref1];
oC = OffsetPoint[a, ref2];
oD = OffsetPoint[b, ref2];
{{oA, oB}, {oC, oD}}
OffsetPointEx[a, ref1]
OffsetPointEx[{a, b}, ref1]
OffsetPointEx[{a, b}, {ref1, ref2}]
OffsetPointEx[{a, b}, #] & /@ {ref1, ref2}
(*
Result:
{{{2, 3}, {4, 4}}, {{4, 3}, {6, 4}}}
{2, 3}
{{2, 3}, {4, 4}}
{{{2, 3}, {4, 4}}, {{4, 3}, {6, 4}}}
{{{2, 3}, {4, 4}}, {{4, 3}, {6, 4}}}
*)
I wrote this. It's right but really complicated and unpractical!
POSTED BY: Moon Liu
Answer
10 months ago
Well! Maybe Mathematica doesn't  provide the "best" way to deal with this problem. It's the user's job to come up with solution of it.
My solution: 1) MapThread; 2) Table
 Clear["`*"];
 
 a = {a1, a2}; b = {b1, b2}; ref1 = {x1, y1}; ref2 = {x2, y2};
 oA1 = Plus[a, ref1];
 oA2 = Plus[a, ref2];
 oB1 = Plus[b, ref1];
 oB2 = Plus[b, ref2];
 {{oA1, oA2}, {oB1, oB2}}
 MapThread[Plus, {{{a, a}, {b, b}}, {{ref1, ref2}, {ref1, ref2}}}]
Table[Plus[x, y], {x, {a, b}}, {y, {ref1, ref2}}]
(*
Result:
{{{a1 + x1, a2 + y1}, {a1 + x2, a2 + y2}}, {{b1 + x1, b2 + y1}, {b1 + x2, b2 + y2}}}
{{{a1 + x1, a2 + y1}, {a1 + x2, a2 + y2}}, {{b1 + x1, b2 + y1}, {b1 + x2, b2 + y2}}}
{{{a1 + x1, a2 + y1}, {a1 + x2, a2 + y2}}, {{b1 + x1, b2 + y1}, {b1 + x2, b2 + y2}}}
*)
These are my provisional solutions. For the moment, Table is the best choice.

By the way, MapThread also has its merit.
{oA1, oA2, oB1, oB2} = MapThread[Plus, {{a, a, b, b}, {ref1, ref2, ref1, ref2}}]
(*
Result:
{{a1 + x1, a2 + y1}, {a1 + x2, a2 + y2}, {b1 + x1, b2 + y1}, {b1 + x2, b2 + y2}}
*)
You don't need to Flatten the result and four points are directly assigned to variables.
With Table, you have to use Flatten or more curly braces.
{oA1, oA2, oB1, oB2} = Table[Plus[x, y], {x, {a, b}}, {y, {ref1, ref2}}]~Flatten~1
{{oA1, oA2}, {oB1, oB2}} = Table[Plus[x, y], {x, {a, b}}, {y, {ref1, ref2}}]
POSTED BY: Moon Liu
Answer
10 months ago
I think I see what you are trying to do now. Generally I would just use this:
(# + c) & /@ {a, b}
For your more expanded version, you can use this:
Plus @@@ Tuples[{{a, b}, {ref1, ref2}}]
Or 'Outer', which is the function version of 'Table' in this case:
Flatten[Outer[Plus, {a, b}, {ref1, ref2}, 1], 1]
Answer
10 months ago
Wow! Thanks you very very much! These are exactly what I want!
 a = {ax, ay}; b = {bx, by}; ref1 = {x1, y1}; ref2 = {x2, y2};
 
 Plus @@@ Tuples[{{a, b}, {ref1, ref2}}]
 Outer[Plus, {a, b}, {ref1, ref2}, 1]~Flatten~1
 (* Result:
 {{ax + x1, ay + y1}, {ax + x2, ay + y2}, {bx + x1, by + y1}, {bx + x2,
  by + y2}}
 {{ax + x1, ay + y1}, {ax + x2, ay + y2}, {bx + x1, by + y1}, {bx + x2,
  by + y2}}
*)
The combination of @@@ and Tuples is much simpler than Table. It will greatly simplify my code! emoticon
Thanks again!
POSTED BY: Moon Liu
Answer
10 months ago