3
$\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$
5
  • 1
    $\begingroup$ The last Table in the post should be a Do :) $\endgroup$ Commented May 22, 2016 at 19:46
  • 3
    $\begingroup$ Cheating: Table[(1 - KroneckerDelta[i, j])/(Sin[i] - Sin[j] + KroneckerDelta[i, j]), {i, 5}, {j, 5}]. $\endgroup$ Commented May 22, 2016 at 19:52
  • $\begingroup$ @MariusLadegårdMeyer Will there be some problem in performance if I use Table? $\endgroup$
    – MOON
    Commented May 22, 2016 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$ Commented May 22, 2016 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
    Commented May 23, 2016 at 9:37

4 Answers 4

6
$\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$
4
$\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$
1
  • $\begingroup$ Thanks for the timing tests! That's a great idea. I'll definitely add that to my answers in the future. $\endgroup$
    – Rashid
    Commented May 24, 2016 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 and acknowledge you have read our privacy policy.

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