1function Problem = SJget (matrix, SJ_Index, refresh_mat)
2%SJGET loads a matrix from the SJSU Singular Matrix Collection.
3%
4%   Problem = SJget(matrix) loads a matrix from the SJSU Singular matrix collection,
5%   specified as either a number (1 to the # of matrices in the collection) or
6%   as a string (the name of the matrix).  With no input parameters, index=SJget
7%   returns an index of matrices in the collection.  A local copy of the matrix
8%   is saved (be aware that as of August 2008 the entire collection is over 1GB
9%   in size).  If no input or output arguments are provided, the index is
10%   printed.  With a 2nd parameter (Problem = SJget (matrix, index)), the index
11%   file is not loaded.  This is faster if you are loading lots of matrices.
12%   Also SJget('refresh') will force downloading the index file from the
13%   SJsingular web site. SJget(matrix,'refresh') or
14%   SJget(matrix,index,'refresh') will force downloading Problem
15%   matrix from the SJsingular web site, rather than using a
16%   locally stored copy.
17%
18%   Examples:
19%     index = SJget ;                     % loads index of the collection
20%     index = SJget ('refresh') ;         % forces download of new index
21%                                         % from the SJsingular web site
22%     Problem = SJget (6)                 % get the 6th problem
23%     Problem = SJget ('HB/ash292')       % get a problem by name
24%     Problem = SJget (6,'refresh')       % forces download of 6th problem
25%                                         % from the SJSingular web site
26%     Problem = SJget (6, index)          % alternatives to get problems
27%     Problem = SJget ('HB/ash292', index)
28%     Problem = SJget (6,index,'refresh') % forces download of 6th problem
29%                                         % from the SJsingular web site
30%
31%   or one can search using SJget:
32%
33%   index = SJget ;     % get index of the SJSU Singular Matrix Collection
34%   ids = find (1000 <= index.numrank & index.numrank <= 1200) ;
35%   [ignore, i] = sort (index.numrank (ids)) ;    %sort by numrank
36%   ids = ids (i) ;
37%   for id = ids
38%      Prob = SJget (id);        % Prob is a struct (matrix, name, meta-data, ...)
39%	   A = Prob.A ;              % A has numerical rank between 1000 and 1200
40%	   disp([index.numrank(id), size(A)]) % list the numerical rank and
41%                                % size of A
42%   end
43
44%   See also SJgrep, SJweb, SJget_example, SJget_defaults, urlwrite.
45
46%   Derived from the ssget toolbox on March 18, 2008, modified 2/1/2009
47%   Copyright 2007, Tim Davis, University of Florida.
48
49%-------------------------------------------------------------------------------
50% get the parameter settings
51%-------------------------------------------------------------------------------
52
53params = SJget_defaults ;
54indexfile = sprintf ('%sSJ_Index.mat', params.dir) ;
55indexurl = sprintf ('%s/SJ_Index.mat', params.url) ;
56
57%-------------------------------------------------------------------------------
58% get the index file (download a new one if necessary)
59%-------------------------------------------------------------------------------
60
61refresh_matrix = 0;
62if nargin >= 2
63    % SJget (..,'refresh') forces downloading matrix .. from the web
64    if (ischar (SJ_Index))
65        if (strcmp(SJ_Index, 'refresh'))
66            refresh_matrix = 1;
67        end
68    end
69end
70if nargin == 3
71    % SJget (..,..,'refresh') forces downloading matrix .. from the web
72    if (ischar (refresh_mat))
73        if (strcmp (refresh_mat, 'refresh'))
74            refresh_matrix = 1 ;
75        end
76    end
77end
78
79refresh = 0 ;
80if nargin == 0
81    % if the user passed in a zero or no argument at all, return the index file
82    matrix = 0 ;
83else
84    % SJget ('refresh') downloads the latest index file from the web
85    if (ischar (matrix))
86        if (strcmp (matrix, 'refresh'))
87            matrix = 0 ;
88            refresh = 1 ;
89        end
90    end
91end
92
93if (~refresh)
94    try
95        % load the existing index file
96        if (nargin < 2 )
97        load (indexfile) ;
98        end
99        if (nargin == 2 && refresh_matrix == 1)
100            load (indexfile) ;
101        end
102        % see if the index file is old; if so, download a fresh copy
103        refresh = (SJ_Index.DownloadTimeStamp + params.refresh < now) ;
104    catch
105        % oops, no index file.  download it.
106        refresh = 1 ;
107    end
108end
109
110if (refresh)
111    % a new SJ_Index.mat file to get access to new matrices (if any)
112    fprintf ('downloading %s\n', indexurl) ;
113    fprintf ('to %s\n', indexfile) ;
114    urlwrite (indexurl, indexfile) ;
115    load (indexfile) ;
116    SJ_Index.DownloadTimeStamp = now ;
117    save (indexfile, 'SJ_Index') ;
118end
119
120%-------------------------------------------------------------------------------
121% return the index file if requested
122%-------------------------------------------------------------------------------
123
124% if the user passed in a zero or no argument at all, return the index file
125if nargin == 0
126    matrix = 0 ;
127end
128
129if (matrix == 0)
130    if (nargout == 0)
131        % no output arguments have been passed, so print the index file
132        fprintf ('\nSJSU Singular matrix collection index:  %s\n', ...
133            SJ_Index.LastRevisionDate) ;
134        fprintf ('\nLegend:\n') ;
135        fprintf ('num. rank:    numerical rank \n') ;
136        fprintf ('struc. rank:  structural rank \n') ;
137        fprintf ('type:      real\n') ;
138        fprintf ('           complex\n') ;
139        fprintf ('           binary:  all entries are 0 or 1\n') ;
140        nmat = length (SJ_Index.nrows) ;
141        for j = 1:nmat
142            if (mod (j, 25) == 1)
143                fprintf ('\n') ;
144                fprintf ('ID   Group/Name                       nrows-by-  ncols  num. rank  struct. rank  type\n') ;
145            end
146            s = sprintf ('%s/%s', SJ_Index.Group {j}, SJ_Index.Name {j}) ;
147            fprintf ('%4d %-30s %7d-by-%7d %10d ', ...
148            j, s, SJ_Index.nrows (j), SJ_Index.ncols (j), SJ_Index.numrank (j)) ;
149            %psym = SJ_Index.pattern_symmetry (j) ;
150            %nsym = SJ_Index.numerical_symmetry (j) ;
151            fprintf('%13d ', SJ_Index.sprank (j) );
152            %if (psym < 0)
153            %    fprintf ('  -  ') ;
154            %else
155            %    fprintf (' %4.2f', psym) ;
156            %end
157            %if (nsym < 0)
158            %    fprintf ('  -  ') ;
159            %else
160            %    fprintf (' %4.2f', nsym) ;
161            %end
162            if (SJ_Index.isBinary (j))
163                fprintf (' binary\n') ;
164            elseif (~SJ_Index.isReal (j))
165                fprintf (' complex\n') ;
166            else
167                fprintf (' real\n') ;
168            end
169        end
170    else
171        Problem = SJ_Index ;
172    end
173    return ;
174end
175
176%-------------------------------------------------------------------------------
177% determine if the matrix parameter is a matrix index or name
178%-------------------------------------------------------------------------------
179
180[group matrix id] = SJget_lookup (matrix, SJ_Index) ;
181
182if (id == 0)
183    error ('invalid matrix') ;
184end
185
186%-------------------------------------------------------------------------------
187% download the matrix (if needed) and load it into MATLAB
188
189matdir = sprintf ('%s%s%s%s.mat', params.dir, group) ;
190matfile = sprintf ('%s%s%s.mat', matdir, filesep, matrix) ;
191maturl = sprintf ('%s/%s/%s.mat', params.url, group, matrix) ;
192
193if (~exist (matdir, 'dir'))
194    mkdir (matdir) ;
195end
196
197if (exist (matfile, 'file') && refresh_matrix == 0)
198    load (matfile)
199else
200    fprintf ('downloading %s\n', maturl) ;
201    fprintf ('to %s\n', matfile) ;
202    urlwrite (maturl, matfile) ;
203    load (matfile)
204    save (matfile, 'Problem') ;
205end
206