I have to run a for loop based on random numbers generation and inversion of a matrix. When the matrix is singular, my code stops, throwing a SingularException() error. If this occurs at a certain iteration of the loop, how can I force the code to restart again the iteration with new numbers generation until a regular matrix is found to continue the loop until the end?
To keep it simple, suppose the following code:
res=zeros(500)
for i=1:length(res)
X=rand(100,100)
X2=transpose(X)*X
res[i]=tr(inv(X2))
end
If at iteration i the matrix X2 is singular, how can I run again iteration i until the iteration can be completed and then proceed with the loop?
Another possible option is to put the body of the loop into a function and wrap it in a try ... catch block. If an exception is found you call the function again.
So something like:
function my_inner_loop()
try
X=rand(100,100)
X2=transpose(X)*X
return tr(inv(X2))
catch
my_inner_loop()
end
end
i = 0
function my_inner_loop(;maxtries=100)
while i < maxtries
try
X=rand(100,100)
X2=transpose(X)*X
r = tr(inv(X2))
return r
catch
i += 1
my_inner_loop()
end
end
return nothing # or 0 or whatever makes sense
end
I would suggest that you do a QR decomposition of X = QR, so that X'X = R'R, use that to detect invertibility and just return Inf for singular matrices, then work with Rinv = inv(R) etc.
After posting the above I realized that there are some scoping issues with the variables. The following code might be closer to what you want for the non-math part:
function my_outerspace_loop(maxtries=100)
i = 1
result = nothing
function my_inner_loop(max)
# global i
while i < maxtries
@show i
try
X=rand(100,100)
X[1,1] < 0.1 || throw()
X2=transpose(X)*X
result = tr(inv(X2))
break
catch
println("Trying again...")
i += 1
return my_inner_loop(max)
end
end
return (result, i) # or 0 or whatever makes sense
end
my_inner_loop(maxtries)
end
In this case you would call my_outerspace_loop(n) where n is the maximum number of times you want to allow your algorithm to try to find an appropriate solution. You do not call my_inner_loop directly.