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$

2 Answers 2

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$
2
  • $\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$ Nov 18, 2018 at 0:44
  • $\begingroup$ @Anoldmaninthesea, fixed now. $\endgroup$
    – kglr
    Nov 18, 2018 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 and acknowledge you have read our privacy policy.

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