2
$\begingroup$

I'm trying to substitute the main diagonal elements when their value is less or equal to zero. I've tried the following:

testmat = {{0, 1, 3}, {2, 0, 0}, {2, 4, 1}};
ReplacePart[testmat, {i_, i_} -> $MachineEpsilon /; # <= 0 &]

This doesn't work. I've also used

ReplacePart[testmat, Position[testmat, # <= 0 &]-> $MachineEpsilon]

but doesn't work either. I've always had a bit a of trouble with patterns and rules. Any good bibliography recommendation is welcome...

$\endgroup$
1
$\begingroup$
ReplacePart[testmat, {i_, i_} /; testmat[[i, i]] <= 0 :> $MachineEpsilon]

{{2.220446049250313*^-16, 1, 3}, {2, 2.220446049250313*^-16, 0}, {2, 4, 1}}

Also

ReplacePart[testmat, 
  Select[#[[1]] == #[[2]] &]@Position[testmat, _?(# <= 0 &)] :> $MachineEpsilon]
MapIndexed[If[Equal @@ #2 && # <= 0, $MachineEpsilon, #] &, testmat, {2}]

same result

$\endgroup$
  • $\begingroup$ thanks for the answer. However, I don't get why the second line of code would give the same result... Where is the check of the pattern {i_,i_}? $\endgroup$ – An old man in the sea. Nov 18 '18 at 0:44
  • $\begingroup$ @Anoldmaninthesea, fixed now. $\endgroup$ – kglr Nov 18 '18 at 1:06
0
$\begingroup$

The same with While and If - less elegant but perhaps easier to read. For your toy matrix, maxi the numbers of rows (columns), i the first column and sth the value you want to replace in the diagonal,

testmat = {{0, 1, 3}, {2, 0, 0}, {2, 4, 1}};
maxi = 3;
i = 1;
sth = 10;

Then

While[i < maxi + 1, 
If[testmat[[i, i]] <= 0, 
testmat = ReplacePart[testmat, {i, i} -> sth],]; i++]

Output is

{{10, 1, 3}, {2, 10, 0}, {2, 4, 1}}

$\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.