1
$\begingroup$

I have a matrix $A=\{a_{ij}\}$ of dimensions $n$ rows by $m$ columns, and I would like to multiply each row of the matrix by a constant $b_i$, $i=1,\ldots,n$, and store the result in the same variable. In linear-algebra speak, I basically would like to do $A=\mathrm{diag}(b_1,\ldots,b_n) A$. However, I would like to avoid having to create a diagonal matrix off the vector $(b_1,\ldots,b_n)$, because $n$ is large and I wouldn't want to use any more RAM. Is there a different and less memory demanding way to do $A=\mathrm{diag}(b_1,\ldots,b_n) A$?

My approach is to go over the rows of $A$ and multiply each by the respective element of the vector $(b_1,\ldots,b_n)$. May be there is a more elegant way to do this? By "elegant" I mean faster yet not too memory-demanding.

m = 3;
n = 5;
A = Table[RandomInteger[{0, 5}], {i, m}, {j, n}];
b = Table[RandomInteger[{5, 10}], {i, m}];
A
Print[b];

(* Standard Linear-Algebraic Solution *)
b=DiagonalMatrix[b];
cc=Dot[b,A];
cc

(* Less memory demanding solution *)
For[i = 1, i <= m, i += 1,
  A[[i, All]] = b[[i]]*A[[i, All]];
  ];
A
$\endgroup$
  • 2
    $\begingroup$ Use a SparseArray[] for the diagonal matrix: SparseArray[Band[{1, 1}] -> b].A. However, due to listability, even a Hadamard product suffices: b A. $\endgroup$ – J. M. will be back soon Oct 28 '15 at 0:35
4
$\begingroup$

This is also a kind of inner product, hence:

amat = Array[a, {3, 5}];
bvec = Array[b, 3];
ans = Transpose[Inner[Times, bvec, amat, List]]
MatrixForm[ans]

enter image description here

Or, numerically:

amat = RandomInteger[{-5, 5}, {3, 5}];
bvec = RandomInteger[{-5, 5}, 3];
ans = Transpose[Inner[Times, bvec, amat, List]];
MatrixForm[ans]

enter image description here

$\endgroup$
  • $\begingroup$ Good answer. But, I just wanted to know that if I want multiplication e.g. a[1,1].b[1]. I have a[1,1]=2 and b[1]=2, then a[1,1].b[1]=4. But I am getting in my case where b[1]-> a[1][1], as a[1][1]a[1][1]. No multiplication but like tensor product. $\endgroup$ – L.K. Sep 26 '16 at 15:13
  • $\begingroup$ You probably have old definitions. Try quitting the kernel and starting again. $\endgroup$ – bill s Sep 26 '16 at 16:30
5
$\begingroup$

Oh, yes, there is a more elegant way!

Mathematica does element-by-element multiplication.

I think this does what you want:

A = Array[a, {3, 5}]

 (* {{a[1, 1], a[1, 2], a[1, 3], a[1, 4], a[1, 5]}, {a[2, 1], 
  a[2, 2], a[2, 3], a[2, 4], a[2, 5]}, {a[3, 1], a[3, 2], a[3, 3], 
  a[3, 4], a[3, 5]}} *)

 bvec = Array[b, {3}]

 (* {b[1], b[2], b[3]} *)

 bvec * A

 (* {{a[1, 1] b[1], a[1, 2] b[1], a[1, 3] b[1], a[1, 4] b[1], 
  a[1, 5] b[1]}, {a[2, 1] b[2], a[2, 2] b[2], a[2, 3] b[2], 
  a[2, 4] b[2], a[2, 5] b[2]}, {a[3, 1] b[3], a[3, 2] b[3], 
  a[3, 3] b[3], a[3, 4] b[3], a[3, 5] b[3]}} *)

I have used symbolic quantities in the test vector and matrix so you can see what is going on.

As a general rule, if you have a nested For loop in Mathematica, you are missing something about its capabilities.

$\endgroup$
  • $\begingroup$ Thanks. What about reciprocating each element of a vector, is there a specific command for that as well? $\endgroup$ – Alex Oct 28 '15 at 1:01
  • $\begingroup$ @Alex: 1/myvector? $\endgroup$ – Verbeia Oct 28 '15 at 1:22
  • $\begingroup$ @Alex: all the basic arithmetic functions, and most of the mathematical functions, are Listable, which lets you avoid having to construct elementwise loops. $\endgroup$ – J. M. will be back soon Oct 28 '15 at 1:33

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.