2
$\begingroup$

I want to make a table to get a nbyn matrix. However, the diagonal are divided by zero. For example:

n = 5;
Table[1/(Sin[i] - Sin[j]), {i, 1., n}, {j, 1, n}]

I can use IF statement, however, is there any more elegant way to set diagonal elements to zero or any other default value?

One solution is, if the matrix is symmetric:

m = Table[0,{i,1,n},{j,1,n}];
Table[m[[i,j]] = 1/(Sin[i] - Sin[j]), {i, 1., n-1}, {j, i+1, n}]
$\endgroup$
  • 1
    $\begingroup$ The last Table in the post should be a Do :) $\endgroup$ – Marius Ladegård Meyer May 22 '16 at 19:46
  • 3
    $\begingroup$ Cheating: Table[(1 - KroneckerDelta[i, j])/(Sin[i] - Sin[j] + KroneckerDelta[i, j]), {i, 5}, {j, 5}]. $\endgroup$ – J. M. will be back soon May 22 '16 at 19:52
  • $\begingroup$ @MariusLadegårdMeyer Will there be some problem in performance if I use Table? $\endgroup$ – MOON May 22 '16 at 20:45
  • $\begingroup$ Probably not, but conseptually you are not making a table, you are just looping and modifying an already created table. $\endgroup$ – Marius Ladegård Meyer May 22 '16 at 20:49
  • $\begingroup$ @J.M. That is nice! I would multiply the kronecker delta by I to prevent the denumerator becomes zero accidentally. $\endgroup$ – MOON May 23 '16 at 9:37
5
$\begingroup$
Normal[SparseArray[{{i_, j_} /; j != i :> 1/(Sin[i] - Sin[j])}, {5, 
   5}]]

Non-zero diagonal, e.g. Pi:

Normal[SparseArray[{{i_,i_} -> Pi, {i_, j_} /; j != i :> 1/(Sin[i] - Sin[j])}, {5, 5}]]
$\endgroup$
4
$\begingroup$

I would prefer to use Array over SparseArray or Table here, because this matrix isn't really sparse and you are indexing over consecutive integers.

For example, if you're okay with non-Ifconditional forms, I would use Array together with Piecewise as follows:

f[i_, j_] := Piecewise[{{0, i == j}, {1/(Sin[i] - Sin[j]), True}}];
m1 = Array[f, {5, 5}]

When there are only two cases though (e.g., i==j or i!=j), I would personally use an If statement together with Array like this one-liner:

m2 = Array[If[#1==#2, 0, 1/(Sin[#1] - Sin[#2])]&, {5, 5}]
$\endgroup$
3
$\begingroup$

Update: Timings

ClearAll[f1, f2, f3, f4]
f1 = Block[{Power}, Power[0. | 0, -1] = #; 
    Table[1/(Sin[i] - Sin[j]), {i, 1, #2}, {j, 1, #2}]] &;
f2 = With[{v = #, n = #2}, Array[If[#1 == #2, v, 1/(Sin[#1] - Sin[#2])] &, 
      {n, n}]] &; (* Rashid's answer*)
f3 = SparseArray[{{i_, j_} /; j != i :> 
      1/(Sin[i] - Sin[j])}, {#2, #2}, #] &; (* a variant of Marius' answer *)
f4 = SparseArray[{{i_, i_} -> #, {i_, j_} /; j != i :> 
      1/(Sin[i] - Sin[j])}, {#2, #2}] &; (* Marius's answer *)

Equal @@ (#[Pi, 5] & /@ {f1, f2, f3, f4})

True

n = 300;
{HoldForm[#], First[AbsoluteTiming[#[Pi, n]]]} & /@ {f1, f2, f3, 
   f4} // Grid

Mathematica graphics

Original post:

Temporarily re-define Power[0,-1] as a:

Block[{Power}, Power[0.|0, -1] = a; Table[1/(Sin[i] - Sin[j]), {i, 1., 5}, {j, 1, 5}]]

Mathematica graphics

$\endgroup$
  • $\begingroup$ Thanks for the timing tests! That's a great idea. I'll definitely add that to my answers in the future. $\endgroup$ – Rashid May 24 '16 at 15:38
0
$\begingroup$

This is a different approach, that seems to be very fast

n = 5;
u = Sin[Range[n]] // N;
(Join[1/(u[[#]] - u[[1;;# - 1]]), {a}, 1/(u[[#]] - u[[# + 1;;]])])& /@ Range[n]
$\endgroup$

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.