File: ssread.m

package info (click to toggle)
suitesparse 1%3A7.10.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 254,920 kB
  • sloc: ansic: 1,134,743; cpp: 46,133; makefile: 4,875; fortran: 2,087; java: 1,826; sh: 996; ruby: 725; python: 495; asm: 371; sed: 166; awk: 44
file content (417 lines) | stat: -rw-r--r-- 13,068 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
function Problem = ssread (directory, tmp)
%SSREAD read a Problem in Matrix Market or Rutherford/Boeing format
% containing a set of files created by sswrite, in either Matrix Market or
% Rutherford/Boeing format. See sswrite for a description of the Problem struct.
%
% Usage: Problem = ssread (directory)
%
% Example:
%
%   load west0479
%   clear Problem
%   Problem.name = 'HB/west0479' ;
%   Problem.title = '8 STAGE COLUMN SECTION, ALL SECTIONS RIGOROUS (CHEM.ENG.)';
%   Problem.A = west0479 ;
%   Problem.id = 267 ;          % the id number of west0479 in the collection
%   Problem.date = '1983' ;
%   Problem.author = 'A. Westerberg' ;
%   Problem.ed = 'I. Duff, R. Grimes, J. Lewis'
%   Problem.kind = 'chemical process simulation problem' ;
%   sswrite (Problem, 'RB/', '') ;
%   Prob3 = ssread ('RB/HB/west0479')
%   isequal (Problem, Prob3)
%
% This part of the example requires CHOLMOD, for the mread function:
%
%   sswrite (Problem, 'MM/') ;
%   Prob2 = ssread ('MM/HB/west0479')
%   isequal (Problem, Prob2)
%
% You can also compare this Problem with the version in the SuiteSparse Matrix
% Collection, with ssget(267) or ssget('HB/west0479').  Note that this includes
% the 22 explicit zero entries present in the west0479 Harwell/Boeing matrix,
% but not included in the MATLAB west0479.mat demo matrix.  Those entries are
% present in the SuiteSparse Matrix Collection.  This example assumes your current
% directory is the RBio directory, containing the west0479 problem in the
% RBio/Test directory:
%
%   Prob5 = ssget ('HB/west0479')
%   Prob6 = ssread ('Test/west0479')
%   isequal (Prob5, Prob6)
%
% The directory can be a compressed tar file of the form "name.tar.gz", in
% which case the tarfile is uncompressed into a temporary directory, and
% the temporary directory is deleted when done.  The '.tar.gz' should not be
% part of the directory argument.  In this case, a 2nd input argument can be
% provided:  Problem = ssread (directory, tmp).  The problem is extracted into
% the tmp directory.  If tmp is not present, the output of the tempdir function
% is used instead.
%
% Note that ssget is much faster than ssread.  ssread is useful if you are
% short on disk space, and want to have just one copy of the collection that
% can be read by MATLAB (via ssread) and a non-MATLAB program (the MM or RB
% versions of the collection).
%
% See also sswrite, mread, mwrite, RBread, RBread, ssget, untar, tempdir.

% Optionally uses the CHOLMOD mread mexFunction, for reading Problems in
% Matrix Market format.

% SuiteSparseCollection, Copyright (c) 2006-2019, Timothy A Davis.
% All Rights Reserved.
% SPDX-License-Identifier: GPL-2.0+

%-------------------------------------------------------------------------------
% determine the Problem name from the directory name
%-------------------------------------------------------------------------------

directory = regexprep (directory, '[\/\\]', '/') ;
t = find (directory == '/') ;
if (isempty (t))
    name = directory ;
else
    name = directory (t(end)+1:end) ;
end

%-------------------------------------------------------------------------------
% open the directory, or untar the tar.gz file
%-------------------------------------------------------------------------------

d = dir (directory) ;
is_tar = 0 ;

if (isempty (d))
    % look for a .tar.gz file
    if (nargin < 2)
	tmpdir = [tempname '_ssread_' name] ;
    else
	tmpdir = [tmp '/' name] ;
    end
    try
	% try untaring the problem
	untar ([directory '.tar.gz'], tmpdir) ;
    catch
	% untar failed, make sure tmpdir is deleted
	try
	    rmdir (tmpdir, 's') ;
	catch
	end
	error (['unable to read problem: ' directory]) ;
    end
    directory = [tmpdir '/' name] ;
    d = dir (directory) ;
    is_tar = 1 ;
end 

%-------------------------------------------------------------------------------
% read the problem
%-------------------------------------------------------------------------------

try

    %---------------------------------------------------------------------------
    % get name, title, id, kind, date, author, editor, notes from master file
    %---------------------------------------------------------------------------

    masterfile = [directory '/' name] ;
    [Problem notes RB] = get_header (masterfile) ;

    %---------------------------------------------------------------------------
    % get the A and Zero matrices from the master file and add to the Problem
    %---------------------------------------------------------------------------

    if (RB)
	% read in the primary Rutherford/Boeing file
	[Problem.A Zeros] = RBread ([masterfile '.rb']) ;
    else
	% read in the primary Matrix Market file.  Get patterns as binary.
	[Problem.A Zeros] = mread ([masterfile '.mtx'], 1) ;
    end
    if (nnz (Zeros) > 0)
	Problem.Zeros = Zeros ;
    end

    % add the notes after A and Zeros
    if (~isempty (notes))
	Problem.notes = notes ;
    end

    namelen = length (name) ;

    %---------------------------------------------------------------------------
    % read b, x, aux (incl. any aux.cell sequences), stored as separate files
    %---------------------------------------------------------------------------

    for k = 1:length(d)

	% get the next filename in the directory
	file = d(k).name ;
	fullfilename = [directory '/' file] ;

	if (length (file) < length (name) + 1)

	    % unrecognized file; skip it
	    continue

	elseif (strcmp (file, [name '.mtx']))

	    % skip the master file; already read in
	    continue

	elseif (strcmp (file, [name '_b.mtx']))

	    % read in b as a Matrix Market file
	    Problem.b = mtx_read (fullfilename, RB) ;

	elseif (strcmp (file, [name '_x.mtx']))

	    % read in x as a Matrix Market file
	    Problem.x = mtx_read (fullfilename, RB) ;

	elseif (strcmp (file, [name '_b.rb']))

	    % read in b as a Rutherford/Boeing file
	    Problem.b = RBread (fullfilename) ;

	elseif (strcmp (file, [name '_x.rb']))

	    % read in x as a Rutherford/Boeing file
	    Problem.x = RBread (fullfilename) ;

	elseif (strcmp (file (1:length(name)+1), [name '_']))

	    % read in an aux component, in the form name_whatever.mtx
	    thedot = find (file == '.', 1, 'last') ;
	    ext = file (thedot:end) ;

	    if (strcmp (ext, '.txt'))

                % get a txt file as either a char array or cell array of strings
                C = sstextread (fullfilename, Problem.id > 2776) ;

	    elseif (strcmp (ext, '.mtx'))

		% read a full or sparse auxiliary matrix in the Matrix Market
		% form, or a full auxiliary matrix in the Rutherford/Boeing form.
		C = mtx_read (fullfilename, RB) ;

	    elseif (strcmp (ext, '.rb'))

		% read in a sparse matrix, for a Rutherford/Boeing collection
		C = RBread (fullfilename) ;

	    else

		% this file is not recognized - skip it.
		C = [ ] ;

	    end

	    % determine the name of the component and place it in the Problem
	    if (~isempty (C))
		% Determine if this is part of an aux.whatever cell sequence.
		% These filenames have the form name_whatever_#.mtx, where name
		% is the name of the Problem, and # is a number (1 or more
		% digts) greater than zero.  If # = i, this becomes the
		% aux.whatever{i} matrix.
		suffix = file (namelen+2:thedot-1) ;
		t = find (suffix == '_', 1, 'last') ;
		what = suffix (1:t-1) ;
		i = str2num (suffix (t+1:end)) ;			    %#ok
		if (~isempty (i) && i > 0 && ~isempty (what))
		    % this is part of aux.whatever{i} cell array
		    Problem.aux.(what) {i,1} = C ;
		elseif (~isempty (suffix))
		    % this is not a cell, simply an aux.whatever matrix
		    Problem.aux.(suffix) = C ;
		end
	    end
	end
    end

    %---------------------------------------------------------------------------
    % delete the uncompressed version of the tar file
    %---------------------------------------------------------------------------

    if (is_tar)
	rmdir (tmpdir, 's') ;
    end

catch

    %---------------------------------------------------------------------------
    % catch the error, delete the temp directory, and rethrow the error
    %---------------------------------------------------------------------------

    try
	if (is_tar)
	    rmdir (tmpdir, 's') ;
	end
    catch
    end
    rethrow (lasterror) ;

end


%-------------------------------------------------------------------------------
% get_header: get the header of the master file (Group/name/name.txt or .mtx)
%-------------------------------------------------------------------------------

function [Problem, notes, RB] = get_header (masterfile)
% Get the name, title, id, kind, date, author, editor and notes from the master
% file.  The name, title, and id are required.  They appear as structured
% comments in the Matrix Market file (masterfile.mtx) or in the text file for
% a problem in Rutherford/Boeing format (masterfile.txt).  RB is returned as
% 1 if the problem is in Rutherford/Boeing format, 0 otherwise.

% first assume it's in Matrix Market format
f = fopen ([masterfile '.mtx'], 'r') ;
if (f < 0)
    % oops, that failed.  This must be a problem in Rutherford/Boeing format
    RB = 1 ;
    f = fopen ([masterfile '.txt'], 'r') ;
    if (f < 0)
	% oops again, this is not a valid problem in the SuiteSparse collection
	error (['invalid problem: ' masterfile]) ;
    end
else
    % we found the Matrix Market file
    RB = 0 ;
end
Problem = [ ] ;
notes = [ ] ;

while (1)

    % get the next line
    s = fgetl (f) ;
    if (~ischar (s) || length (s) < 3 || s (1) ~= '%')
	% end of file or end of leading comments ... no notes found
	fclose (f) ;
	[Problem notes] = valid_problem (Problem, [ ]) ;
	return ;
    end

    % remove the leading '% ' and get the first token
    s = s (3:end) ;
    [t r] = strtok (s) ;

    % parse the line
    if (strcmp (t, 'name:'))

	% get the Problem.name.  It must be of the form Group/Name.
	Problem.name = strtrim (r) ;
	if (length (find (Problem.name == '/')) ~= 1)
	    fclose (f) ;
	    error (['invalid problem name ' Problem.name]) ;
	end

    elseif (s (1) == '[')

	% get the Problem.title
	k = find (s == ']', 1, 'last') ;
	if (isempty (k))
	    fclose (f) ;
	    error ('invalid problem title') ;
	end
	Problem.title = s (2:k-1) ;

    elseif (strcmp (t, 'id:'))

	% get the Problem.id
	Problem.id = str2num (r) ;					    %#ok
	if (isempty (Problem.id) || Problem.id < 0)
	    fclose (f) ;
	    error ('invalid problem id') ;
	end

    elseif (strcmp (t, 'kind:'))

	% get the Problem.kind
	Problem.kind = strtrim (r) ;

    elseif (strcmp (t, 'date:'))

	% get the Problem.date
	Problem.date = strtrim (r) ;

    elseif (strcmp (t, 'author:'))

	% get the Problem.author
	Problem.author = strtrim (r) ;

    elseif (strcmp (t, 'ed:'))

	% get the Problem.ed
	Problem.ed = strtrim (r) ;

    elseif (strcmp (t, 'notes:'))

	% get the notes, which always appear last
	k = 0 ;
	notes = [ ] ;
	while (1)
	    % get the next line
	    s = fgetl (f) ;
	    if (~ischar (s) || length (s) < 2 || ~strcmp (s (1:2), '% '))
		% end of file or end of notes ... convert notes to char array
		fclose (f) ;
		[Problem notes] = valid_problem (Problem, notes) ;
		return ;
	    end
	    % add the line to the notes
	    k = k + 1 ;
	    notes {k} = s ;						    %#ok
	end
    end
end


%-------------------------------------------------------------------------------
% valid_problem: determine if a problem is valid, and finalizes the notes
%-------------------------------------------------------------------------------

function [Problem, notes] = valid_problem (Problem, notes)
% make sure the required fields (name, title, id, date, author, ed) are present.
% Convert notes to char, and strip off the leading '% ', inserted when the notes
% were printed in the Matrix Market file.
if (~isfield (Problem, 'name') || ~isfield (Problem, 'title') || ...
    ~isfield (Problem, 'id') || ~isfield (Problem, 'date') || ...
    ~isfield (Problem, 'author') || ~isfield (Problem, 'ed') || ...
    ~isfield (Problem, 'kind'))
    error ('invalid Problem mfile') ;
end
if (~isempty (notes))
    notes = char (notes) ;
    notes = notes (:, 3:end) ;
end


%-------------------------------------------------------------------------------
% mtx_read: read a *.mtx file
%-------------------------------------------------------------------------------

% In the Rutherford/Boeing form, a *.mtx file is used only for full matrices,
% using a tiny subset of the Matrix Market format.  In the Matrix Market form,
% the *.mtx is used for all b, x, and aux matrices (both full and sparse).

function C = mtx_read (file, RB)

if (~RB)

    % Get a Matrix Market file, using full Matrix Market features.
    C = mread (file, 1) ;

else

    % mread is not installed.  The RB format uses a tiny subset of the Matrix
    % Market format for full matrices: just the one header line, and no comment
    % or blank lines permitted.  Allowable header lines are:
    %	%%MatrixMarket matrix array real general
    %	%%MatrixMarket matrix array complex general
    % This tiny subset can be read by ssfull_read.
    C = ssfull_read (file) ;

end