8
$\begingroup$

I want to create a n by n Identity matrix and replace the ones with n π^2. NOS is three here (it is a number). The code I have written for this doesn't work.

Kin = IdentityMatrix[NOS]

n = 1; m = 1; While[n == m && n < NOS &&  m < NOS, 
 Kin[[n, m]] -> n π^2; n++; m++]

I want

Kin[[1, 1]]== π^2
Kin[[2, 2]]==2 π^2

and so on. Could anyone help me with this please?

$\endgroup$
2
  • $\begingroup$ try Pi^2 DiagonalMatrix[Range[NOS]] $\endgroup$
    – kglr
    Jun 14, 2017 at 0:32
  • $\begingroup$ @klgr Thanks a lot, It works $\endgroup$ Jun 14, 2017 at 0:34

3 Answers 3

9
$\begingroup$

It is far faster to make the multiplication by a vector and then convert to a diagonal matrix, rather than building a full matrix and multiplying after:

DiagonalMatrix[π^2 Range[3]]

$\left( \begin{array}{ccc} \pi ^2 & 0 & 0 \\ 0 & 2 \pi ^2 & 0 \\ 0 & 0 & 3 \pi ^2 \\ \end{array} \right)$

Even faster is to build a sparse array, which is done by applying SparseArray before (inside) DiagonalMatrix. With this formulation multiplicaiton after is fast because only specified elements (the diagonal) are actually multiplied.

π^2 DiagonalMatrix[Range[1000]];                // RepeatedTiming // First
DiagonalMatrix[π^2 Range[1000]];                // RepeatedTiming // First
π^2 DiagonalMatrix[SparseArray @ Range[1000]];  // RepeatedTiming // First
0.434

0.01

0.000647

The examples above preserve the diagonals in Symbolic form. If machine reals(1) are OK:

π^2` DiagonalMatrix[Range[1000]];                // RepeatedTiming // First
DiagonalMatrix[π^2` Range[1000]];                // RepeatedTiming // First
π^2` DiagonalMatrix[SparseArray @ Range[1000]];  // RepeatedTiming // First
0.0040

0.00174

0.0000231

Reference:

$\endgroup$
3
  • $\begingroup$ Can you explain why the SparseArray[] solution is faster? $\endgroup$ Jun 14, 2017 at 4:03
  • $\begingroup$ @AnjanKumar It is a much smaller expression being created, here about 1/144 the size of the dense array. Because of the use of exact π^2 the array cannot be packed (in the plain case), so fast library operations cannot be used. π^2` DiagonalMatrix[Range[1000]]; (note the backtick) takes only 0.00371 on my machine because everything remains packed and fast library functions are used. $\endgroup$
    – Mr.Wizard
    Jun 14, 2017 at 9:58
  • $\begingroup$ I should add the note that there is an undocumented syntax for directly producing a sparse diagonal matrix: DiagonalMatrix[π^2 Range[3], 0, 3, SparseArray] $\endgroup$ Mar 29, 2019 at 10:33
6
$\begingroup$
NOS = 3; 

π^2 DiagonalMatrix[Range[NOS]] 
π^2 Range[NOS] IdentityMatrix[NOS]
MapIndexed[π^2 #2[[1]] # &, IdentityMatrix[NOS], {2}]
ReplacePart[IdentityMatrix[NOS], {i_, i_} :> (i π^2)]
Block[{i = 1}, IdentityMatrix[NOS] /. 1 :> (π^2 i++)]

all give

{{π^2, 0, 0}, {0, 2 π^2, 0}, {0, 0, 3 π^2}}

$\endgroup$
4
$\begingroup$

here is another way using Unitize

π^2 Table[i (1 - Unitize[Range[1000] - i]), {i, 1000}]; // AbsoluteTiming 
  (* {0.552622, Null} *)

and with SparseArray alone:

π^2 SparseArray[{i_, i_} :> i , {1000, 1000}];//AbsoluteTiming
  (* {0.00134081, Null} *)

Borrowing the backtick from @Mr.Wizard significantly improves the answer

π^2` Table[i (1 - Unitize[Range[1000] - i]), {i, 1000}]; // AbsoluteTiming
(* {0.0230811, Null} *)


π^2` SparseArray[{i_, i_} :> i, {1000, 1000}]; // AbsoluteTiming
(* {0.000165618, Null} *)
$\endgroup$
3
  • $\begingroup$ Which version are you using? For the first line I get 0.43793 and for the second 0.000658. What timings do you get for the six lines in my answer, please? $\endgroup$
    – Mr.Wizard
    Jun 14, 2017 at 10:06
  • $\begingroup$ @Mr.Wizard thanks for picking it out. I think for the first one i used the timing from Range[100] rather than 1000. I just updated it $\endgroup$
    – Ali Hashmi
    Jun 14, 2017 at 10:18
  • 1
    $\begingroup$ Table just seems unnecessarily baroque and honestly I'd leave it out if I were you, but +1 for the concise SparseArray form. It's not quite as fast as DiagonalMatrix with a sparse argument but I doubt it matters. FWIW SparseArray[{i_, i_} :> i Pi^2, {1000, 1000}] also works. $\endgroup$
    – Mr.Wizard
    Jun 14, 2017 at 12:04

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.