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$
1
  • 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$ Commented Oct 28, 2015 at 0:35

2 Answers 2

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$
2
  • $\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.
    Commented Sep 26, 2016 at 15:13
  • $\begingroup$ You probably have old definitions. Try quitting the kernel and starting again. $\endgroup$
    – bill s
    Commented Sep 26, 2016 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$
3
  • $\begingroup$ Thanks. What about reciprocating each element of a vector, is there a specific command for that as well? $\endgroup$
    – Alex
    Commented Oct 28, 2015 at 1:01
  • $\begingroup$ @Alex: 1/myvector? $\endgroup$
    – Verbeia
    Commented Oct 28, 2015 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$ Commented Oct 28, 2015 at 1:33

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.