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$ 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.
    Sep 26, 2016 at 15:13
  • $\begingroup$ You probably have old definitions. Try quitting the kernel and starting again. $\endgroup$
    – bill s
    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
    Oct 28, 2015 at 1:01
  • $\begingroup$ @Alex: 1/myvector? $\endgroup$
    – Verbeia
    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$ Oct 28, 2015 at 1:33

Your Answer

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

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