4

I have a cell array which each cell is an n-by-n matrix. I want to delete the cells for which inv(cell{i}'*cell{i}) gives warning that matrix is close to singular. Thank you

fo_x86
  • 2,583
  • 1
  • 30
  • 41
Chris
  • 167
  • 5

3 Answers3

3

In general, removing elements is the easy part. If C is your array, removing cells specified by the indices in vector idx can be done by:

C(idx) = {};

Regarding your specific problem, to check if a matrix is "almost" singular or not can be done with rcond (if the result is close to zero, it's probably singular). To apply it to all cells you can use cellfun in the following way:

idx = cellfun(@(x)(rcond(x' * x) < 1e-12), C);

Adjust the threshold value to your liking. The resulting idx is a logical array with 1s at the location of singular matrices. Use idx to remove these elements from C as shown above.

Eitan T
  • 32,660
  • 14
  • 72
  • 109
1

Create a function that check for your condition:

function state = CheckElement(element)

if ([condition])
   state = 1;
else
   state = 0;
end

end

then do cellfun on all you cell array elements like the following:

indices = cellfun(@CheckElement,myCellArray);
cellArray(indices ) = [];
Sameh K. Mohamed
  • 2,323
  • 4
  • 29
  • 55
  • 1
    You don't need the `'UniformOutput', false` part when computing `indices`. You want indices to be a matrix, not a cell array. – Eitan T Jan 15 '13 at 15:26
0

Assuming you have already defined a issingular function defined you can use cellfun to get the indices of the cells that contain the matrices you want to remove.

c; % cell arry

singularIdx = cellfun((@x) issingular( inv(x' * x)), c);  %' added single quote for SO syntax

cFiltered = c(~singluarIdx);

You'll probably need to write your own function to check for singularity, for more information on that see this question: Fast method to check if a Matrix is singular? (non-invertible, det = 0)

Community
  • 1
  • 1
slayton
  • 20,123
  • 10
  • 60
  • 89
  • 1
    The `'` and `*` operators are not defined for cell arrays, so you'll trigger an error for the `c'` and `c' * c` parts. Also, I'm not sure that you actually have to compute `inv`... I think it's the `c'*c` result that can be singular. – Eitan T Jan 15 '13 at 15:31
  • @EitanT, oh yea, I totally messed that up. I actually had to wrap it in a anonymous function to get the desired behavior – slayton Jan 15 '13 at 23:07
  • I still think the `inv` is unnecessary. – Eitan T Jan 16 '13 at 07:36
  • @EitanT, yea you're probably right, I was simply echoing the original code from the OP – slayton Jan 16 '13 at 14:44
  • At first, I was doing the same thing :) – Eitan T Jan 16 '13 at 14:47