function gout = matcolor(S) % SPK: This function is MATLABROOT/toolbox/matlab/funfun/private/colgroup.m % I have renamed it and copied it to a location where it is not hidden. %COLGROUP Helper function used by NUMJAC for sparse Jacobians. % This helper function is used by NUMJAC to reduce the number of function % evaluations required to compute all of the columns of a sparse Jacobian % matrix. Given a sparsity pattern matrix S, G = COLGROUP(S) returns a % column vector G consisting of a group number assigned to each column of % matrix S. Two columns may be grouped together if they do not overlap, % i.e. their dot product is zero. The number of function evaluations that % NUMJAC requires to generate a sparse Jacobian is given by % max(colgroup(S)). % % COLGROUP tries two different packings (first-fit and first-fit after % reverse colamd ordering) and returns the one that requires fewer % groups. The result may not be optimal. (Finding the smallest packing is % an NP-complete problem equivalent to K-coloring a graph.) % % See also NUMJAC, ODE15S, ODE23S, ODESET, BRUSSODE, COLAMD. % Mark W. Reichelt and Lawrence F. Shampine, 3-28-94 % Copyright 1984-2003 The MathWorks, Inc. % $Revision: 1.13.4.3 $ $Date: 2004/12/06 16:34:57 $ [m,n] = size(S); [i,j] = find(S); T = sparse(i,j,1,m,n); % Early exit in case of a full row. if any(sum(T,2) == n) gout = (1:n)'; return end TT = tril(T' * T); % First-fit packing. g = zeros(n,1); groupnum = 0; J = (1:n)'; while length(J) groupnum = groupnum + 1; g(J(1)) = groupnum; col = full(TT(:,J(1))); for k = J' if col(k) == 0 col = col + TT(:,k); g(k) = groupnum; end end J = find(g == 0); end % Form the reverse column minimum-degree ordering. p = colamd(T); p = p(n:-1:1); T = T(:,p); TT = tril(T' * T); % First-fit packing. g2 = zeros(n,1); groupnum2 = 0; J = (1:n)'; while length(J) groupnum2 = groupnum2 + 1; g2(J(1)) = groupnum2; col = full(TT(:,J(1))); for k = J' if col(k) == 0 col = col + TT(:,k); g2(k) = groupnum2; end end J = find(g2 == 0); end % Use whichever packing required fewer groups. if groupnum <= groupnum2 gout = g; else q(p) = 1:n; % invert the permutation gout = g2(q); end