1 |
/* |
2 |
* SLV: Ascend Numeric Solver |
3 |
* by Karl Michael Westerberg |
4 |
* Created: 2/6/90 |
5 |
* Version: $Revision: 1.23 $ |
6 |
* Version control file: $RCSfile: slv_interface.c,v $ |
7 |
* Date last modified: $Date: 1998/01/11 17:19:09 $ |
8 |
* Last modified by: $Author: ballan $ |
9 |
* |
10 |
* This file is part of the SLV solver. |
11 |
* |
12 |
* Copyright (C) 1990 Karl Michael Westerberg, Thomas Guthrie Epperly |
13 |
* Copyright (C) 1993 Joseph Zaher |
14 |
* Copyright (C) 1994 Joseph Zaher, Benjamin Andrew Allan |
15 |
* |
16 |
* The SLV solver is free software; you can redistribute |
17 |
* it and/or modify it under the terms of the GNU General Public License as |
18 |
* published by the Free Software Foundation; either version 2 of the |
19 |
* License, or (at your option) any later version. |
20 |
* |
21 |
* The SLV solver is distributed in hope that it will be |
22 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
24 |
* General Public License for more details. |
25 |
* |
26 |
* You should have received a copy of the GNU General Public License along with |
27 |
* the program; if not, write to the Free Software Foundation, Inc., 675 |
28 |
* Mass Ave, Cambridge, MA 02139 USA. Check the file named COPYING. |
29 |
* COPYING is found in ../compiler. |
30 |
*/ |
31 |
|
32 |
/** |
33 |
*** This file defines the function Solve(struct Instance *inst), which is |
34 |
*** swiped from solver/chris.h. This module will instead use Karl's |
35 |
*** solver. (was newascend/compiler/chris.h on wetterhorn) |
36 |
*** much of slv_interface.h is not yet implemented for SLV. |
37 |
**/ |
38 |
|
39 |
#include "utilities/ascConfig.h" |
40 |
#include "utilities/ascSignal.h" |
41 |
#include "compiler/instance_enum.h" |
42 |
#include "compiler/fractions.h" |
43 |
#include "compiler/compiler.h" |
44 |
#include "utilities/ascMalloc.h" |
45 |
#include "compiler/dimen.h" |
46 |
#include "utilities/readln.h" |
47 |
#include "solver/mtx.h" |
48 |
#include "solver/slv_types.h" |
49 |
#include "solver/var.h" |
50 |
#include "solver/rel.h" |
51 |
#include "solver/discrete.h" |
52 |
#include "solver/conditional.h" |
53 |
#include "solver/logrel.h" |
54 |
#include "solver/bnd.h" |
55 |
#include "solver/calc.h" |
56 |
#include "solver/relman.h" |
57 |
#include "solver/slv_common.h" |
58 |
#include "solver/linsol.h" |
59 |
#include "solver/linsolqr.h" |
60 |
#include "solver/slv_client.h" /* should be client ... */ |
61 |
#include "solver/system.h" |
62 |
#include "solver/slv_interface.h" /* Implementation of this */ |
63 |
#include "interface/checkdim.h" |
64 |
#include "interface/plot.h" |
65 |
|
66 |
#define prompt printf |
67 |
|
68 |
#define yorn(b) ((b) ? "YES" : "NO") |
69 |
#define torf(b) ((b) ? "TRUE" : "FALSE") |
70 |
|
71 |
#define SAFE_FIX_ME 0 |
72 |
|
73 |
#define C_NOP 0 |
74 |
#define C_RETURN 1 |
75 |
#define C_HELP 2 |
76 |
#define C_INPUT_PARAMETERS 3 |
77 |
#define C_OUTPUT_PARAMETERS 4 |
78 |
#define C_OUTPUT_STATUS 5 |
79 |
#define C_COUNT 6 |
80 |
#define C_COUNT_IN_BLOCK 7 |
81 |
#define C_WRITE_VAR 8 |
82 |
#define C_WRITE_VARS 9 |
83 |
#define C_WRITE_VARS_IN_BLOCK 10 |
84 |
#define C_TOGGLE_SUPPRESS_REL 11 |
85 |
#define C_WRITE_REL 12 |
86 |
#define C_WRITE_RELS 13 |
87 |
#define C_WRITE_RELS_IN_BLOCK 14 |
88 |
#define C_WRITE_OBJ 15 |
89 |
#define C_CHECK_DIMENSIONS 16 |
90 |
#define C_ELIGIBLE_SOLVERS 17 |
91 |
#define C_SELECT_SOLVER 18 |
92 |
#define C_SELECTED_SOLVER 19 |
93 |
#define C_PRESOLVE 20 |
94 |
#define C_RESOLVE 21 |
95 |
#define C_ITERATE 22 |
96 |
#define C_SOLVE 23 |
97 |
#define C_DUMP_SYSTEM 25 |
98 |
#define C_PLOT 26 |
99 |
|
100 |
static struct command_list_t { |
101 |
char *name; |
102 |
char *descr; |
103 |
int num; |
104 |
} commands[] = { |
105 |
{ "", "", C_NOP } , |
106 |
{ "return", "Returns to ascend", C_RETURN } , |
107 |
{ "quit", "Returns to ascend", C_RETURN } , |
108 |
{ "bye", "Returns to ascend", C_RETURN } , |
109 |
{ "?", "Prints out this list", C_HELP } , |
110 |
{ "help", "Prints out this list", C_HELP } , |
111 |
{ "input parameters", "Input solver parameters", C_INPUT_PARAMETERS } , |
112 |
{ "output parameters", "Output solver parameters", C_OUTPUT_PARAMETERS } , |
113 |
{ "output status", "Output solver status", C_OUTPUT_STATUS } , |
114 |
{ "count", "Counts variables/relations", C_COUNT } , |
115 |
{ "count in block", "Counts variables/relations in block", |
116 |
C_COUNT_IN_BLOCK } , |
117 |
{ "write var" , "Writes one variable" , C_WRITE_VAR } , |
118 |
{ "write vars" , "Writes complete variable list" , C_WRITE_VARS } , |
119 |
{ "write vars in block" , "Writes variables in current block" , |
120 |
C_WRITE_VARS_IN_BLOCK } , |
121 |
{ "toggle suppress rel" , "Toggles the suppress-relation-flag" , |
122 |
C_TOGGLE_SUPPRESS_REL } , |
123 |
{ "write rel" , "Writes one relation" , C_WRITE_REL } , |
124 |
{ "write rels" , "Writes complete relation list" , C_WRITE_RELS } , |
125 |
{ "write rels in block" , "Writes relations in current block" , |
126 |
C_WRITE_RELS_IN_BLOCK } , |
127 |
{ "write obj" , "Writes objective function" , C_WRITE_OBJ } , |
128 |
{ "check dimensions" , "Checks global dimensional consistency" , |
129 |
C_CHECK_DIMENSIONS } , |
130 |
{ "eligible solvers" , "Indicates which solvers can solve the problem" , |
131 |
C_ELIGIBLE_SOLVERS } , |
132 |
{ "select solver" , "Allows user to select a solver" , C_SELECT_SOLVER } , |
133 |
{ "selected solver" , "Indicates which solver has been selected" , |
134 |
C_SELECTED_SOLVER } , |
135 |
{ "presolve" , "Pre-solves system" , C_PRESOLVE } , |
136 |
{ "resolve" , "Re-solves system" , C_RESOLVE } , |
137 |
{ "iterate" , "Perform one iteration" , C_ITERATE } , |
138 |
{ "solve" , "Attempts to solve entire system" , C_SOLVE } , |
139 |
{ "dump system" , "Dump solve system to a file" , C_DUMP_SYSTEM } , |
140 |
{ "plot" , "Plots the solve instance" , C_PLOT } |
141 |
}; |
142 |
#define NCOMMANDS array_length(commands) |
143 |
|
144 |
static void print_commands() |
145 |
/** |
146 |
*** Prints out all commands |
147 |
**/ |
148 |
{ |
149 |
int ndx; |
150 |
for( ndx=0 ; ndx < NCOMMANDS ; ++ndx ) |
151 |
PRINTF("%-30s%s\n",commands[ndx].name,commands[ndx].descr); |
152 |
} |
153 |
|
154 |
static int command_number(str) |
155 |
char *str; |
156 |
/** |
157 |
*** Returns number corresponding to command string. |
158 |
*** If non-existent, -1 is returned. |
159 |
**/ |
160 |
{ |
161 |
int i; |
162 |
for( i=0 ; i<NCOMMANDS ; ++i ) |
163 |
if( strcmp(commands[i].name , str) == 0 ) |
164 |
break; /* found it */ |
165 |
return( i < NCOMMANDS ? commands[i].num : -1 ); |
166 |
} |
167 |
|
168 |
static boolean input_boolean(def) |
169 |
boolean def; |
170 |
/** |
171 |
*** Inputs a boolean (true or false) |
172 |
**/ |
173 |
{ |
174 |
char buf[10]; |
175 |
readln(buf,sizeof(buf)); |
176 |
switch( buf[0] ) { |
177 |
case 'y': |
178 |
case 'Y': |
179 |
case 't': |
180 |
case 'T': |
181 |
return(TRUE); |
182 |
case 'n': |
183 |
case 'N': |
184 |
case 'f': |
185 |
case 'F': |
186 |
return(FALSE); |
187 |
default: |
188 |
return(def); |
189 |
} |
190 |
} |
191 |
|
192 |
static int input_command() |
193 |
/** |
194 |
*** Inputs command, returns command number. |
195 |
**/ |
196 |
{ |
197 |
char s[100]; |
198 |
|
199 |
PRINTF("Solver> "); |
200 |
readln(s,sizeof(s)); |
201 |
return( command_number(s) ); |
202 |
} |
203 |
|
204 |
static void write_var(out,sys,var) |
205 |
FILE *out; |
206 |
slv_system_t sys; |
207 |
struct var_variable *var; |
208 |
/** |
209 |
*** Writes a variable out. |
210 |
**/ |
211 |
{ |
212 |
char *name; |
213 |
name = var_make_name(sys,var); |
214 |
if( *name == '?' ) FPRINTF(out,"%d",var_sindex(var)); |
215 |
else FPRINTF(out,"%s",name); |
216 |
ascfree(name); |
217 |
} |
218 |
|
219 |
static void write_rel(out,sys,rel,suppress) |
220 |
FILE *out; |
221 |
slv_system_t sys; |
222 |
struct rel_relation *rel; |
223 |
boolean suppress; |
224 |
/** |
225 |
*** Writes a relation out. |
226 |
**/ |
227 |
{ |
228 |
char *name, *str; |
229 |
name = rel_make_name(sys,rel); |
230 |
if( *name == '?' ) FPRINTF(out,"%d",rel_sindex(rel)); |
231 |
else FPRINTF(out,"%s",name); |
232 |
ascfree(name); |
233 |
if( suppress ) return; |
234 |
PUTC('\n',out); |
235 |
str = relman_make_string_infix(sys,rel); |
236 |
FPRINTF(out,"\t%s\n",str); |
237 |
ascfree(str); |
238 |
} |
239 |
|
240 |
static void write_varlist(out,sys,vfilter,justwritestats) |
241 |
FILE *out; |
242 |
slv_system_t sys; |
243 |
var_filter_t *vfilter; |
244 |
boolean justwritestats; |
245 |
/** |
246 |
*** Writes the variable list for those variables |
247 |
*** passing through filter. |
248 |
**/ |
249 |
{ |
250 |
linsol_system_t lsys; |
251 |
mtx_matrix_t mtx; |
252 |
mtx_region_t reg; |
253 |
int32 col; |
254 |
struct var_variable **vp; |
255 |
int32 num[2][2]; /* num[?fixed][?incident] */ |
256 |
int32 tnum[2]; /* tnum[?incident] */ |
257 |
|
258 |
lsys = slv_get_linsol_sys(sys); |
259 |
mtx = linsol_get_matrix(lsys); |
260 |
FPRINTF(out,"#/block. value (nominal) [LB,UB] "); |
261 |
FPRINTF(out,"?fixed ?incident ?solved - name\n"); |
262 |
num[0][0] = num[0][1] = num[1][0] = num[1][1] = 0; |
263 |
for( vp=slv_get_master_var_list(sys) ; *vp != NULL ; ++vp ) |
264 |
if( var_apply_filter(*vp,vfilter) ) { |
265 |
++num[(int)(var_fixed(*vp)&&var_active(*vp))] |
266 |
[(int)(var_incident(*vp)&&var_active(*vp))]; |
267 |
if( justwritestats ) continue; |
268 |
col = mtx_org_to_col(mtx,var_sindex(*vp)); |
269 |
FPRINTF(out,"%3d/%3d. %14e (%14e) [%14e,%14e] %2s %4s - ", |
270 |
var_sindex(*vp) , mtx_block_containing_col(mtx,col,®) , |
271 |
var_value(*vp),var_nominal(*vp), |
272 |
var_lower_bound(*vp) , var_upper_bound(*vp) , |
273 |
(var_fixed(*vp)&&var_active(*vp))?"FX":"FR", |
274 |
(var_incident(*vp)&&var_active(*vp))?"INC":"!INC"); |
275 |
write_var(out,sys,*vp); |
276 |
PUTC('\n',out); |
277 |
} |
278 |
|
279 |
tnum[0]=num[0][0]+num[1][0]; |
280 |
tnum[1]=num[0][1]+num[1][1]; |
281 |
FPRINTF(out,"# vars free fixed total\n"); |
282 |
FPRINTF(out,"incident %4d %4d %4d\n", |
283 |
num[0][1],num[1][1],tnum[1]); |
284 |
FPRINTF(out,"otherwise %4d %4d %4d\n", |
285 |
num[0][0],num[1][0],tnum[0]); |
286 |
FPRINTF(out,"total %4d %4d %4d\n", |
287 |
num[0][0]+num[0][1],num[1][0]+num[1][1],tnum[0]+tnum[1]); |
288 |
} |
289 |
|
290 |
static void write_rellist(out,sys,rfilter,justwritestats,suppress) |
291 |
FILE *out; |
292 |
slv_system_t sys; |
293 |
rel_filter_t *rfilter; |
294 |
boolean justwritestats; |
295 |
boolean suppress; |
296 |
/** |
297 |
*** Writes the relation list for those relations |
298 |
*** passing through filter. |
299 |
**/ |
300 |
{ |
301 |
linsol_system_t lsys; |
302 |
mtx_matrix_t mtx; |
303 |
mtx_region_t reg; |
304 |
int32 row; |
305 |
struct rel_relation **rp; |
306 |
boolean old_calc_ok; |
307 |
int32 num[2]; /* [?included] */ |
308 |
|
309 |
old_calc_ok = calc_ok; |
310 |
lsys = slv_get_linsol_sys(sys); |
311 |
mtx = linsol_get_matrix(lsys); |
312 |
|
313 |
FPRINTF(out,"#/block. residual ?included - name\\n relation\n"); |
314 |
num[0] = num[1] = 0L; |
315 |
Asc_SignalHandlerPush(SIGFPE,SIG_IGN); |
316 |
for( rp=slv_get_master_rel_list(sys) ; *rp != NULL ; ++rp ) { |
317 |
if( rel_apply_filter(*rp,rfilter) ) { |
318 |
real64 res; |
319 |
|
320 |
++num[(int)(rel_included(*rp) && rel_active(*rp))]; |
321 |
if( justwritestats ) continue; |
322 |
|
323 |
calc_ok = TRUE; |
324 |
res = relman_eval(*rp,&calc_ok,SAFE_FIX_ME); |
325 |
row = mtx_org_to_row(mtx,rel_sindex(*rp)); |
326 |
FPRINTF(out,"%3d/%3d. %c%14e %2s - ", |
327 |
rel_sindex(*rp) , mtx_block_containing_row(mtx,row,®) , |
328 |
calc_ok?' ':'!',res, |
329 |
(rel_included(*rp) && rel_active(*rp))?"IN":"IG"); |
330 |
write_rel(out,sys,*rp,suppress); |
331 |
} |
332 |
} |
333 |
Asc_SignalHandlerPop(SIGFPE,SIG_IGN); |
334 |
FPRINTF(out,"There are %d relations, %d included and %d ignored.\n", |
335 |
num[0]+num[1],num[1],num[0]); |
336 |
calc_ok = old_calc_ok; |
337 |
} |
338 |
|
339 |
static void write_obj(out,sys) |
340 |
FILE *out; |
341 |
slv_system_t sys; |
342 |
/** |
343 |
*** Writes out the objective function. THE SEMANTICS MAY BE WRONG HERE. |
344 |
**/ |
345 |
{ |
346 |
struct rel_relation *obj = slv_get_obj_relation(sys); |
347 |
real64 val; |
348 |
|
349 |
if( obj == NULL ) |
350 |
FPRINTF(out,"Objective: ----NONE---- ( = 0.0)\n"); |
351 |
else { |
352 |
char *str = relman_make_string_infix(sys,obj); |
353 |
Asc_SignalHandlerPush(SIGFPE,SIG_IGN); |
354 |
val = relman_eval(obj,&calc_ok,SAFE_FIX_ME); |
355 |
Asc_SignalHandlerPop(SIGFPE,SIG_IGN); |
356 |
FPRINTF(out,"Objective: %s ( = %g)\n",str,val); |
357 |
ascfree(str); |
358 |
} |
359 |
} |
360 |
|
361 |
static void input_parameters(sys) |
362 |
slv_system_t sys; |
363 |
/* Inputs parameters for the given system. */ |
364 |
{ |
365 |
slv_parameters_t p; |
366 |
|
367 |
slv_get_parameters(sys,&p); |
368 |
|
369 |
PRINTF("Print more important messages? [%s] ", |
370 |
yorn(p.output.more_important!=NULL)); |
371 |
p.output.more_important = input_boolean(p.output.more_important!=NULL) ? |
372 |
stdout : NULL; |
373 |
|
374 |
PRINTF("Print less important messages? [%s] ", |
375 |
yorn(p.output.less_important!=NULL)); |
376 |
p.output.less_important = input_boolean(p.output.less_important!=NULL) ? |
377 |
stdout : NULL; |
378 |
|
379 |
PRINTF("Cpu time limit (in seconds) [%g]: ",p.time_limit); |
380 |
p.time_limit = readdouble(p.time_limit); |
381 |
|
382 |
PRINTF("Iteration limit [%d]: ",p.iteration_limit); |
383 |
p.iteration_limit = readlong((long)p.iteration_limit); |
384 |
|
385 |
PRINTF("Tolerance, singular [%g]: ",p.tolerance.singular); |
386 |
p.tolerance.singular = readdouble(p.tolerance.singular); |
387 |
|
388 |
PRINTF("Tolerance, feasible [%g]: ",p.tolerance.feasible); |
389 |
p.tolerance.feasible = readdouble(p.tolerance.feasible); |
390 |
|
391 |
PRINTF("Partition problem? [%s] ",yorn(p.partition)); |
392 |
p.partition = input_boolean(p.partition); |
393 |
|
394 |
PRINTF("Ignore bounds? [%s] ",yorn(p.ignore_bounds)); |
395 |
p.ignore_bounds = input_boolean(p.ignore_bounds); |
396 |
|
397 |
slv_set_parameters(sys,&p); |
398 |
} |
399 |
|
400 |
static void output_parameters(sys) |
401 |
slv_system_t sys; |
402 |
/** |
403 |
*** Outputs parameters for the given system. |
404 |
**/ |
405 |
{ |
406 |
slv_parameters_t p; |
407 |
slv_get_parameters(sys,&p); |
408 |
|
409 |
PRINTF("Print more important messages? = %s\n", |
410 |
yorn(p.output.more_important!=NULL)); |
411 |
PRINTF("Print less important messages? = %s\n", |
412 |
yorn(p.output.less_important!=NULL)); |
413 |
PRINTF("Cpu time limit = %g seconds\n",p.time_limit); |
414 |
PRINTF("Iteration limit = %d\n",p.iteration_limit); |
415 |
PRINTF("Tolerance, singular = %g\n",p.tolerance.singular); |
416 |
PRINTF("Tolerance, feasible = %g\n",p.tolerance.feasible); |
417 |
PRINTF("Partition problem? = %s\n",yorn(p.partition)); |
418 |
PRINTF("Ignore bounds? = %s\n",yorn(p.ignore_bounds)); |
419 |
} |
420 |
|
421 |
static void output_status(sys) |
422 |
slv_system_t sys; |
423 |
/** |
424 |
*** Outputs status for the given system. |
425 |
**/ |
426 |
{ |
427 |
slv_status_t s; |
428 |
slv_get_status(sys,&s); |
429 |
|
430 |
PRINTF("\nSolver status\n-------------\n"); |
431 |
|
432 |
if( s.converged ) |
433 |
PRINTF("System converged.\n"); |
434 |
else |
435 |
PRINTF("System is %sready to solve.\n",s.ready_to_solve ? "" : "not "); |
436 |
|
437 |
PRINTF("Abnormalities -->"); |
438 |
if( s.over_defined ) PRINTF(" over-defined"); |
439 |
if( s.under_defined ) PRINTF(" under-defined"); |
440 |
if( s.struct_singular ) PRINTF(" structurally singular"); |
441 |
if( s.diverged ) PRINTF(" diverged"); |
442 |
if( s.inconsistent ) PRINTF(" inconsistent"); |
443 |
if( !s.calc_ok ) PRINTF(" calculation error"); |
444 |
if( s.iteration_limit_exceeded ) PRINTF(" iteration limit exceeded"); |
445 |
if( s.time_limit_exceeded ) PRINTF(" time limit exceeded"); |
446 |
if( s.ok ) PRINTF(" NONE"); |
447 |
PUTCHAR('\n'); |
448 |
|
449 |
PRINTF("# of blocks = %d\n",s.block.number_of); |
450 |
PRINTF("current block = %d\n",s.block.current_block); |
451 |
PRINTF("its size = %d\n",s.block.current_size); |
452 |
PRINTF("# vars/rels solved already = %d\n", |
453 |
s.block.previous_total_size); |
454 |
PRINTF("Iteration = %d (this block = %d)\n", |
455 |
s.iteration,s.block.iteration); |
456 |
PRINTF("CPU time elapsed = %g sec (this block = %g sec)\n", |
457 |
s.cpu_elapsed,s.block.cpu_elapsed); |
458 |
PRINTF("Residual norm in current block = %g\n",s.block.residual); |
459 |
} |
460 |
|
461 |
|
462 |
|
463 |
struct rock { |
464 |
struct var_variable **vlist; |
465 |
struct rel_relation **rlist; |
466 |
int32 nvars,nrels; |
467 |
}; |
468 |
|
469 |
static void output_system(fp,sys) |
470 |
FILE *fp; |
471 |
slv_system_t sys; |
472 |
{ |
473 |
struct rock vr; |
474 |
int32 n; |
475 |
struct var_variable **vp; |
476 |
struct rel_relation **rp, *obj; |
477 |
slv_parameters_t p; |
478 |
|
479 |
vr.nvars = vr.nrels = 0; |
480 |
vr.vlist = slv_get_master_var_list(sys); |
481 |
vr.rlist = slv_get_master_rel_list(sys); |
482 |
|
483 |
for( vp=vr.vlist ; vp != NULL && *vp != NULL ; ++vp ) |
484 |
++vr.nvars; |
485 |
FPRINTF(fp,"nvars %d\n",vr.nvars); |
486 |
|
487 |
for( rp=vr.rlist ; rp != NULL && *rp != NULL ; ++rp ) |
488 |
++vr.nrels; |
489 |
FPRINTF(fp,"nrels %d\n\n",vr.nrels); |
490 |
|
491 |
for( n=0,vp=slv_get_master_var_list(sys); |
492 |
vp != NULL && *vp != NULL; |
493 |
++vp,++n ) { |
494 |
FPRINTF(fp,";v%d\n",n); |
495 |
FPRINTF(fp," v%d = %g\n",n,var_value(*vp)); |
496 |
FPRINTF(fp," v%d nominal %g\n",n,var_nominal(*vp)); |
497 |
FPRINTF(fp," v%d LB %g\n",n,var_lower_bound(*vp)); |
498 |
FPRINTF(fp," v%d UB %g\n",n,var_upper_bound(*vp)); |
499 |
FPRINTF(fp," v%d %s\n",n,var_fixed(*vp)?"fixed":"free"); |
500 |
FPRINTF(fp," v%d %s\n",n,var_active(*vp)?"active":"inactive"); |
501 |
} |
502 |
|
503 |
for( n=0,rp=slv_get_master_rel_list(sys); |
504 |
rp != NULL && *rp != NULL; |
505 |
++rp,++n ) { |
506 |
char *str = relman_make_string_infix(sys,*rp); |
507 |
FPRINTF(fp,"r%d: %s\n",n,str); |
508 |
FPRINTF(fp," r%d %s\n",n,(rel_included(*rp) && rel_active(*rp)) ? |
509 |
"included" : "ignored"); |
510 |
ascfree(str); |
511 |
} |
512 |
|
513 |
if( (obj=slv_get_obj_relation(sys)) != NULL ) { |
514 |
char *str = relman_make_string_infix(sys,obj); |
515 |
FPRINTF(fp,"\nobj %s\n",str); |
516 |
ascfree(str); |
517 |
} |
518 |
|
519 |
slv_get_parameters(sys,&p); |
520 |
FPRINTF(fp,"\ntime limit %g ;seconds\n",p.time_limit); |
521 |
FPRINTF(fp,"iteration limit %d\n",p.iteration_limit); |
522 |
FPRINTF(fp,"singular tolerance %g\n",p.tolerance.singular); |
523 |
FPRINTF(fp,"feasible tolerance %g\n",p.tolerance.feasible); |
524 |
FPRINTF(fp,"partition %s\n",p.partition?"yes":"no"); |
525 |
FPRINTF(fp,"ignore bounds %s\n",p.ignore_bounds?"yes":"no"); |
526 |
FPRINTF(fp,"output more important %s\n",(p.output.more_important!=NULL)? |
527 |
"yes" :"no"); |
528 |
FPRINTF(fp,"output less important %s\n",(p.output.less_important!=NULL)? |
529 |
"yes" :"no"); |
530 |
FPRINTF(fp,"\nend\n"); |
531 |
} |
532 |
|
533 |
|
534 |
|
535 |
static slv_system_t sys = NULL; |
536 |
/* The system in use */ |
537 |
static struct Instance *inst = NULL; |
538 |
/* Instance in use */ |
539 |
|
540 |
static boolean do_command(command) |
541 |
int command; |
542 |
/** |
543 |
*** Executes given command: returns FALSE if terminate. |
544 |
**/ |
545 |
{ |
546 |
static boolean suppress_rel_flag = TRUE; |
547 |
|
548 |
switch(command) { |
549 |
default: |
550 |
PRINTF("No such command.\n"); |
551 |
break; |
552 |
|
553 |
case C_NOP: |
554 |
break; |
555 |
|
556 |
case C_RETURN: |
557 |
PRINTF("Keep system around for next time? [yes]: "); |
558 |
if( !input_boolean(TRUE) ) { |
559 |
system_destroy(sys); |
560 |
sys = NULL; |
561 |
} |
562 |
return(FALSE); |
563 |
|
564 |
case C_HELP: |
565 |
print_commands(); |
566 |
break; |
567 |
|
568 |
case C_INPUT_PARAMETERS: |
569 |
input_parameters(sys); |
570 |
break; |
571 |
|
572 |
case C_OUTPUT_PARAMETERS: |
573 |
output_parameters(sys); |
574 |
break; |
575 |
|
576 |
case C_OUTPUT_STATUS: |
577 |
output_status(sys); |
578 |
break; |
579 |
|
580 |
case C_COUNT: { |
581 |
var_filter_t vfilter; |
582 |
rel_filter_t rfilter; |
583 |
|
584 |
vfilter.matchbits = 0; /* allow all */ |
585 |
rfilter.matchbits = 0; /* allow all */ |
586 |
FPRINTF(stdout,"There are %d variables and %d relations.\n", |
587 |
slv_count_solvers_vars(sys,&vfilter), |
588 |
slv_count_solvers_rels(sys,&rfilter)); |
589 |
break; |
590 |
} |
591 |
|
592 |
case C_COUNT_IN_BLOCK: { |
593 |
slv_status_t s; |
594 |
int32 bnum; |
595 |
linsol_system_t lsys; |
596 |
mtx_matrix_t mtx; |
597 |
mtx_region_t reg; |
598 |
|
599 |
slv_get_status(sys,&s); |
600 |
PRINTF("Block number [%d]: ",s.block.current_block); |
601 |
bnum = (int32)readlong((long)s.block.current_block); |
602 |
lsys = slv_get_linsol_sys(sys); |
603 |
mtx = linsol_get_matrix(lsys); |
604 |
mtx_block(mtx,bnum,®); |
605 |
FPRINTF(stdout,"There are %d variables in block %d.\n", |
606 |
(reg.col.high-reg.col.low+1),bnum); |
607 |
FPRINTF(stdout,"There are %d relations in block %d.\n", |
608 |
(reg.row.high-reg.row.low+1),bnum); |
609 |
break; |
610 |
} |
611 |
|
612 |
case C_WRITE_VAR: { |
613 |
int32 n; |
614 |
struct var_variable *var; |
615 |
|
616 |
PRINTF("Which variable [0]: "); |
617 |
n = (int32)readlong(0L); |
618 |
var = slv_get_master_var_list(sys)[n]; |
619 |
write_var(stdout,sys,var); |
620 |
break; |
621 |
} |
622 |
|
623 |
case C_WRITE_VARS: { |
624 |
var_filter_t vfilter; |
625 |
vfilter.matchbits = 0; |
626 |
write_varlist(stdout,sys,&vfilter,FALSE); |
627 |
break; |
628 |
} |
629 |
|
630 |
case C_WRITE_VARS_IN_BLOCK: { |
631 |
struct var_variable **vp = slv_get_solvers_var_list(sys); |
632 |
slv_status_t s; |
633 |
int32 bnum; |
634 |
linsol_system_t lsys; |
635 |
mtx_matrix_t mtx; |
636 |
mtx_region_t reg; |
637 |
|
638 |
slv_get_status(sys,&s); |
639 |
PRINTF("Block number [%d]: ",s.block.current_block); |
640 |
bnum = (int32)readlong((long)s.block.current_block); |
641 |
lsys = slv_get_linsol_sys(sys); |
642 |
mtx = linsol_get_matrix(lsys); |
643 |
mtx_block(mtx,bnum,®); |
644 |
for( ; reg.col.low <= reg.col.high; reg.col.low++ ) { |
645 |
struct var_variable *var = vp[mtx_col_to_org(mtx,reg.col.low)]; |
646 |
write_var(stdout,sys,var); |
647 |
} |
648 |
break; |
649 |
} |
650 |
|
651 |
case C_TOGGLE_SUPPRESS_REL: |
652 |
PRINTF("Relations will %sbe printed now.\n", |
653 |
(suppress_rel_flag = !suppress_rel_flag)?"not " : ""); |
654 |
break; |
655 |
|
656 |
case C_WRITE_REL: { |
657 |
struct rel_relation *rel; |
658 |
int32 n; |
659 |
|
660 |
PRINTF("Which relation [0]: "); |
661 |
n = (int32)readlong(0L); |
662 |
rel = slv_get_master_rel_list(sys)[n]; |
663 |
write_rel(stdout,sys,rel,suppress_rel_flag); |
664 |
break; |
665 |
} |
666 |
|
667 |
case C_WRITE_RELS: { |
668 |
rel_filter_t rfilter; |
669 |
rfilter.matchbits = 0; |
670 |
write_rellist(stdout,sys,&rfilter,FALSE,suppress_rel_flag); |
671 |
break; |
672 |
} |
673 |
|
674 |
case C_WRITE_RELS_IN_BLOCK: { |
675 |
struct rel_relation **rp = slv_get_solvers_rel_list(sys); |
676 |
slv_status_t s; |
677 |
int32 bnum; |
678 |
linsol_system_t lsys; |
679 |
mtx_matrix_t mtx; |
680 |
mtx_region_t reg; |
681 |
|
682 |
slv_get_status(sys,&s); |
683 |
PRINTF("Block number [%d]: ",s.block.current_block); |
684 |
bnum = (int32)readlong((long)s.block.current_block); |
685 |
lsys = slv_get_linsol_sys(sys); |
686 |
mtx = linsol_get_matrix(lsys); |
687 |
mtx_block(mtx,bnum,®); |
688 |
for( ; reg.row.low <= reg.row.high; reg.row.low++ ) { |
689 |
struct rel_relation *rel = rp[mtx_row_to_org(mtx,reg.row.low)]; |
690 |
write_rel(stdout,sys,rel,suppress_rel_flag); |
691 |
} |
692 |
break; |
693 |
} |
694 |
|
695 |
case C_WRITE_OBJ: |
696 |
write_obj(stdout,sys); |
697 |
break; |
698 |
|
699 |
case C_CHECK_DIMENSIONS: { |
700 |
chkdim_system_t chk; |
701 |
slv_parameters_t p; |
702 |
/*expr_t obj;*/ |
703 |
|
704 |
PRINTF("Creating system . . .\n"); |
705 |
chkdim_create_system(&chk,slv_get_master_rel_list(sys)); |
706 |
/* if( (obj=slv_get_obj_function(sys)) != NULL ) |
707 |
chkdim_append_expr(&chk,obj); */ |
708 |
|
709 |
PRINTF(". . . done. Check system . . .\n"); |
710 |
slv_get_parameters(sys,&p); |
711 |
chkdim_check_dimensions(&chk,&p); |
712 |
|
713 |
PRINTF(". . . done. Assign dimensions to variables? [no] "); |
714 |
if( input_boolean(FALSE) ) |
715 |
chkdim_assign_dimensions(&chk,&p); |
716 |
chkdim_destroy_system(&chk); |
717 |
break; |
718 |
} |
719 |
|
720 |
case C_ELIGIBLE_SOLVERS: { |
721 |
int cur,n; |
722 |
/* broken 6/96 baa */ |
723 |
cur = slv_get_selected_solver(sys); |
724 |
PRINTF("Solver Name ?Eligible\n"); |
725 |
PRINTF("-----------------------------\n"); |
726 |
for( n=0 ; n<slv_number_of_solvers ; ++n ) |
727 |
PRINTF("%c%3d %-11s %s\n", |
728 |
(n==cur?'*':' '),n,slv_solver_name(n), |
729 |
yorn(slv_eligible_solver(sys)) ); |
730 |
break; |
731 |
} |
732 |
|
733 |
case C_SELECT_SOLVER: { |
734 |
int n; |
735 |
|
736 |
PRINTF("Solver Name\n"); |
737 |
PRINTF("----------------------\n"); |
738 |
for( n=0 ; n<slv_number_of_solvers ; ++n ) |
739 |
PRINTF("%4d %s\n",n,slv_solver_name(n)); |
740 |
PRINTF("Which solver? [%d]: ",n=slv_get_selected_solver(sys)); |
741 |
n = (int)readlong((long)n); |
742 |
|
743 |
slv_select_solver(sys,n); |
744 |
break; |
745 |
} |
746 |
|
747 |
case C_SELECTED_SOLVER: { |
748 |
int n; |
749 |
n = slv_get_selected_solver(sys); |
750 |
PRINTF("Selected solver is %d (%s).\n",n,slv_solver_name(n)); |
751 |
break; |
752 |
} |
753 |
|
754 |
case C_PRESOLVE: |
755 |
slv_presolve(sys); |
756 |
output_status(sys); |
757 |
break; |
758 |
|
759 |
case C_RESOLVE: |
760 |
slv_resolve(sys); |
761 |
output_status(sys); |
762 |
break; |
763 |
|
764 |
case C_ITERATE: |
765 |
slv_iterate(sys); |
766 |
output_status(sys); |
767 |
break; |
768 |
|
769 |
case C_SOLVE: |
770 |
slv_solve(sys); |
771 |
output_status(sys); |
772 |
break; |
773 |
|
774 |
case C_DUMP_SYSTEM: { |
775 |
FILE *out; |
776 |
char fname[200]; |
777 |
struct var_variable **vp; |
778 |
struct rel_relation **rp; |
779 |
|
780 |
PRINTF("Target filename [stdout]: "); |
781 |
readln(fname,sizeof(fname)); |
782 |
out = (*fname=='\0') ? stdout : fopen(fname,"w"); |
783 |
if( out == NULL ) { |
784 |
FPRINTF(stderr,"Unable to open %s for writing.\n",fname); |
785 |
break; |
786 |
} |
787 |
|
788 |
for( vp=slv_get_master_var_list(sys) ; *vp != NULL ; ++vp ) { |
789 |
FPRINTF(out,"; v%d <--> ",var_sindex(*vp)); |
790 |
write_var(out,sys,*vp); |
791 |
PUTC('\n',out); |
792 |
} |
793 |
for( rp=slv_get_master_rel_list(sys) ; *rp != NULL ; ++rp ) { |
794 |
FPRINTF(out,"; r%d <--> ",rel_sindex(*rp)); |
795 |
write_rel(out,sys,*rp,suppress_rel_flag); |
796 |
PUTC('\n',out); |
797 |
} |
798 |
output_system(out,sys); |
799 |
|
800 |
if( out != stdout ) |
801 |
fclose(out); |
802 |
break; |
803 |
} |
804 |
|
805 |
case C_PLOT: { |
806 |
char args[50]; |
807 |
static char plotfilename[] = "~/ascend.plot"; |
808 |
|
809 |
if( !plot_allowed(inst) ) { |
810 |
PRINTF("Not allowed to plot instance: wrong type.\n"); |
811 |
break; |
812 |
} |
813 |
|
814 |
PRINTF("Command line arguments: "); |
815 |
readln(args,sizeof(args)); |
816 |
plot_prepare_file(inst,plotfilename); |
817 |
PRINTF("Plot left in %s\n",plotfilename); |
818 |
break; |
819 |
} |
820 |
} |
821 |
return(TRUE); |
822 |
} |
823 |
|
824 |
#define USER_SAYS_KEEP \ |
825 |
(PRINTF("Keep previous system? [yes]: ") , input_boolean(TRUE)) |
826 |
/** |
827 |
*** Asks user if system should be kept, and returns response. |
828 |
**/ |
829 |
|
830 |
void Solve(i) |
831 |
struct Instance *i; |
832 |
{ |
833 |
if( sys != NULL ) |
834 |
if( inst != i || !USER_SAYS_KEEP ) { |
835 |
system_destroy(sys); |
836 |
sys = NULL; |
837 |
} |
838 |
|
839 |
if( sys == NULL ) { |
840 |
sys = system_build(i); |
841 |
PRINTF("Presolving . . .\n"); |
842 |
do_command(C_PRESOLVE); |
843 |
} |
844 |
|
845 |
inst = i; |
846 |
while( do_command(input_command()) ) |
847 |
; |
848 |
} |