1 |
/* |
2 |
* Solver Standard Clients |
3 |
* by Benjamin Andrew Allan |
4 |
* 5/19/96 |
5 |
* Version: $Revision: 1.28 $ |
6 |
* Version control file: $RCSfile: slv_stdcalls.c,v $ |
7 |
* Date last modified: $Date: 1998/06/16 16:53:04 $ |
8 |
* Last modified by: $Author: mthomas $ |
9 |
* |
10 |
* Copyright(C) 1996 Benjamin Andrew Allan |
11 |
* Copyright(C) 1998 Carnegie Mellon University |
12 |
* |
13 |
* This file is part of the ASCEND IV math programming system. |
14 |
* Here is where we register our normal solvers and keep things |
15 |
* like reordering clients and so forth. This file should probably |
16 |
* be broken up into one file-one client layout for the unregistered |
17 |
* clients so that we can load them selectively. |
18 |
* |
19 |
* The Ascend Math Programming System is free software; you can |
20 |
* redistribute it and/or modify it under the terms of the GNU |
21 |
* General Public License as published by the Free Software |
22 |
* Foundation; either version 2 of the License, or (at your option) |
23 |
* any later version. |
24 |
* |
25 |
* The Ascend Math Programming System is distributed in hope that it |
26 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
27 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
28 |
* See the GNU General Public License for more details. |
29 |
* |
30 |
* You should have received a copy of the GNU General Public License |
31 |
* along with the program; if not, write to the Free Software |
32 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
33 |
* the file named COPYING. |
34 |
*/ |
35 |
|
36 |
#include "utilities/ascConfig.h" |
37 |
#include "compiler/compiler.h" |
38 |
#include "utilities/ascMalloc.h" |
39 |
#include "general/list.h" |
40 |
#include "solver/mtx.h" |
41 |
#include "solver/slv_types.h" |
42 |
#include "solver/var.h" |
43 |
#include "solver/rel.h" |
44 |
#include "solver/discrete.h" |
45 |
#include "solver/conditional.h" |
46 |
#include "solver/logrel.h" |
47 |
#include "solver/relman.h" |
48 |
#include "solver/logrelman.h" |
49 |
#include "solver/bnd.h" |
50 |
#include "solver/slv_common.h" |
51 |
#include "solver/linsol.h" |
52 |
#include "solver/linsolqr.h" |
53 |
#include "solver/slv_client.h" |
54 |
/* header of registered clients */ |
55 |
#include "solver/slv0.h" |
56 |
#include "solver/slv1.h" |
57 |
#include "solver/slv2.h" |
58 |
#include "solver/slv3.h" |
59 |
#include "solver/slv6.h" |
60 |
#include "solver/slv7.h" |
61 |
#include "solver/slv8.h" |
62 |
#include "solver/slv9.h" |
63 |
#include "solver/slv9a.h" |
64 |
#include "solver/model_reorder.h" |
65 |
#include "solver/slv_stdcalls.h" |
66 |
|
67 |
#define KILL 0 /* deleteme code. compile old code if kill = 1 */ |
68 |
#define NEEDSTOBEDONE 0 /* indicates code/comments that are not yet ready */ |
69 |
#define USECODE 0 /* Code in good shape but not used currently */ |
70 |
|
71 |
/* |
72 |
* Here we play some hefty jacobian reordering games. |
73 |
* What we want to happen eventually is as follows: |
74 |
* |
75 |
* Get the free & incident pattern for include relations. |
76 |
* Output assign jacobian. |
77 |
* BLT permute the jacobian. if underspecified, fake rows |
78 |
* to make things appear square. |
79 |
* For all leading square blocks apply reordering (kirk, etc) |
80 |
* If trailing rectangular block, apply clever kirkbased scheme not known. |
81 |
* |
82 |
* At present, we aren't quite so clever. We: |
83 |
* |
84 |
* Get the free & incident pattern for include relations. |
85 |
* Output assign jacobian. |
86 |
* BLT permute the square output assigned region of the jacobian. |
87 |
* For all leading square blocks apply reordering (kirk, etc) |
88 |
* |
89 |
* Collect the block list as part of the master data structure. |
90 |
* Set sindices for rels, vars as current rows/cols in matrix so |
91 |
* that the jacobian is 'naturally' preordered for all solvers. |
92 |
* |
93 |
* Solvers are still free to reorder their own matrices any way they like; |
94 |
* it's probably a dumb idea, though. |
95 |
* |
96 |
* returns 0 if ok, 1 if out of memory. |
97 |
*/ |
98 |
|
99 |
#define MIMDEBUG 0 |
100 |
/* |
101 |
* Populates a matrix according to the sys solvers_vars, solvers_rels |
102 |
* lists and the filters given. The filter should have at least |
103 |
* SVAR = 1 bit on. mtx given must be created (not null) and with |
104 |
* order >= MAX( slv_get_num_solvers_rels(sys),slv_get_num_solvers_vars(sys)); |
105 |
* returns 0 if went ok. |
106 |
*/ |
107 |
int slv_std_make_incidence_mtx(slv_system_t sys, mtx_matrix_t mtx, |
108 |
var_filter_t *vf,rel_filter_t *rf) |
109 |
{ |
110 |
#if MIMDEBUG |
111 |
FILE *fp; |
112 |
#endif |
113 |
int32 r, rlen,ord; |
114 |
struct rel_relation **rp; |
115 |
|
116 |
if (sys==NULL || mtx == NULL || vf == NULL || rf == NULL) { |
117 |
FPRINTF(stderr,"make_incidence called with null\n"); |
118 |
return 1; |
119 |
} |
120 |
rp = slv_get_solvers_rel_list(sys); |
121 |
assert(rp!=NULL); |
122 |
rlen = slv_get_num_solvers_rels(sys); |
123 |
ord = MAX(rlen,slv_get_num_solvers_vars(sys)); |
124 |
if (ord > mtx_order(mtx)) { |
125 |
FPRINTF(stderr,"make_incidence called with undersized matrix\n"); |
126 |
return 2; |
127 |
} |
128 |
for (r=0; r < rlen; r++) { |
129 |
if (rel_apply_filter(rp[r],rf)) { |
130 |
relman_get_incidence(rp[r],vf,mtx); |
131 |
} |
132 |
} |
133 |
#if MIMDEBUG |
134 |
fp = fopen("/tmp/mim.plot","w+"); |
135 |
if (fp !=NULL) { |
136 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
137 |
fclose(fp); |
138 |
} |
139 |
#endif |
140 |
return 0; |
141 |
} |
142 |
|
143 |
#define RIDEBUG 0 |
144 |
/* returns 0 if successful, 1 if insufficient memory. Does not change |
145 |
* the data in mtx. Orders the solvers_var list of the system to |
146 |
* match the permutation on the given mtx. It is assumed that |
147 |
* the org cols of mtx == var list position. Only the |
148 |
* vars in range lo to hi of the var list are affected and |
149 |
* only these vars should appear in the same org column range of |
150 |
* the mtx. This should not be called on blocks less than 3x3. |
151 |
*/ |
152 |
static int reindex_vars_from_mtx(slv_system_t sys, int32 lo, int32 hi, |
153 |
const mtx_matrix_t mtx) |
154 |
{ |
155 |
struct var_variable **vtmp, **vp; |
156 |
int32 c,v,vlen; |
157 |
|
158 |
if (lo >= hi +1) return 0; /* job too small */ |
159 |
vp = slv_get_solvers_var_list(sys); |
160 |
vlen = slv_get_num_solvers_vars(sys); |
161 |
/* on vtmp we DONT have the terminating null */ |
162 |
vtmp = (struct var_variable **)ascmalloc(vlen*sizeof(struct var_variable *)); |
163 |
if (vtmp == NULL) { |
164 |
return 1; |
165 |
} |
166 |
/* copy pointers to vtmp in order desired and copy back rather than sort */ |
167 |
for (c=lo;c<=hi;c++) { |
168 |
v = mtx_col_to_org(mtx,c); |
169 |
vtmp[c] = vp[v]; |
170 |
} |
171 |
/* copying back and re-sindexing */ |
172 |
for (c=lo;c<=hi;c++) { |
173 |
vp[c] = vtmp[c]; |
174 |
var_set_sindex(vp[c],c); |
175 |
} |
176 |
ascfree(vtmp); |
177 |
return 0; |
178 |
} |
179 |
/* returns 0 if successful, 1 if insufficient memory. Does not change |
180 |
* the data in mtx. Orders the solvers_rel list of the system to |
181 |
* match the permutation on the given mtx. It is assumed that |
182 |
* the org rows of mtx == rel list position. Only the |
183 |
* rels in range lo to hi of the rel list are affected and |
184 |
* only these rels should appear in the same org row range of |
185 |
* the input mtx. This should not be called on blocks less than 3x3. |
186 |
*/ |
187 |
static int reindex_rels_from_mtx(slv_system_t sys, int32 lo, int32 hi, |
188 |
const mtx_matrix_t mtx) |
189 |
{ |
190 |
struct rel_relation **rtmp, **rp; |
191 |
int32 c,v,rlen; |
192 |
|
193 |
rp = slv_get_solvers_rel_list(sys); |
194 |
rlen = slv_get_num_solvers_rels(sys); |
195 |
/* on rtmp we DONT have the terminating null */ |
196 |
rtmp = (struct rel_relation **)ascmalloc(rlen*sizeof(struct rel_relation *)); |
197 |
if (rtmp == NULL) { |
198 |
return 1; |
199 |
} |
200 |
/* copy pointers to rtmp in order desired and copy back rather than sort. |
201 |
* do this only in the row range of interest. */ |
202 |
for (c=lo;c<=hi;c++) { |
203 |
v = mtx_row_to_org(mtx,c); |
204 |
#if RIDEBUG |
205 |
FPRINTF(stderr,"Old rel sindex (org) %d becoming sindex (cur) %d\n",v,c); |
206 |
#endif |
207 |
rtmp[c] = rp[v]; |
208 |
} |
209 |
/* copying back and re-sindexing */ |
210 |
for (c=lo;c<=hi;c++) { |
211 |
rp[c] = rtmp[c]; |
212 |
rel_set_sindex(rp[c],c); |
213 |
} |
214 |
ascfree(rtmp); |
215 |
return 0; |
216 |
} |
217 |
|
218 |
|
219 |
/* returns 0 if ok, OTHERWISE if madness detected. |
220 |
* doesn't grok inequalities. |
221 |
*/ |
222 |
#define SBPDEBUG 0 |
223 |
int slv_block_partition_real(slv_system_t sys,int uppertriangular) |
224 |
{ |
225 |
#if SBPDEBUG |
226 |
FILE *fp; |
227 |
#endif |
228 |
struct rel_relation **rp; |
229 |
struct var_variable **vp; |
230 |
mtx_region_t *newblocks; |
231 |
dof_t *d; |
232 |
int32 nrow,ncol; |
233 |
int32 ncolpfix, nrowpun, vlenmnv; |
234 |
mtx_matrix_t mtx; |
235 |
int32 order, rank; |
236 |
int32 c,len,vlen,r,rlen; |
237 |
var_filter_t vf; |
238 |
rel_filter_t rf; |
239 |
|
240 |
rp = slv_get_solvers_rel_list(sys); |
241 |
vp = slv_get_solvers_var_list(sys); |
242 |
rlen = slv_get_num_solvers_rels(sys); |
243 |
vlen = slv_get_num_solvers_vars(sys); |
244 |
if (rlen ==0 || vlen == 0) return 1; |
245 |
order = MAX(rlen,vlen); |
246 |
|
247 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
248 |
rf.matchvalue = (REL_ACTIVE); |
249 |
vf.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); |
250 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); |
251 |
|
252 |
/* nrow plus unincluded rels and ineqs */ |
253 |
nrowpun = slv_count_solvers_rels(sys,&rf); |
254 |
ncolpfix = slv_count_solvers_vars(sys,&vf); /* ncol plus fixed vars */ |
255 |
|
256 |
vf.matchbits = (VAR_SVAR); |
257 |
vf.matchvalue = 0; |
258 |
vlenmnv = vlen - slv_count_solvers_vars(sys,&vf); /* vlen minus non vars */ |
259 |
|
260 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
261 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
262 |
vf.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_FIXED | VAR_ACTIVE); |
263 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); |
264 |
|
265 |
nrow = slv_count_solvers_rels(sys,&rf); |
266 |
ncol = slv_count_solvers_vars(sys,&vf); |
267 |
|
268 |
mtx = mtx_create(); |
269 |
mtx_set_order(mtx,order); |
270 |
|
271 |
if (slv_std_make_incidence_mtx(sys,mtx,&vf,&rf)) { |
272 |
FPRINTF(stderr, |
273 |
"slv_block_partition: failure in creating incidence matrix.\n"); |
274 |
mtx_destroy(mtx); |
275 |
return 1; |
276 |
} |
277 |
|
278 |
mtx_output_assign(mtx,rlen,vlen); |
279 |
rank = mtx_symbolic_rank(mtx); |
280 |
if (rank == 0 ) return 1; /* nothing to do, eh? */ |
281 |
/* lot of whining about dof */ |
282 |
if (rank < nrow) { |
283 |
FPRINTF(stderr,"System is row rank deficient (%d dependent equations)\n", |
284 |
nrow - rank); |
285 |
} |
286 |
if (rank < ncol) { |
287 |
if ( nrow != rank) { |
288 |
FPRINTF(stderr,"System is row rank deficient with %d excess columns.\n", |
289 |
ncol - rank); |
290 |
} else { |
291 |
FPRINTF(stderr,"System has %d degrees of freedom.\n", ncol - rank); |
292 |
} |
293 |
} |
294 |
if (ncol == nrow) { |
295 |
FPRINTF(stderr,"System is (%d) square",ncol); |
296 |
if (ncol != rank) { |
297 |
FPRINTF(stderr,"but rank deficient.\n"); |
298 |
} else { |
299 |
FPRINTF(stderr,".\n"); |
300 |
} |
301 |
} |
302 |
if (uppertriangular) { |
303 |
mtx_ut_partition(mtx); |
304 |
} else { |
305 |
mtx_partition(mtx); |
306 |
} |
307 |
/* copy the block list. there is at least one if rank >=1 as above */ |
308 |
len = mtx_number_of_blocks(mtx); |
309 |
newblocks = (mtx_region_t *)ascmalloc(len*sizeof(mtx_region_t)); |
310 |
if (newblocks == NULL) { |
311 |
mtx_destroy(mtx); |
312 |
return 2; |
313 |
} |
314 |
for (c = 0 ; c < len; c++) { |
315 |
mtx_block(mtx,c,&(newblocks[c])); |
316 |
} |
317 |
slv_set_solvers_blocks(sys,len,newblocks); /* give it to the system */ |
318 |
d = slv_get_dofdata(sys); |
319 |
d->structural_rank = rank; |
320 |
d->n_rows = nrow; |
321 |
d->n_cols = ncol; |
322 |
/* the next two lines assume inequalities are unincluded. |
323 |
*/ |
324 |
#define MINE 1 |
325 |
#if MINE |
326 |
d->n_fixed = ncolpfix - ncol; |
327 |
d->n_unincluded = nrowpun - nrow; |
328 |
#else |
329 |
d->n_fixed = vlen - ncol; |
330 |
d->n_unincluded = rlen - nrow; |
331 |
#endif |
332 |
d->reorder.partition = 1; /* yes */ |
333 |
d->reorder.basis_selection = 0; /* none yet */ |
334 |
d->reorder.block_reordering = 0; /* none */ |
335 |
|
336 |
#if SBPDEBUG |
337 |
fp = fopen("/tmp/sbp1.plot","w+"); |
338 |
if (fp !=NULL) { |
339 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
340 |
fclose(fp); |
341 |
} |
342 |
#endif |
343 |
|
344 |
|
345 |
#if MINE |
346 |
len = vlenmnv - 1; /* row of last possible solver variable */ |
347 |
for (c=ncol; len > c ; ) { /* sort the fixed out of inactive */ |
348 |
r = mtx_col_to_org(mtx,c); |
349 |
if ( var_fixed(vp[r]) && var_active(vp[r])) { |
350 |
c++; |
351 |
} else { |
352 |
mtx_swap_cols(mtx,c,len); |
353 |
len--; |
354 |
} |
355 |
} |
356 |
#endif |
357 |
|
358 |
/* Now, leftover columns are where we want them. |
359 |
* That is, unassigned incidence is next to assigned and fixed on right with |
360 |
* no columns which do not correspond to variables in the range 0..vlen-1. |
361 |
*/ |
362 |
/* there aren't any nonincident vars in the solvers varlist, so |
363 |
* we now have the columns in |assigned|dof|fixed|inactive|nonvars| order */ |
364 |
|
365 |
/* rows 0->rlen-1 should be actual rels, though, and not phantoms. |
366 |
* At this point we should have |
367 |
* rows - assigned |
368 |
* - unassigned w/incidence |
369 |
* - unincluded and included w/out free incidence and inactive mixed. |
370 |
*/ |
371 |
/* sort unincluded relations to bottom of good region */ |
372 |
/* this is needed because the idiot user may have fixed everything */ |
373 |
/* in a relation, but we want those rows not to be confused with */ |
374 |
/* unincluded rows. we're sort of dropping inequalities on the floor.*/ |
375 |
len = rlen - 1; /* row of last possible relation */ |
376 |
/* sort the inactive out of the unassigned/unincluded */ |
377 |
for (c=rank; len > c ; ) { |
378 |
r = mtx_row_to_org(mtx,c); |
379 |
if ( rel_active(rp[r])) { |
380 |
c++; |
381 |
} else { |
382 |
mtx_swap_rows(mtx,c,len); |
383 |
len--; |
384 |
} |
385 |
} |
386 |
|
387 |
#if MINE |
388 |
/* sort the unincluded out of the unassigned */ |
389 |
len = nrowpun - 1; /* row of last possible unassigned/unincluded relation */ |
390 |
for (c=rank; len > c ; ) { |
391 |
r = mtx_row_to_org(mtx,c); |
392 |
if ( rel_included(rp[r]) ) { |
393 |
c++; |
394 |
} else { |
395 |
mtx_swap_rows(mtx,c,len); |
396 |
len--; |
397 |
} |
398 |
} |
399 |
#endif |
400 |
|
401 |
|
402 |
#if SBPDEBUG |
403 |
fp = fopen("/tmp/sbp2.plot","w+"); |
404 |
if (fp !=NULL) { |
405 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
406 |
fclose(fp); |
407 |
} |
408 |
#endif |
409 |
/* now, at last we have cols jacobian in the order we want the lists to |
410 |
* be handed to the solvers. So, we need to reset the var sindex values |
411 |
* and reorder the lists. |
412 |
*/ |
413 |
if (reindex_vars_from_mtx(sys,0,vlen-1,mtx)) { |
414 |
mtx_destroy(mtx); |
415 |
return 2; |
416 |
} |
417 |
/* now, at last we have rows jacobian in the order we want the lists to |
418 |
* be handed to the solvers. So, we need to reset the rel sindex values. |
419 |
*/ |
420 |
if (reindex_rels_from_mtx(sys,0,rlen-1,mtx)) { |
421 |
mtx_destroy(mtx); |
422 |
return 2; |
423 |
} |
424 |
mtx_destroy(mtx); |
425 |
return 0; |
426 |
} |
427 |
|
428 |
|
429 |
#if 0 /* code not currently used */ |
430 |
#ifdef STATIC_HARWELL |
431 |
extern void mc21b(); |
432 |
extern void mc13emod(); |
433 |
/* returns 0 if ok, OTHERWISE if madness detected. |
434 |
* doesn't grok inequalities. |
435 |
* CURRENTLY DOESN'T DO WELL WHEN NCOL<NROW |
436 |
*/ |
437 |
#define SBPDEBUG 0 |
438 |
int slv_block_partition_harwell(slv_system_t sys) |
439 |
{ |
440 |
#if SBPDEBUG |
441 |
FILE *fp; |
442 |
#endif |
443 |
struct rel_relation **rp; |
444 |
struct rel_relation **rtmp; |
445 |
struct rel_relation *rel; |
446 |
struct var_variable **vp; |
447 |
struct var_variable **vtmp; |
448 |
struct var_variable *var; |
449 |
const struct var_variable **list; |
450 |
mtx_region_t *newblocks; |
451 |
dof_t *d; |
452 |
int32 nrow,ncol,size; |
453 |
int32 order, rank; |
454 |
int32 c,len,vlen,r,v,rlen,col,row; |
455 |
int32 licn,rel_tmp_end,rel_count,var_perm_count,var_tmp_end,row_perm_count; |
456 |
int32 col_incidence,numnz,row_high,col_high,dummy_ptr,row_ptr,num; |
457 |
int32 *dummy_array_ptr; |
458 |
var_filter_t vf; |
459 |
rel_filter_t rf; |
460 |
int32 *icn, *ip, *lenr, *iperm, *iw1, *iw2, *iw3, *arp, *ipnew, *ib; |
461 |
int32 *row_perm; |
462 |
|
463 |
/* get rel and var info */ |
464 |
rp = slv_get_solvers_rel_list(sys); |
465 |
vp = slv_get_solvers_var_list(sys); |
466 |
rlen = slv_get_num_solvers_rels(sys); |
467 |
vlen = slv_get_num_solvers_vars(sys); |
468 |
if (rlen ==0 || vlen == 0) return 1; |
469 |
order = MAX(rlen,vlen); |
470 |
|
471 |
/* allocate temp arrays */ |
472 |
vtmp = (struct var_variable **)ascmalloc(vlen*sizeof(struct var_variable *)); |
473 |
var = (struct var_variable *)ascmalloc(sizeof(struct var_variable *)); |
474 |
if (vtmp == NULL || var ==NULL) { |
475 |
return 1; |
476 |
} |
477 |
rtmp = (struct rel_relation **)ascmalloc(rlen*sizeof(struct rel_relation *)); |
478 |
rel = (struct rel_relation *)ascmalloc(sizeof(struct rel_relation *)); |
479 |
if (rtmp == NULL || rel ==NULL) { |
480 |
return 1; |
481 |
} |
482 |
|
483 |
/* set up filters */ |
484 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY); |
485 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY); |
486 |
vf.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_FIXED); |
487 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR); |
488 |
|
489 |
/* count rows and cols */ |
490 |
nrow = slv_count_solvers_rels(sys,&rf); |
491 |
ncol = slv_count_solvers_vars(sys,&vf); |
492 |
|
493 |
|
494 |
/* count incidence for equality relations that are included |
495 |
and active. Sorts out unincluded and inactive rels to |
496 |
the end of the temporary relation list */ |
497 |
licn = 0; |
498 |
rel_tmp_end = rlen -1; |
499 |
for (r=0; r < rlen; r++) { |
500 |
rel = rp[r]; |
501 |
if (rel_apply_filter(rel,&rf) && rel_active(rel)) { |
502 |
len = rel_n_incidences(rel); |
503 |
list = rel_incidence_list(rel); |
504 |
for (c=0; c < len; c++) { |
505 |
if( var_apply_filter(list[c],&vf) ) { |
506 |
licn++; |
507 |
} |
508 |
} |
509 |
} else { |
510 |
rtmp[rel_tmp_end] = rp[r]; |
511 |
rel_tmp_end--; |
512 |
} |
513 |
} |
514 |
|
515 |
/* sort the inactive out of the unincluded and move to end */ |
516 |
len = rlen -1; |
517 |
for(c = rel_tmp_end + 1; len > c; ) { |
518 |
rel = rtmp[c]; |
519 |
if (rel_active(rel)) { |
520 |
c++; |
521 |
} else { |
522 |
rtmp[c] = rtmp[len]; |
523 |
rtmp[len] = rel; |
524 |
len--; |
525 |
} |
526 |
} |
527 |
|
528 |
/* Sort variable list */ |
529 |
var_perm_count = 0; |
530 |
var_tmp_end = vlen - 1; |
531 |
for (c = 0; c < vlen; c++) { |
532 |
var = vp[c]; |
533 |
if (var_apply_filter(var,&vf)) { |
534 |
vtmp[var_perm_count] = var; |
535 |
var_perm_count++; |
536 |
} else { |
537 |
vtmp[var_tmp_end] = var; |
538 |
var_tmp_end--; |
539 |
} |
540 |
} |
541 |
/* sort the inactive out of the unincluded and move to end */ |
542 |
len = vlen -1; |
543 |
for(c = var_tmp_end + 1; len > c; ) { |
544 |
var = vtmp[c]; |
545 |
if (var_active(var) && var_active(var)) { |
546 |
c++; |
547 |
} else { |
548 |
vtmp[c] = vtmp[len]; |
549 |
vtmp[len] = var; |
550 |
len--; |
551 |
} |
552 |
} |
553 |
|
554 |
/* reset solver indicies to make life easier */ |
555 |
for (c = 0; c < vlen; c++) { |
556 |
vp[c] = vtmp[c]; |
557 |
var_set_sindex(vp[c],c); |
558 |
} |
559 |
|
560 |
size = MAX(nrow,ncol); |
561 |
/* Create vectors for fortran calls */ |
562 |
icn = (int32 *)ascmalloc(licn*sizeof(int32)); |
563 |
ip = (int32 *)ascmalloc(size*sizeof(int32)); |
564 |
lenr = (int32 *)ascmalloc(size*sizeof(int32)); |
565 |
iperm = (int32 *)ascmalloc(size*sizeof(int32)); |
566 |
iw1 = (int32 *)ascmalloc(size*sizeof(int32)); |
567 |
iw2 = (int32 *)ascmalloc(size*sizeof(int32)); |
568 |
iw3 = (int32 *)ascmalloc(size*sizeof(int32)); |
569 |
arp = (int32 *)ascmalloc(size*sizeof(int32)); |
570 |
ipnew = (int32 *)ascmalloc(size*sizeof(int32)); |
571 |
ib = (int32 *)ascmalloc(size*sizeof(int32)); |
572 |
row_perm = (int32 *)ascmalloc(size*sizeof(int32)); |
573 |
|
574 |
|
575 |
/* Fill incidence vectors and place included relations w/o |
576 |
* incidence in temporary relation list before the unincluded |
577 |
* and inactive relations |
578 |
*/ |
579 |
col_incidence = 0; |
580 |
row_perm_count = 0; |
581 |
for (r=0; r < rlen; r++) { |
582 |
rel = rp[r]; |
583 |
if (rel_apply_filter(rel,&rf) && rel_active(rel)) { |
584 |
len = rel_n_incidences(rel); |
585 |
if (len > 0) { |
586 |
ip[row_perm_count] = col_incidence + 1; /*FORTRAN*/ |
587 |
lenr[row_perm_count] = len; |
588 |
row_perm[row_perm_count] = r; |
589 |
row_perm_count++; |
590 |
list = rel_incidence_list(rel); |
591 |
for (c=0; c < len; c++) { |
592 |
if( var_apply_filter(list[c],&vf) ) { |
593 |
col = var_sindex(list[c]); |
594 |
icn[col_incidence] = col + 1; /*FORTRAN*/ |
595 |
col_incidence++; |
596 |
} |
597 |
} |
598 |
} else { |
599 |
rtmp[rel_tmp_end] = rel; |
600 |
rel_tmp_end--; |
601 |
} |
602 |
} |
603 |
} |
604 |
|
605 |
licn = col_incidence; |
606 |
order = row_perm_count; |
607 |
mc21b(&order,icn,&licn,ip,lenr,iperm,&numnz,iw1,arp,iw2,iw3); |
608 |
if (order == numnz){ |
609 |
FPRINTF(stderr,"they are equal\n"); |
610 |
} else if(order == numnz + 1){ |
611 |
FPRINTF(stderr,"ADD ONE\n"); |
612 |
} else { |
613 |
FPRINTF(stderr,"no relationship\n"); |
614 |
} |
615 |
|
616 |
if (rank == 0 ) { |
617 |
return 1; /* nothing to do, eh? */ |
618 |
} |
619 |
row_high = nrow - 1; |
620 |
col_high = ncol -1; |
621 |
|
622 |
/* lot of whining about dof */ |
623 |
if (rank < nrow) { |
624 |
FPRINTF(stderr,"System is row rank deficient (dependent equations)\n"); |
625 |
row_high = rank - 1; |
626 |
/* KHACK: have found that this is executed erroneously */ |
627 |
} |
628 |
if (rank < ncol) { |
629 |
if ( nrow != rank) { |
630 |
FPRINTF(stderr,"System is row rank deficient with excess columns.\n"); |
631 |
} else { |
632 |
FPRINTF(stderr,"System has degrees of freedom.\n"); |
633 |
} |
634 |
} |
635 |
if (ncol == nrow) { |
636 |
FPRINTF(stderr,"System is (%d) square",ncol); |
637 |
if (ncol != rank) { |
638 |
FPRINTF(stderr,"but rank deficient.\n"); |
639 |
} else { |
640 |
FPRINTF(stderr,".\n"); |
641 |
} |
642 |
} |
643 |
|
644 |
dummy_array_ptr = arp; |
645 |
arp = lenr; |
646 |
lenr = dummy_array_ptr; |
647 |
|
648 |
/* Fix row pointers for assigned relations. Put unassigned |
649 |
onto temporary relation list (before included w/o incidence) |
650 |
and put dummy dense rows into ipnew */ |
651 |
dummy_ptr = licn + 1; /* FORTRAN */ |
652 |
for (row = 0; row < order; row++) { |
653 |
row_ptr = iperm[row] - 1; /* FORTRAN */ |
654 |
if (row_ptr != -1) { /* indicates unassigned row */ |
655 |
ipnew[row_ptr] = ip[row]; |
656 |
lenr[row_ptr] = arp[row]; |
657 |
} else { |
658 |
ipnew[row_ptr] = dummy_ptr; |
659 |
dummy_ptr += ncol; |
660 |
lenr[row_ptr] = ncol; |
661 |
/* unassigned before fixed*/ |
662 |
rtmp[rel_tmp_end] = rp[row_perm[row_ptr]]; |
663 |
rel_tmp_end--; |
664 |
} |
665 |
} |
666 |
for (row = order; row < ncol; row++) { |
667 |
ipnew[row] = dummy_ptr; |
668 |
dummy_ptr += ncol; |
669 |
lenr[row] = ncol; |
670 |
} |
671 |
|
672 |
mc13emod(&size,icn,&licn,ipnew,lenr,arp,ib,&num,iw1,iw2,iw3); |
673 |
|
674 |
|
675 |
/* copy the block list. there is at least one if rank >=1 as above */ |
676 |
len = num; |
677 |
newblocks = (mtx_region_t *)ascmalloc(len*sizeof(mtx_region_t)); |
678 |
if (newblocks == NULL) { |
679 |
return 2; |
680 |
} |
681 |
/* set up locations of block corners with the row and column |
682 |
orderings which will be set soon */ |
683 |
for (c = 0 ; c < len; c++) { |
684 |
newblocks[c].row.low = ib[c]-1; |
685 |
newblocks[c].col.low = newblocks[c].row.low; |
686 |
} |
687 |
for (c = 0 ; c < len -1; c++) { |
688 |
newblocks[c].row.high = newblocks[c+1].row.low -1; |
689 |
newblocks[c].col.high = newblocks[c].row.high; |
690 |
} |
691 |
newblocks[len - 1].row.high = row_high; |
692 |
newblocks[len - 1].col.high = col_high; |
693 |
|
694 |
slv_set_solvers_blocks(sys,len,newblocks); /* give it to the system */ |
695 |
d = slv_get_dofdata(sys); |
696 |
d->structural_rank = rank; |
697 |
d->n_rows = nrow; |
698 |
d->n_cols = ncol; |
699 |
/* the next two lines assume only free and fixed incident solvervar |
700 |
* appear in the solvers var list and inequalities are unincluded. |
701 |
*/ |
702 |
d->n_fixed = vlen - ncol; |
703 |
d->n_unincluded = rlen - nrow; |
704 |
d->reorder.partition = 1; /* yes */ |
705 |
d->reorder.basis_selection = 0; /* none yet */ |
706 |
d->reorder.block_reordering = 0; /* none */ |
707 |
|
708 |
for (c = 0; c < ncol; c++) { |
709 |
v = arp[c] -1; /* FORTRAN */ |
710 |
vtmp[c] = vp[v]; |
711 |
} |
712 |
for (c = 0; c < vlen; c++) { |
713 |
vp[c] = vtmp[c]; |
714 |
var_set_sindex(vp[c],c); |
715 |
} |
716 |
|
717 |
rel_count = 0; |
718 |
for (c = 0; c < size; c++) { |
719 |
r = arp[c] - 1; |
720 |
if (r < order){ /* weed out fake rows */ |
721 |
r = iperm[r] - 1; |
722 |
if (r != -1) { /* unassigned already in rtmp */ |
723 |
rtmp[rel_count] = rp[row_perm[r]]; |
724 |
rel_count++; |
725 |
} |
726 |
} |
727 |
} |
728 |
for (c = 0; c < rlen; c++) { |
729 |
rp[c] = rtmp[c]; |
730 |
rel_set_sindex(rp[c],c); |
731 |
} |
732 |
ascfree(vtmp); |
733 |
ascfree(rtmp); |
734 |
ascfree(icn); |
735 |
ascfree(ip); |
736 |
ascfree(lenr); |
737 |
ascfree(iperm); |
738 |
ascfree(iw1); |
739 |
ascfree(iw2); |
740 |
ascfree(iw3); |
741 |
ascfree(arp); |
742 |
ascfree(ipnew); |
743 |
ascfree(ib); |
744 |
return 0; |
745 |
} |
746 |
#endif /*STATIC_HARWELL*/ |
747 |
#endif /* 0 */ |
748 |
|
749 |
|
750 |
void slv_sort_rels_and_vars(slv_system_t sys, |
751 |
int32 *rel_count, |
752 |
int32 *var_count) |
753 |
{ |
754 |
struct rel_relation **rp; |
755 |
struct rel_relation **rtmp; |
756 |
struct rel_relation *rel; |
757 |
struct var_variable **vp; |
758 |
struct var_variable **vtmp; |
759 |
struct var_variable *var; |
760 |
int32 nrow,ncol,rlen,vlen,order,rel_tmp_end; |
761 |
int32 r,c,var_tmp_end,len; |
762 |
var_filter_t vf; |
763 |
rel_filter_t rf; |
764 |
|
765 |
/* get rel and var info */ |
766 |
rp = slv_get_solvers_rel_list(sys); |
767 |
vp = slv_get_solvers_var_list(sys); |
768 |
rlen = slv_get_num_solvers_rels(sys); |
769 |
vlen = slv_get_num_solvers_vars(sys); |
770 |
if (rlen ==0 || vlen == 0) return; |
771 |
order = MAX(rlen,vlen); |
772 |
|
773 |
assert(var_count != NULL && rel_count != NULL); |
774 |
*var_count = *rel_count = -1; |
775 |
|
776 |
/* allocate temp arrays */ |
777 |
vtmp = (struct var_variable **)ascmalloc(vlen*sizeof(struct var_variable *)); |
778 |
if (vtmp == NULL) { |
779 |
return; |
780 |
} |
781 |
rtmp = (struct rel_relation **)ascmalloc(rlen*sizeof(struct rel_relation *)); |
782 |
if (rtmp == NULL) { |
783 |
ascfree(vtmp); |
784 |
return; |
785 |
} |
786 |
|
787 |
/* set up filters */ |
788 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
789 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
790 |
vf.matchbits = (VAR_INCIDENT | VAR_SVAR | VAR_FIXED | VAR_ACTIVE); |
791 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); |
792 |
|
793 |
/* count rows and cols */ |
794 |
nrow = slv_count_solvers_rels(sys,&rf); |
795 |
ncol = slv_count_solvers_vars(sys,&vf); |
796 |
|
797 |
|
798 |
/* Sort out unincluded and inactive rels to |
799 |
* the end of the temporary relation list. |
800 |
*/ |
801 |
*rel_count = 0; |
802 |
rel_tmp_end = rlen -1; |
803 |
for (r=0; r < rlen; r++) { |
804 |
rel = rp[r]; |
805 |
if (rel_apply_filter(rel,&rf)) { |
806 |
rtmp[*rel_count] = rel; |
807 |
(*rel_count)++; |
808 |
} else { |
809 |
rtmp[rel_tmp_end] = rel; |
810 |
rel_tmp_end--; |
811 |
} |
812 |
} |
813 |
|
814 |
/* sort the inactive out of the unincluded and move to end */ |
815 |
len = rlen -1; |
816 |
for(c = rel_tmp_end + 1; len > c; ) { |
817 |
rel = rtmp[c]; |
818 |
if (rel_active(rel)) { |
819 |
c++; |
820 |
} else { |
821 |
rtmp[c] = rtmp[len]; |
822 |
rtmp[len] = rel; |
823 |
len--; |
824 |
} |
825 |
} |
826 |
|
827 |
/* Sort variable list */ |
828 |
*var_count = 0; |
829 |
var_tmp_end = vlen - 1; |
830 |
for (c = 0; c < vlen; c++) { |
831 |
var = vp[c]; |
832 |
if (var_apply_filter(var,&vf)) { |
833 |
vtmp[*var_count] = var; |
834 |
(*var_count)++; |
835 |
} else { |
836 |
vtmp[var_tmp_end] = var; |
837 |
var_tmp_end--; |
838 |
} |
839 |
} |
840 |
/* sort the inactive out of the unincluded and move to end */ |
841 |
len = vlen -1; |
842 |
for(c = var_tmp_end + 1; len > c; ) { |
843 |
var = vtmp[c]; |
844 |
if (var_active(var) && var_active(var)) { |
845 |
c++; |
846 |
} else { |
847 |
vtmp[c] = vtmp[len]; |
848 |
vtmp[len] = var; |
849 |
len--; |
850 |
} |
851 |
} |
852 |
|
853 |
/* reset solver indicies */ |
854 |
for (c = 0; c < vlen; c++) { |
855 |
vp[c] = vtmp[c]; |
856 |
var_set_sindex(vp[c],c); |
857 |
} |
858 |
|
859 |
for (c = 0; c < rlen; c++) { |
860 |
rp[c] = rtmp[c]; |
861 |
rel_set_sindex(rp[c],c); |
862 |
} |
863 |
ascfree(vtmp); |
864 |
ascfree(rtmp); |
865 |
return; |
866 |
} |
867 |
|
868 |
|
869 |
|
870 |
|
871 |
|
872 |
int slv_block_unify(slv_system_t sys) |
873 |
{ |
874 |
dof_t *d; |
875 |
const mtx_block_t *mbt; |
876 |
mtx_region_t *newblocks; |
877 |
|
878 |
if (sys==NULL) return 1; |
879 |
|
880 |
d = slv_get_dofdata(sys); |
881 |
mbt = slv_get_solvers_blocks(sys); |
882 |
assert(d!=NULL && mbt!=NULL); |
883 |
if (d->structural_rank && mbt->nblocks >1) { |
884 |
newblocks = (mtx_region_t *)ascmalloc(sizeof(mtx_region_t)); |
885 |
if (newblocks == NULL) return 2; |
886 |
newblocks->row.low = newblocks->col.low = 0; |
887 |
newblocks->row.high = d->structural_rank - 1; |
888 |
newblocks->col.high = d->n_cols - 1; |
889 |
if ( newblocks->col.high < 0 || newblocks->row.high < 0) { |
890 |
ascfree(newblocks); |
891 |
return 1; |
892 |
} |
893 |
slv_set_solvers_blocks(sys,1,newblocks); |
894 |
} |
895 |
return 0; |
896 |
} |
897 |
|
898 |
int slv_set_up_block(slv_system_t sys,int bnum) |
899 |
{ |
900 |
struct rel_relation **rp; |
901 |
struct var_variable **vp; |
902 |
mtx_region_t reg; |
903 |
const mtx_block_t *b; |
904 |
int32 c,vlen,rlen; |
905 |
var_filter_t vf; |
906 |
rel_filter_t rf; |
907 |
|
908 |
if (sys==NULL) return 1; |
909 |
rlen = slv_get_num_solvers_rels(sys); |
910 |
vlen = slv_get_num_solvers_vars(sys); |
911 |
if (rlen ==0 || vlen == 0) return 1; |
912 |
|
913 |
rp = slv_get_solvers_rel_list(sys); |
914 |
vp = slv_get_solvers_var_list(sys); |
915 |
assert(rp!=NULL); |
916 |
assert(vp!=NULL); |
917 |
|
918 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK | REL_ACTIVE); |
919 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK | REL_ACTIVE); |
920 |
vf.matchbits =(VAR_INCIDENT |VAR_SVAR | VAR_FIXED |VAR_INBLOCK | VAR_ACTIVE); |
921 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_INBLOCK | VAR_ACTIVE); |
922 |
|
923 |
b = slv_get_solvers_blocks(sys); |
924 |
assert(b!=NULL); |
925 |
if (bnum <0 || bnum >= b->nblocks || b->block == NULL) return 1; |
926 |
reg = b->block[bnum]; |
927 |
for (c=reg.col.low; c<=reg.col.high; c++) { |
928 |
var_set_in_block(vp[c],1); |
929 |
} |
930 |
for (c=reg.row.low; c<=reg.row.high; c++) { |
931 |
rel_set_in_block(rp[c],1); |
932 |
} |
933 |
return 0; |
934 |
} |
935 |
|
936 |
/* returns 0 if ok, OTHERWISE if madness detected. |
937 |
*/ |
938 |
int slv_spk1_reorder_block(slv_system_t sys,int bnum,int transpose) |
939 |
{ |
940 |
struct rel_relation **rp; |
941 |
struct var_variable **vp; |
942 |
mtx_region_t reg; |
943 |
const mtx_block_t *b; |
944 |
mtx_matrix_t mtx; |
945 |
mtx_coord_t coord; |
946 |
int32 c,vlen,rlen; |
947 |
var_filter_t vf; |
948 |
rel_filter_t rf; |
949 |
dof_t *d; |
950 |
|
951 |
if (sys==NULL) return 1; |
952 |
rlen = slv_get_num_solvers_rels(sys); |
953 |
vlen = slv_get_num_solvers_vars(sys); |
954 |
if (rlen ==0 || vlen == 0) return 1; |
955 |
|
956 |
rp = slv_get_solvers_rel_list(sys); |
957 |
vp = slv_get_solvers_var_list(sys); |
958 |
assert(rp!=NULL); |
959 |
assert(vp!=NULL); |
960 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK | REL_ACTIVE); |
961 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK | REL_ACTIVE); |
962 |
vf.matchbits =(VAR_INCIDENT |VAR_SVAR | VAR_FIXED |VAR_INBLOCK | VAR_ACTIVE); |
963 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_INBLOCK | VAR_ACTIVE); |
964 |
|
965 |
mtx = mtx_create(); |
966 |
mtx_set_order(mtx,MAX(rlen,vlen)); |
967 |
b = slv_get_solvers_blocks(sys); |
968 |
assert(b!=NULL); |
969 |
if (bnum <0 || bnum >= b->nblocks || b->block == NULL) return 1; |
970 |
reg = b->block[bnum]; |
971 |
for (c=reg.col.low; c<=reg.col.high; c++) { |
972 |
var_set_in_block(vp[c],1); |
973 |
} |
974 |
for (c=reg.row.low; c<=reg.row.high; c++) { |
975 |
rel_set_in_block(rp[c],1); |
976 |
} |
977 |
if (reg.row.low != reg.col.low || reg.row.high != reg.col.high) { |
978 |
return 1; /* must be square */ |
979 |
/* could also enforce minsize 3x3, but someone my call with a |
980 |
* partitionable region, so don't want to. |
981 |
*/ |
982 |
} |
983 |
|
984 |
if (slv_std_make_incidence_mtx(sys,mtx,&vf,&rf)) { |
985 |
FPRINTF(stderr, |
986 |
"slv_spk1_reorder_block: failure in creating incidence matrix.\n"); |
987 |
mtx_destroy(mtx); |
988 |
return 1; |
989 |
} |
990 |
/* verify that block has no empty columns, though not checking diagonal */ |
991 |
for (c = reg.row.low; c <= reg.row.high; c++) { |
992 |
coord.col = mtx_FIRST; |
993 |
coord.row = c; |
994 |
if (mtx_next_in_row(mtx,&coord,mtx_ALL_COLS), coord.col == mtx_LAST) { |
995 |
mtx_destroy(mtx); |
996 |
FPRINTF(stderr, "slv_spk1_reorder_block: empty row (%d) found.\n",c); |
997 |
return 1; |
998 |
} |
999 |
coord.row = mtx_FIRST; |
1000 |
coord.col = c; |
1001 |
if (mtx_next_in_col(mtx,&coord,mtx_ALL_ROWS), coord.row == mtx_LAST) { |
1002 |
FPRINTF(stderr, "slv_spk1_reorder_block: empty col (%d) found.\n",c); |
1003 |
mtx_destroy(mtx); |
1004 |
return 1; |
1005 |
} |
1006 |
} |
1007 |
if (transpose) { |
1008 |
mtx_reorder(mtx,®,mtx_TSPK1); |
1009 |
} else { |
1010 |
mtx_reorder(mtx,®,mtx_SPK1); |
1011 |
} |
1012 |
if (reindex_vars_from_mtx(sys,reg.col.low,reg.col.high,mtx)) { |
1013 |
mtx_destroy(mtx); |
1014 |
return 2; |
1015 |
} |
1016 |
if (reindex_rels_from_mtx(sys,reg.row.low,reg.row.high,mtx)) { |
1017 |
mtx_destroy(mtx); |
1018 |
return 2; |
1019 |
} |
1020 |
d = slv_get_dofdata(sys); |
1021 |
d->reorder.block_reordering = 1; /* spk1 */ |
1022 |
|
1023 |
mtx_destroy(mtx); |
1024 |
return 0; |
1025 |
} |
1026 |
|
1027 |
/* global to get around the mr header */ |
1028 |
static |
1029 |
enum mtx_reorder_method g_blockmethod = mtx_UNKNOWN; |
1030 |
|
1031 |
/* |
1032 |
A function to be called on the leftover diagonal blocks of mr_bisect. |
1033 |
This function should be thoroughly investigated, which it has not been. |
1034 |
*/ |
1035 |
static int tear_subreorder(slv_system_t server, |
1036 |
mtx_matrix_t mtx, mtx_region_t *reg) |
1037 |
{ |
1038 |
assert(mtx != NULL && reg !=NULL); |
1039 |
(void)server; |
1040 |
if (g_blockmethod==mtx_UNKNOWN) { |
1041 |
mtx_reorder(mtx,reg,mtx_SPK1); |
1042 |
} else { |
1043 |
mtx_reorder(mtx,reg,g_blockmethod); |
1044 |
} |
1045 |
return 0; |
1046 |
} |
1047 |
|
1048 |
int slv_tear_drop_reorder_block(slv_system_t sys, int32 bnum, |
1049 |
int32 cutoff, int two, |
1050 |
enum mtx_reorder_method blockmethod) |
1051 |
{ |
1052 |
struct rel_relation **rp; |
1053 |
struct var_variable **vp; |
1054 |
const mtx_block_t *b; |
1055 |
dof_t *d; |
1056 |
mr_reorder_t *mrsys; |
1057 |
mtx_matrix_t mtx; |
1058 |
mtx_region_t reg; |
1059 |
mtx_coord_t coord; |
1060 |
int32 c,vlen,rlen,modcount; |
1061 |
var_filter_t vf; |
1062 |
rel_filter_t rf; |
1063 |
|
1064 |
if (sys==NULL) return 1; |
1065 |
rlen = slv_get_num_solvers_rels(sys); |
1066 |
vlen = slv_get_num_solvers_vars(sys); |
1067 |
if (rlen ==0 || vlen == 0) return 1; |
1068 |
|
1069 |
rp = slv_get_solvers_rel_list(sys); |
1070 |
vp = slv_get_solvers_var_list(sys); |
1071 |
assert(rp!=NULL); |
1072 |
assert(vp!=NULL); |
1073 |
rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK | REL_ACTIVE); |
1074 |
rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_INBLOCK| REL_ACTIVE); |
1075 |
vf.matchbits =(VAR_INCIDENT |VAR_SVAR | VAR_FIXED |VAR_INBLOCK | VAR_ACTIVE); |
1076 |
vf.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_INBLOCK | VAR_ACTIVE); |
1077 |
|
1078 |
mtx = mtx_create(); |
1079 |
mtx_set_order(mtx,MAX(rlen,vlen)); |
1080 |
b = slv_get_solvers_blocks(sys); |
1081 |
assert(b!=NULL); /* probably shouldn't be an assert here ... */ |
1082 |
if (bnum <0 || bnum >= b->nblocks || b->block == NULL) { |
1083 |
mtx_destroy(mtx); |
1084 |
return 1; |
1085 |
} |
1086 |
reg = b->block[bnum]; |
1087 |
/* do the flag setting even if we don't do the reorder */ |
1088 |
for (c=reg.col.low; c<=reg.col.high; c++) { |
1089 |
var_set_in_block(vp[c],1); |
1090 |
} |
1091 |
for (c=reg.row.low; c<=reg.row.high; c++) { |
1092 |
rel_set_in_block(rp[c],1); |
1093 |
} |
1094 |
if (reg.row.low != reg.col.low || reg.row.high != reg.col.high) { |
1095 |
mtx_destroy(mtx); |
1096 |
return 1; /* must be square */ |
1097 |
} |
1098 |
if (reg.row.high - reg.row.low < 3) { |
1099 |
mtx_destroy(mtx); |
1100 |
return 0; /* must be 3x3 or bigger to have any effect */ |
1101 |
} |
1102 |
|
1103 |
if (slv_std_make_incidence_mtx(sys,mtx,&vf,&rf)) { |
1104 |
FPRINTF(stderr, |
1105 |
"slv_tear_drop_reorder_block: failure in creating incidence matrix.\n"); |
1106 |
mtx_destroy(mtx); |
1107 |
return 1; |
1108 |
} |
1109 |
/* verify that block has no empty columns, though not checking diagonal */ |
1110 |
for (c = reg.row.low; c <= reg.row.high; c++) { |
1111 |
coord.col = mtx_FIRST; |
1112 |
coord.row = c; |
1113 |
if (mtx_next_in_row(mtx,&coord,mtx_ALL_COLS), coord.col == mtx_LAST) { |
1114 |
mtx_destroy(mtx); |
1115 |
FPRINTF(stderr, "slv_tear_drop_reorder_block: empty row (%d) found.\n",c); |
1116 |
return 1; |
1117 |
} |
1118 |
coord.row = mtx_FIRST; |
1119 |
coord.col = c; |
1120 |
if (mtx_next_in_col(mtx,&coord,mtx_ALL_ROWS), coord.row == mtx_LAST) { |
1121 |
FPRINTF(stderr, "slv_tear_drop_reorder_block: empty col (%d) found.\n",c); |
1122 |
mtx_destroy(mtx); |
1123 |
return 1; |
1124 |
} |
1125 |
} |
1126 |
|
1127 |
modcount = slv_get_num_models(sys); |
1128 |
mrsys = mr_reorder_create(sys,mtx,modcount); |
1129 |
if (mrsys==NULL) return 1; |
1130 |
mrsys->cutoff = cutoff; |
1131 |
g_blockmethod = blockmethod; |
1132 |
if (!two) { |
1133 |
mr_bisect_partition(mrsys,®,1,tear_subreorder); |
1134 |
} else { |
1135 |
mr_bisect_partition2(mrsys,®,1,tear_subreorder); |
1136 |
} |
1137 |
#if 1 |
1138 |
FPRINTF(stderr,"Model-based reordering: (tear-style = %d)\n",two); |
1139 |
FPRINTF(stderr,"Min. tearable size:\t%d\n",mrsys->cutoff); |
1140 |
FPRINTF(stderr,"Tears:\t\t%d\n",mrsys->ntears); |
1141 |
FPRINTF(stderr,"Partitionings:\t%d\n",mrsys->nblts); |
1142 |
#endif |
1143 |
reg = b->block[bnum]; /* bisect likely munged reg */ |
1144 |
if (reindex_vars_from_mtx(sys,reg.col.low,reg.col.high,mtx)) { |
1145 |
mtx_destroy(mtx); |
1146 |
mr_reorder_destroy(mrsys); |
1147 |
return 2; |
1148 |
} |
1149 |
if (reindex_rels_from_mtx(sys,reg.row.low,reg.row.high,mtx)) { |
1150 |
mtx_destroy(mtx); |
1151 |
mr_reorder_destroy(mrsys); |
1152 |
return 2; |
1153 |
} |
1154 |
d = slv_get_dofdata(sys); |
1155 |
d->reorder.block_reordering = 2; /* tear_drop_baa */ |
1156 |
|
1157 |
mtx_destroy(mtx); |
1158 |
mr_reorder_destroy(mrsys); |
1159 |
return 0; |
1160 |
} |
1161 |
|
1162 |
int slv_insure_bounds(slv_system_t sys,int32 lo,int32 hi, FILE *mif) |
1163 |
{ |
1164 |
real64 val,low,high; |
1165 |
int32 c,nchange=0; |
1166 |
struct var_variable *var, **vp; |
1167 |
|
1168 |
vp = slv_get_solvers_var_list(sys); |
1169 |
if (vp==NULL) return -1; |
1170 |
for (c= lo; c <= hi; c++) { |
1171 |
var = vp[c]; |
1172 |
low = var_lower_bound(var); |
1173 |
high = var_upper_bound(var); |
1174 |
val = var_value(var); |
1175 |
if( low > high ) { |
1176 |
if (mif!=NULL) { |
1177 |
FPRINTF(mif,"Bounds for variable "); |
1178 |
var_write_name(sys,var,mif); |
1179 |
FPRINTF(mif," are inconsistent [%g,%g].\n",low,high); |
1180 |
FPRINTF(mif,"Bounds will be swapped.\n"); |
1181 |
} |
1182 |
var_set_upper_bound(var, low); |
1183 |
var_set_lower_bound(var, high); |
1184 |
low = var_lower_bound(var); |
1185 |
high = var_upper_bound(var); |
1186 |
nchange++; |
1187 |
} |
1188 |
|
1189 |
if( low > val ) { |
1190 |
if (mif!=NULL) { |
1191 |
FPRINTF(mif,"Variable "); |
1192 |
var_write_name(sys,var,mif); |
1193 |
FPRINTF(mif," was initialized below its lower bound.\n"); |
1194 |
FPRINTF(mif,"It will be moved to its lower bound.\n"); |
1195 |
} |
1196 |
var_set_value(var, low); |
1197 |
} else { |
1198 |
if( val > high ) { |
1199 |
if (mif!=NULL) { |
1200 |
FPRINTF(mif,"Variable "); |
1201 |
var_write_name(sys,var,mif); |
1202 |
FPRINTF(mif," was initialized above its upper bound.\n"); |
1203 |
FPRINTF(mif,"It will be moved to its upper bound.\n"); |
1204 |
} |
1205 |
var_set_value(var, high); |
1206 |
nchange++; |
1207 |
} |
1208 |
} |
1209 |
} |
1210 |
return nchange; |
1211 |
} |
1212 |
|
1213 |
void slv_check_bounds(const slv_system_t sys,int32 lo,int32 hi, |
1214 |
FILE *mif,const char *label) |
1215 |
{ |
1216 |
real64 val,low,high; |
1217 |
int32 c,len; |
1218 |
struct var_variable *var, **vp; |
1219 |
static char defaultlabel[] = ""; |
1220 |
|
1221 |
if (label==NULL) label = defaultlabel; |
1222 |
if (sys==NULL || mif == NULL) return; |
1223 |
vp = slv_get_solvers_var_list(sys); |
1224 |
if (vp==NULL) return; |
1225 |
len = slv_get_num_solvers_vars(sys); |
1226 |
if (lo > len || hi > len) { |
1227 |
FPRINTF(stderr,"slv_check_bounds miscalled\n"); |
1228 |
return; |
1229 |
} |
1230 |
for (c= lo; c <= hi; c++) { |
1231 |
var = vp[c]; |
1232 |
low = var_lower_bound(var); |
1233 |
high = var_upper_bound(var); |
1234 |
val = var_value(var); |
1235 |
if( low > high ) { |
1236 |
FPRINTF(mif,"Bounds for %s variable ",label); |
1237 |
var_write_name(sys,var,mif); |
1238 |
FPRINTF(mif,"\nare inconsistent [%g,%g].\n",low,high); |
1239 |
} |
1240 |
|
1241 |
if( low > val ) { |
1242 |
FPRINTF(mif,"%s variable ",label); |
1243 |
var_write_name(sys,var,mif); |
1244 |
FPRINTF(mif,"\nwas initialized below its lower bound.\n"); |
1245 |
} else { |
1246 |
if( val > high ) { |
1247 |
FPRINTF(mif,"%s variable ",label); |
1248 |
var_write_name(sys,var,mif); |
1249 |
FPRINTF(mif," was initialized above its upper bound.\n"); |
1250 |
} |
1251 |
} |
1252 |
} |
1253 |
return; |
1254 |
} |
1255 |
|
1256 |
int SlvRegisterStandardClients(void) |
1257 |
{ |
1258 |
int nclients = 0; |
1259 |
int status; |
1260 |
#ifdef STATIC_SLV |
1261 |
status = slv_register_client(slv0_register,NULL,NULL); |
1262 |
if (status) { |
1263 |
FPRINTF(stderr,"Unable to register slv0.\n"); |
1264 |
} else { |
1265 |
nclients++; |
1266 |
} |
1267 |
#endif |
1268 |
#ifdef STATIC_MINOS |
1269 |
status = slv_register_client(slv1_register,NULL,NULL); |
1270 |
if (status) { |
1271 |
FPRINTF(stderr,"Unable to register slv1.\n"); |
1272 |
} else { |
1273 |
nclients++; |
1274 |
} |
1275 |
#endif |
1276 |
#ifdef STATIC_QRSLV |
1277 |
status = slv_register_client(slv3_register,NULL,NULL); |
1278 |
if (status) { |
1279 |
FPRINTF(stderr,"Unable to register slv3.\n"); |
1280 |
} else { |
1281 |
nclients++; |
1282 |
} |
1283 |
#endif |
1284 |
#ifdef STATIC_CSLV |
1285 |
status = slv_register_client(slv4_register,NULL,NULL); |
1286 |
if (status) { |
1287 |
FPRINTF(stderr,"Unable to register slv4.\n"); |
1288 |
} else { |
1289 |
nclients++; |
1290 |
} |
1291 |
#endif |
1292 |
#ifdef STATIC_LSSLV |
1293 |
status = slv_register_client(slv5_register,NULL,NULL); |
1294 |
if (status) { |
1295 |
FPRINTF(stderr,"Unable to register slv5.\n"); |
1296 |
} else { |
1297 |
nclients++; |
1298 |
} |
1299 |
#endif |
1300 |
#ifdef STATIC_MPS |
1301 |
status = slv_register_client(slv6_register,NULL,NULL); |
1302 |
if (status) { |
1303 |
FPRINTF(stderr,"Unable to register slv6.\n"); |
1304 |
} else { |
1305 |
nclients++; |
1306 |
} |
1307 |
#endif |
1308 |
#ifdef STATIC_NGSLV |
1309 |
status = slv_register_client(slv7_register,NULL,NULL); |
1310 |
if (status) { |
1311 |
FPRINTF(stderr,"Unable to register slv7.\n"); |
1312 |
} else { |
1313 |
nclients++; |
1314 |
} |
1315 |
#endif |
1316 |
#ifdef STATIC_OPTSQP |
1317 |
status = slv_register_client(slv2_register,NULL,NULL); |
1318 |
if (status) { |
1319 |
FPRINTF(stderr,"Unable to register slv2.\n"); |
1320 |
} else { |
1321 |
nclients++; |
1322 |
} |
1323 |
#endif |
1324 |
#if (defined(STATIC_CONOPT) || defined(DYNAMIC_CONOPT)) |
1325 |
status = slv_register_client(slv8_register,NULL,NULL); |
1326 |
if (status) { |
1327 |
FPRINTF(stderr,"Unable to register slv8.\n"); |
1328 |
} else { |
1329 |
nclients++; |
1330 |
} |
1331 |
#endif |
1332 |
#ifdef STATIC_CMSLV |
1333 |
status = slv_register_client(slv9_register,NULL,NULL); |
1334 |
if (status) { |
1335 |
FPRINTF(stderr,"Unable to register slv9.\n"); |
1336 |
} else { |
1337 |
nclients++; |
1338 |
} |
1339 |
#endif |
1340 |
#ifdef STATIC_LRSLV |
1341 |
status = slv_register_client(slv9a_register,NULL,NULL); |
1342 |
if (status) { |
1343 |
FPRINTF(stderr,"Unable to register slv9a.\n"); |
1344 |
} else { |
1345 |
nclients++; |
1346 |
} |
1347 |
#endif |
1348 |
return nclients; |
1349 |
} |
1350 |
|
1351 |
|
1352 |
|
1353 |
/************************************************************************\ |
1354 |
Output Assignment and partitiong in Logical Relations |
1355 |
\************************************************************************/ |
1356 |
|
1357 |
#define MLIMDEBUG 0 |
1358 |
/* |
1359 |
* Populates a matrix according to the sys solvers_dvars, solvers_logrels |
1360 |
* lists and the filters given. mtx given must be created (not null) |
1361 |
* and with order >= MAX( slv_get_num_solvers_logrels(sys), |
1362 |
* slv_get_num_solvers_dvars(sys)); |
1363 |
* returns 0 if went ok. |
1364 |
*/ |
1365 |
int slv_std_make_log_incidence_mtx(slv_system_t sys, mtx_matrix_t mtx, |
1366 |
dis_filter_t *dvf,logrel_filter_t *lrf) |
1367 |
{ |
1368 |
#if MLIMDEBUG |
1369 |
FILE *fp; |
1370 |
#endif |
1371 |
int32 lr, lrlen,ord; |
1372 |
struct logrel_relation **lrp; |
1373 |
|
1374 |
if (sys==NULL || mtx == NULL || dvf == NULL || lrf == NULL) { |
1375 |
FPRINTF(stderr,"make_log_incidence called with null\n"); |
1376 |
return 1; |
1377 |
} |
1378 |
lrp = slv_get_solvers_logrel_list(sys); |
1379 |
assert(lrp!=NULL); |
1380 |
lrlen = slv_get_num_solvers_logrels(sys); |
1381 |
ord = MAX(lrlen,slv_get_num_solvers_dvars(sys)); |
1382 |
if (ord > mtx_order(mtx)) { |
1383 |
FPRINTF(stderr,"make_incidence called with undersized matrix\n"); |
1384 |
return 2; |
1385 |
} |
1386 |
for (lr=0; lr < lrlen; lr++) { |
1387 |
if (logrel_apply_filter(lrp[lr],lrf)) { |
1388 |
logrelman_get_incidence(lrp[lr],dvf,mtx); |
1389 |
} |
1390 |
} |
1391 |
#if MLIMDEBUG |
1392 |
fp = fopen("/tmp/mim.plot","w+"); |
1393 |
if (fp !=NULL) { |
1394 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
1395 |
fclose(fp); |
1396 |
} |
1397 |
#endif |
1398 |
return 0; |
1399 |
} |
1400 |
|
1401 |
#if USEDCODE |
1402 |
|
1403 |
/* returns 0 if successful, 1 if insufficient memory. Does not change |
1404 |
* the data in mtx. Orders the solvers_dvar list of the system to |
1405 |
* match the permutation on the given mtx. It is assumed that |
1406 |
* the org cols of mtx == dvar list position. Only the |
1407 |
* dvars in range lo to hi of the dvar list are affected and |
1408 |
* only these dvars should appear in the same org column range of |
1409 |
* the mtx. This should not be called on blocks less than 3x3. |
1410 |
*/ |
1411 |
static int reindex_dvars_from_mtx(slv_system_t sys, int32 lo, int32 hi, |
1412 |
const mtx_matrix_t mtx) |
1413 |
{ |
1414 |
struct dis_discrete **dvtmp, **dvp; |
1415 |
int32 c,v,vlen; |
1416 |
|
1417 |
if (lo >= hi +1) return 0; /* job too small */ |
1418 |
dvp = slv_get_solvers_dvar_list(sys); |
1419 |
vlen = slv_get_num_solvers_dvars(sys); |
1420 |
/* on dvtmp we DONT have the terminating null */ |
1421 |
dvtmp = (struct dis_discrete **) |
1422 |
ascmalloc(vlen*sizeof(struct dis_discrete *)); |
1423 |
if (dvtmp == NULL) { |
1424 |
return 1; |
1425 |
} |
1426 |
/* copy pointers to dvtmp in order desired and copy back rather than sort */ |
1427 |
for (c=lo;c<=hi;c++) { |
1428 |
v = mtx_col_to_org(mtx,c); |
1429 |
dvtmp[c] = dvp[v]; |
1430 |
} |
1431 |
/* copying back and re-sindexing */ |
1432 |
for (c=lo;c<=hi;c++) { |
1433 |
dvp[c] = dvtmp[c]; |
1434 |
dis_set_sindex(dvp[c],c); |
1435 |
} |
1436 |
ascfree(dvtmp); |
1437 |
return 0; |
1438 |
} |
1439 |
|
1440 |
/* returns 0 if successful, 1 if insufficient memory. Does not change |
1441 |
* the data in mtx. Orders the solvers_logrel list of the system to |
1442 |
* match the permutation on the given mtx. It is assumed that |
1443 |
* the org rows of mtx == logrel list position. Only the |
1444 |
*logrels in range lo to hi of the logrel list are affected and |
1445 |
* only these logrels should appear in the same org row range of |
1446 |
* the input mtx. This should not be called on blocks less than 3x3. |
1447 |
*/ |
1448 |
static int reindex_logrels_from_mtx(slv_system_t sys, int32 lo, int32 hi, |
1449 |
const mtx_matrix_t mtx) |
1450 |
{ |
1451 |
struct logrel_relation **lrtmp, **lrp; |
1452 |
int32 c,v,rlen; |
1453 |
|
1454 |
lrp = slv_get_solvers_logrel_list(sys); |
1455 |
rlen = slv_get_num_solvers_logrels(sys); |
1456 |
/* on lrtmp we DONT have the terminating null */ |
1457 |
lrtmp = (struct logrel_relation **) |
1458 |
ascmalloc(rlen*sizeof(struct logrel_relation *)); |
1459 |
if (lrtmp == NULL) { |
1460 |
return 1; |
1461 |
} |
1462 |
/* copy pointers to lrtmp in order desired and copy back rather than sort. |
1463 |
* do this only in the row range of interest. */ |
1464 |
for (c=lo;c<=hi;c++) { |
1465 |
v = mtx_row_to_org(mtx,c); |
1466 |
#if RIDEBUG |
1467 |
FPRINTF(stderr,"Old logrel sindex(org) %d becoming sindex(cur) %d\n",v,c); |
1468 |
#endif |
1469 |
lrtmp[c] = lrp[v]; |
1470 |
} |
1471 |
/* copying back and re-sindexing */ |
1472 |
for (c=lo;c<=hi;c++) { |
1473 |
lrp[c] = lrtmp[c]; |
1474 |
logrel_set_sindex(lrp[c],c); |
1475 |
} |
1476 |
ascfree(lrtmp); |
1477 |
return 0; |
1478 |
} |
1479 |
|
1480 |
#endif /* USEDCODE */ |
1481 |
|
1482 |
/* |
1483 |
* returns 0 if ok, OTHERWISE if madness detected. |
1484 |
*/ |
1485 |
#define SLBPDEBUG 0 |
1486 |
int slv_log_block_partition(slv_system_t sys) |
1487 |
{ |
1488 |
#if SLBPDEBUG |
1489 |
FILE *fp; |
1490 |
#endif |
1491 |
struct logrel_relation **lrp; |
1492 |
struct dis_discrete **dvp; |
1493 |
mtx_region_t *newblocks; |
1494 |
dof_t *d; |
1495 |
int32 nrow,ncol; |
1496 |
int32 ncolpfix, nrowpun, vlenmnv; |
1497 |
mtx_matrix_t mtx; |
1498 |
int32 order, rank; |
1499 |
int32 c,len,dvlen,r,lrlen; |
1500 |
dis_filter_t dvf; |
1501 |
logrel_filter_t lrf; |
1502 |
|
1503 |
lrp = slv_get_solvers_logrel_list(sys); |
1504 |
dvp = slv_get_solvers_dvar_list(sys); |
1505 |
lrlen = slv_get_num_solvers_logrels(sys); |
1506 |
dvlen = slv_get_num_solvers_dvars(sys); |
1507 |
if (lrlen ==0 || dvlen == 0) return 1; |
1508 |
order = MAX(lrlen,dvlen); |
1509 |
|
1510 |
lrf.matchbits = (LOGREL_ACTIVE); |
1511 |
lrf.matchvalue = (LOGREL_ACTIVE); |
1512 |
dvf.matchbits = (DIS_INCIDENT | DIS_BVAR | DIS_ACTIVE); |
1513 |
dvf.matchvalue = (DIS_INCIDENT | DIS_BVAR | DIS_ACTIVE); |
1514 |
|
1515 |
/* nrow plus unincluded logrels */ |
1516 |
nrowpun = slv_count_solvers_logrels(sys,&lrf); |
1517 |
/* ncol plus fixed discrete vars */ |
1518 |
ncolpfix = slv_count_solvers_dvars(sys,&dvf); |
1519 |
|
1520 |
dvf.matchbits = (DIS_BVAR); |
1521 |
dvf.matchvalue = 0; |
1522 |
|
1523 |
/* dvlen minus non boolean vars */ |
1524 |
vlenmnv = dvlen - slv_count_solvers_dvars(sys,&dvf); |
1525 |
|
1526 |
lrf.matchbits = (LOGREL_INCLUDED | LOGREL_ACTIVE); |
1527 |
lrf.matchvalue = (LOGREL_INCLUDED | LOGREL_ACTIVE); |
1528 |
dvf.matchbits = (DIS_INCIDENT | DIS_BVAR | DIS_FIXED | DIS_ACTIVE); |
1529 |
dvf.matchvalue = (DIS_INCIDENT | DIS_BVAR | DIS_ACTIVE); |
1530 |
|
1531 |
nrow = slv_count_solvers_logrels(sys,&lrf); |
1532 |
ncol = slv_count_solvers_dvars(sys,&dvf); |
1533 |
|
1534 |
mtx = slv_get_sys_mtx(sys); |
1535 |
mtx_set_order(mtx,order); |
1536 |
|
1537 |
if (slv_std_make_log_incidence_mtx(sys,mtx,&dvf,&lrf)) { |
1538 |
FPRINTF(stderr, |
1539 |
"slv_log_block_partition: failure in creating incidence matrix.\n"); |
1540 |
mtx_destroy(mtx); |
1541 |
return 1; |
1542 |
} |
1543 |
|
1544 |
mtx_output_assign(mtx,lrlen,dvlen); |
1545 |
rank = mtx_symbolic_rank(mtx); |
1546 |
if (rank == 0 ) return 1; |
1547 |
if (rank < nrow) { |
1548 |
FPRINTF(stderr,"rank<nrow in slv_log_block_partition\n"); |
1549 |
FPRINTF(stderr,"dependent logical relations ? \n"); |
1550 |
} |
1551 |
if (rank < ncol) { |
1552 |
if ( nrow != rank) { |
1553 |
FPRINTF(stderr,"rank<ncol and nrow!=rank in slv_log_block_partition.\n"); |
1554 |
FPRINTF(stderr,"Excess of columns ? \n"); |
1555 |
} else { |
1556 |
FPRINTF(stderr,"rank<ncol but nrow==rank in slv_log_block_partition.\n"); |
1557 |
FPRINTF(stderr,"Degrees of freedom ? \n"); |
1558 |
} |
1559 |
} |
1560 |
if (ncol == nrow) { |
1561 |
if (ncol == rank) { |
1562 |
FPRINTF(stderr,"\n"); |
1563 |
FPRINTF(stderr, |
1564 |
"System of logical relations does not need Logic Inference \n"); |
1565 |
} |
1566 |
if (ncol != rank) { |
1567 |
FPRINTF(stderr,"but ncol!=rank.\n"); |
1568 |
FPRINTF(stderr,"Rank deficient ? \n"); |
1569 |
} else { |
1570 |
FPRINTF(stderr,"\n"); |
1571 |
} |
1572 |
} |
1573 |
mtx_partition(mtx); |
1574 |
/* copy the block list. there is at least one if rank >=1 as above */ |
1575 |
len = mtx_number_of_blocks(mtx); |
1576 |
newblocks = (mtx_region_t *)ascmalloc(len*sizeof(mtx_region_t)); |
1577 |
if (newblocks == NULL) { |
1578 |
mtx_destroy(mtx); |
1579 |
return 2; |
1580 |
} |
1581 |
for (c = 0 ; c < len; c++) { |
1582 |
mtx_block(mtx,c,&(newblocks[c])); |
1583 |
} |
1584 |
slv_set_solvers_log_blocks(sys,len,newblocks); /* give it to the system */ |
1585 |
d = slv_get_log_dofdata(sys); |
1586 |
d->structural_rank = rank; |
1587 |
d->n_rows = nrow; |
1588 |
d->n_cols = ncol; |
1589 |
d->n_fixed = ncolpfix - ncol; |
1590 |
d->n_unincluded = nrowpun - nrow; |
1591 |
d->reorder.partition = 1; /* yes */ |
1592 |
d->reorder.basis_selection = 0; /* none yet */ |
1593 |
d->reorder.block_reordering = 0; /* none */ |
1594 |
|
1595 |
#if SLBPDEBUG |
1596 |
fp = fopen("/tmp/sbp1.plot","w+"); |
1597 |
if (fp !=NULL) { |
1598 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
1599 |
fclose(fp); |
1600 |
} |
1601 |
#endif |
1602 |
|
1603 |
|
1604 |
len = vlenmnv - 1; /* row of last possible boolean variable */ |
1605 |
for (c=ncol; len > c ; ) { /* sort the fixed out of inactive */ |
1606 |
r = mtx_col_to_org(mtx,c); |
1607 |
if ( dis_fixed(dvp[r]) && dis_active(dvp[r])) { |
1608 |
c++; |
1609 |
} else { |
1610 |
mtx_swap_cols(mtx,c,len); |
1611 |
len--; |
1612 |
} |
1613 |
} |
1614 |
|
1615 |
/* Now, leftover columns are where we want them. |
1616 |
* That is, unassigned incidence is next to assigned and fixed on right with |
1617 |
* no columns which do not correspond to dis vars in the range 0..dvlen-1. |
1618 |
*/ |
1619 |
/* there aren't any nonincident dvars in the solvers dvarlist, so |
1620 |
* we now have the columns in |assigned|dof|fixed|inactive|nonvars| order */ |
1621 |
|
1622 |
/* rows 0->lrlen-1 should be actual logrels, though, and not phantoms. |
1623 |
* At this point we should have |
1624 |
* rows - assigned |
1625 |
* - unassigned w/incidence |
1626 |
* - unincluded and included w/out free incidence and inactive mixed. |
1627 |
*/ |
1628 |
|
1629 |
/* sort unincluded logrelations to bottom of good region */ |
1630 |
/* this is needed because the idiot user may have fixed everything */ |
1631 |
/* in a logrelation, but we want those rows not to be confused with */ |
1632 |
/* unincluded rows.*/ |
1633 |
len = lrlen - 1; /* row of last possible relation */ |
1634 |
/* sort the inactive out of the unassigned/unincluded */ |
1635 |
for (c=rank; len > c ; ) { |
1636 |
r = mtx_row_to_org(mtx,c); |
1637 |
if ( logrel_active(lrp[r])) { |
1638 |
c++; |
1639 |
} else { |
1640 |
mtx_swap_rows(mtx,c,len); |
1641 |
len--; |
1642 |
} |
1643 |
} |
1644 |
|
1645 |
/* sort the unincluded out of the unassigned */ |
1646 |
len = nrowpun - 1; /* row of last possible unassigned/unincluded relation */ |
1647 |
for (c=rank; len > c ; ) { |
1648 |
r = mtx_row_to_org(mtx,c); |
1649 |
if ( logrel_included(lrp[r]) ) { |
1650 |
c++; |
1651 |
} else { |
1652 |
mtx_swap_rows(mtx,c,len); |
1653 |
len--; |
1654 |
} |
1655 |
} |
1656 |
|
1657 |
#if SBPDEBUG |
1658 |
fp = fopen("/tmp/sbp2.plot","w+"); |
1659 |
if (fp !=NULL) { |
1660 |
mtx_write_region_plot(fp,mtx,mtx_ENTIRE_MATRIX); |
1661 |
fclose(fp); |
1662 |
} |
1663 |
#endif |
1664 |
|
1665 |
/* These functions are called for slv_block_partitioning, but I do not |
1666 |
* know if I need them here: |
1667 |
* |
1668 |
* now, at last we have cols in the order we want the lists to |
1669 |
* be handed to the solver. So, we need to reset the dvar sindex values |
1670 |
* and reorder the lists. |
1671 |
*/ |
1672 |
|
1673 |
#if USEDCODE |
1674 |
if (reindex_dvars_from_mtx(sys,0,dvlen-1,mtx)) { |
1675 |
mtx_destroy(mtx); |
1676 |
return 2; |
1677 |
} |
1678 |
#endif /* USEDCODE */ |
1679 |
|
1680 |
/* |
1681 |
* now, at last we have rows jacobian in the order we want the lists to |
1682 |
* be handed to the solvers. So, we need to reset the rel sindex values. |
1683 |
*/ |
1684 |
|
1685 |
#if USEDCODE |
1686 |
if (reindex_logrels_from_mtx(sys,0,lrlen-1,mtx)) { |
1687 |
mtx_destroy(mtx); |
1688 |
return 2; |
1689 |
} |
1690 |
#endif /* USEDCODE */ |
1691 |
|
1692 |
return 0; |
1693 |
} |
1694 |
|