/[ascend]/trunk/base/generic/solver/slv.c
ViewVC logotype

Contents of /trunk/base/generic/solver/slv.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1133 - (show annotations) (download) (as text)
Sun Jan 14 11:51:48 2007 UTC (15 years, 5 months ago) by johnpye
File MIME type: text/x-csrc
File size: 47941 byte(s)
Removed the 'REX' and 'IEX' array aliases (added the solver parameter comments directly in the slv_param_* calls).
Renamed Simulation::[gs]etSolverParameters to Simulation::[gs]etParameters.
Added [gs]etParameter (singular) methods to SWIG wrapper.
Fixed missing NULL in IDA.
Fixed bug with BDF/AM wrong way round in LSODE.
Removed some debug output from slv.c
1 /*
2 SLV: Ascend Nonlinear Solver
3 Copyright (C) 1990 Karl Michael Westerberg
4 Copyright (C) 1993 Joseph Zaher
5 Copyright (C) 1994 Joseph Zaher, Benjamin Andrew Allan
6 Copyright (C) 1996 Benjamin Andrew Allan
7 Copyright (C) 2005-2006 Carnegie-Mellon University
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 This file is part of the SLV solver.
23 */
24
25 #include <math.h>
26 #include <stdarg.h>
27 #include <utilities/ascConfig.h>
28
29 ASC_EXPORT int g_SlvNumberOfRegisteredClients=0; /* see header */
30
31 #include <compiler/instance_enum.h>
32 #include <compiler/fractions.h>
33 #include <compiler/compiler.h>
34 #include <utilities/ascMalloc.h>
35 #include <utilities/ascPanic.h>
36 #include <compiler/dimen.h>
37 #include <compiler/atomvalue.h>
38 #include "mtx.h"
39 #include "linsol.h"
40 #include "linsolqr.h"
41 #include "slv_types.h"
42 #include "var.h"
43 #include "rel.h"
44 #include "logrel.h"
45 #include "discrete.h"
46 #include "conditional.h"
47 #include "bnd.h"
48 #include "bndman.h"
49 #include "system.h"
50 #include "slv_server.h"
51 #include "slv_common.h"
52 #include "analyze.h"
53 #include "slv_client.h"
54
55 #define NEEDSTOBEDONE 0
56
57 /**
58 *** Include all of the solvers involved,
59 *** even if they are not linked later
60 *** Defines are to take care of the unlinked ones.
61 **/
62 #if 0
63 # include "slv0.h"
64 # include "slv1.h"
65 # include "slv2.h"
66 # include "slv3.h"
67 # include "slv4.h"
68 # include "slv5.h"
69 # include "slv6.h"
70 # include "slv7.h"
71 # include "slv8.h"
72 # include "slv9.h"
73 #endif
74
75
76 struct slv_system_structure {
77 int solver;
78
79 int serial_id;
80 /**< Through time, two systems may have the same pointer but never
81 simultaneously. The serial_id provides a unique tag that will
82 never repeat. Clients concerned with identity but not capable
83 of tracking time must use the serial_id for checks. */
84
85 SlvBackendToken instance; /* should be void * in the most generic case */
86
87 /* All solver handles. sysI can't be dereferenced outside slvI.c
88 * should be an array of pointers to arrays of the functions provided
89 * by dynamically loaded clients, or at least by the client which this
90 * system is currently supporting.
91 */
92
93 SlvClientToken ct;
94 /* This is a pointer that the client returns on registration.
95 * If it is not null, the registration was successful.
96 * This token will be handed back to the client code on all calls
97 * originating from here.
98 */
99
100 dof_t dof; /* non linear blocks */
101 dof_t logdof; /* logical blocks */
102
103 /* In the following NULL terminated lists, note that snum and mnum
104 * are the lengths of the arrays WITHOUT the NULL pointer at the end.
105 * Note objs is a list of relations that are objectives
106 * (e_maximize,e_minimize). this list will include the first included obj.
107 */
108 struct {
109 int snum; /* length of the solver list */
110 int mnum; /* length of the master list */
111 struct var_variable **solver;
112 struct var_variable **master;
113 struct var_variable *buf;
114 } vars;
115
116 struct {
117 int snum; /* length of the solver list */
118 int mnum; /* length of the master list */
119 struct dis_discrete **solver;
120 struct dis_discrete **master;
121 struct dis_discrete *buf;
122 int bufnum;
123 } dvars;
124
125 struct {
126 int snum; /* length of the solver list */
127 int mnum; /* length of the master list */
128 struct rel_relation **solver;
129 struct rel_relation **master;
130 struct rel_relation *buf;
131 } rels;
132
133 struct {
134 int snum;
135 int mnum;
136 struct rel_relation **solver;
137 struct rel_relation **master;
138 struct rel_relation *buf;
139 } objs;
140
141 struct {
142 int snum; /* length of the solver list */
143 int mnum; /* length of the master list */
144 struct rel_relation **solver;
145 struct rel_relation **master;
146 struct rel_relation *buf;
147 } condrels;
148
149 struct {
150 int snum; /* length of the solver list */
151 int mnum; /* length of the master list */
152 struct logrel_relation **solver;
153 struct logrel_relation **master;
154 struct logrel_relation *buf;
155 } logrels;
156
157 struct {
158 int snum; /* length of the solver list */
159 int mnum; /* length of the master list */
160 struct logrel_relation **solver;
161 struct logrel_relation **master;
162 struct logrel_relation *buf;
163 } condlogrels;
164
165 struct {
166 int snum; /* length of the solver list */
167 int mnum; /* length of the master list */
168 struct w_when **solver;
169 struct w_when **master;
170 struct w_when *buf;
171 int bufnum;
172 } whens;
173
174 struct {
175 int snum; /* length of the solver list */
176 int mnum; /* length of the master list */
177 struct bnd_boundary **solver;
178 struct bnd_boundary **master;
179 struct bnd_boundary *buf;
180 int bufnum;
181 } bnds;
182
183 struct {
184 int snum;
185 int mnum;
186 struct var_variable **solver;
187 struct var_variable **master;
188 struct var_variable *buf;
189 } pars;
190
191 struct {
192 int snum;
193 int mnum;
194 struct var_variable **solver;
195 struct var_variable **master;
196 struct var_variable *buf;
197 } unattached;
198
199 struct {
200 int snum;
201 int mnum;
202 struct dis_discrete **solver;
203 struct dis_discrete **master;
204 struct dis_discrete *buf;
205 } disunatt;
206
207 void *diffvars;
208 /**
209 This will be a pointer to a SolverDiffVarCollection, but we don't want
210 to force all solvers to know what that is. Default to NULL, thankfully.
211 */
212
213 /* the data that follows is for internal consumption only. */
214 struct {
215 int num_extrels;
216 struct ExtRelCache **erlist;
217 } extrels;
218
219 struct rel_relation *obj; /* selected for optimization from list */
220 struct var_variable *objvar; /* selected for optimization from list */
221 struct gl_list_t *symbollist; /* list of symbol values struct used to */
222 /* assign an integer value to a symbol value */
223 struct {
224 struct var_variable **incidence; /* all relation incidence list memory */
225 struct rel_relation **varincidence; /* all variable incidence list memory */
226 struct dis_discrete **logincidence; /* all logrel incidence list memory */
227 long incsize; /* size of incidence array */
228 long varincsize; /* size of varincidence array */
229 long logincsize; /* size of discrete incidence array */
230 #if NEEDSTOBEDONE
231 /* we should be group allocating this data, but aren't */
232 struct ExtRelCache *ebuf; /* data space for all extrel caches */
233 #endif
234 } data;
235
236 int32 nmodels;
237 int32 need_consistency; /* consistency analysis required for conditional model ? */
238 real64 objvargrad; /* maximize -1 minimize 1 noobjvar 0 */
239 };
240
241 /**
242 global variable used to communicate information between solvers and
243 an interface, whether a calculation should be halted or not.
244 0 means go on. any other value may contain additional information
245 content.
246 */
247 int Solv_C_CheckHalt_Flag = 0;
248
249
250 /* ASC_EXPORT int g_SlvNumberOfRegisteredClients=0; */
251
252 /** making ANSI assumption that RegisteredClients is init to 0/NULLs */
253 static SlvFunctionsT SlvClientsData[SLVMAXCLIENTS];
254
255 /*-----------------------------------------------------------------*/
256 /**
257 Note about g_number_of_whens, g_number_of_dvars and g_number_of_bnds:
258 These numbers are as the same as those given in the solver and master
259 lists, however, these lists are destroyed before the buffers are destroyed,
260 so the information is gone before I can use it.
261 */
262 /*
263 These have been REMOVED and added to the 'sys' type.
264 */
265
266 /*-------------------------------------------------------------------
267 Convenience macros
268 */
269
270 /** Return the solver index for a given slv_system_t */
271 #define SNUM(sys) ((sys)->solver)
272
273 /** Number of registered clients */
274 #define NORC g_SlvNumberOfRegisteredClients
275
276 /** Return the pointer to a registered SLV client's data space. @see SF, related.
277 @param i registered solver ID
278 */
279 #define SCD(i) SlvClientsData[(i)]
280
281 /** Get the solver index for a system and return TRUE if the solver
282 index is in the range [0,NORC). 'sys' should not be null
283 @param sys system, slv_system_t.
284 */
285 #define LS(sys) ( (sys)->solver >= 0 && (sys)->solver < g_SlvNumberOfRegisteredClients )
286
287 /** Boolean test that i is in the range [0,NORC) */
288 #define LSI(i) ( (i) >= 0 && (i) < g_SlvNumberOfRegisteredClients )
289
290 /** Check and return a function pointer. See @SF */
291 #define CF(sys,ptr) ( LS(sys) ? SlvClientsData[(sys)->solver].ptr : NULL )
292
293 /** Return the pointer to the client-supplied function or char if
294 the client supplied one, else NULL. This should only be called
295 with nonNULL sys after CF is happy. @see CF
296 */
297 #define SF(sys,ptr) ( SlvClientsData[(sys)->solver].ptr )
298
299 /** Free a pointer provided it's not NULL */
300 #define SFUN(p) if ((p) != NULL) ascfree(p)
301
302 /*-----------------------------------------------------------------
303 SERVER FUNCTIONS
304 */
305
306 int slv_lookup_client( const char *solverName )
307 {
308 int i;
309 if (solverName == NULL) { return -1; }
310 for (i = 0; i < NORC; i++) {
311 if ( strcmp( SCD(i).name, solverName)==0) {
312 return i;
313 }
314 }
315 return -1;
316 }
317
318 /**
319 Register a new solver.
320
321 @TODO This needs work still, particularly of the dynamic loading
322 sort. it would be good if here we farmed out the dynamic loading
323 to another file so we don't have to crap this one all up.
324 */
325 int slv_register_client(SlvRegistration registerfunc, CONST char *func
326 ,CONST char *file, int *new_client_id)
327 {
328 int status;
329
330 UNUSED_PARAMETER(func);
331 UNUSED_PARAMETER(file);
332
333 status = registerfunc(&( SlvClientsData[NORC]));
334 if (!status) { /* ok */
335 SlvClientsData[NORC].number = NORC;
336 *new_client_id = NORC;
337 NORC++;
338 } else {
339 *new_client_id = -2;
340 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Client %d registration failure (%d)!",NORC,status);
341 }
342 return status;
343 }
344
345 slv_system_t slv_create(void)
346 {
347 slv_system_t sys;
348 static unsigned nextid = 1;
349 sys = (slv_system_t)asccalloc(1,sizeof(struct slv_system_structure) );
350 /* all lists, sizes, pointers DEFAULT to 0/NULL */
351 sys->solver = -1; /* a nonregistration */
352 sys->serial_id = nextid++;
353 return(sys);
354 }
355
356 unsigned slv_serial_id(slv_system_t sys)
357 {
358 return sys->serial_id;
359 }
360
361 /*---------------------------------------------------------------
362 Macros to define
363 slv_set_incidence
364 slv_set_var_incidence
365 slv_set_logincidence
366 */
367
368 /* define but with error on null */
369 #define DEFINE_SET_INCIDENCE(NAME,PROP,TYPE,SIZE) \
370 void slv_set_##NAME(slv_system_t sys, struct TYPE **inc, long s){ \
371 if(sys->data.PROP != NULL){ \
372 Asc_Panic(2,"slv_set_" #NAME,"bad call: sys->data." #PROP " is already defined!"); \
373 }else if(inc == NULL){ \
374 ERROR_REPORTER_HERE(ASC_PROG_ERROR,"bad call: 'inc' parameter is NULL"); \
375 /*Asc_Panic(2,"slv_set_" #NAME,"bad call: 'inc' parameter is NULL!");*/ \
376 }else{ \
377 sys->data.PROP = inc; \
378 sys->data.SIZE = s; \
379 } \
380 }
381
382 /* define, no error on null */
383 #define DEFINE_SET_INCIDENCE_NONULLERROR(NAME,PROP,TYPE,SIZE) \
384 void slv_set_##NAME(slv_system_t sys, struct TYPE **inc, long s){ \
385 if(sys->data.PROP != NULL){ \
386 Asc_Panic(2,"slv_set_" #NAME,"bad call: sys->data." #PROP " is already defined!"); \
387 }else{ \
388 sys->data.PROP = inc; \
389 sys->data.SIZE = s; \
390 } \
391 }
392
393
394 #define DEFINE_SET_INCIDENCES(D,D1) \
395 D(incidence, incidence, var_variable, incsize) \
396 D(var_incidence, varincidence, rel_relation, varincsize) \
397 D1(logincidence, logincidence, dis_discrete, incsize)
398
399 DEFINE_SET_INCIDENCES(DEFINE_SET_INCIDENCE, DEFINE_SET_INCIDENCE_NONULLERROR)
400
401 /* see below for the use of this one */
402 #define SLV_FREE_INCIDENCE(NAME,PROP,TYPE,SIZE) \
403 if (sys->data.PROP != NULL) ascfree(sys->data.PROP); \
404 sys->data.PROP = NULL;
405
406 /*----------------------------------------------------
407 destructors
408 */
409
410 #define DEFINE_DESTROY_BUFFER(NAME,PROP,TYPE,DESTROY) \
411 static void slv_destroy_##NAME##_buffer(slv_system_t sys){ \
412 int c; struct TYPE *cur; \
413 struct TYPE *buf; \
414 buf = sys->PROP.buf; \
415 for(c = 0; c < sys->PROP.bufnum; c++){ \
416 cur = &(buf[c]); \
417 DESTROY(cur); \
418 } \
419 ascfree(buf); \
420 sys->PROP.buf = NULL; \
421 sys->PROP.bufnum = 0; \
422 }
423
424 #define DEFINE_DESTROY_BUFFERS(D) \
425 D(dvar, dvars, dis_discrete, dis_destroy) \
426 D(when, whens, w_when, when_destroy) \
427 D(bnd, bnds, bnd_boundary, bnd_destroy)
428
429 DEFINE_DESTROY_BUFFERS(DEFINE_DESTROY_BUFFER)
430
431 #define SLV_FREE_BUF(PROP) \
432 if(sys->PROP.buf !=NULL) ascfree(sys->PROP.buf); \
433 sys->PROP.buf = NULL;
434
435 #define SLV_FREE_BUF_GLOBAL(NAME, PROP) \
436 if (sys->PROP.buf != NULL) { \
437 slv_destroy_##NAME##_buffer(sys); \
438 }
439
440 #define SLV_FREE_BUFS(D,D_GLOBAL) \
441 D(vars) \
442 D(rels) \
443 D(objs) \
444 D(condrels) \
445 D(logrels) \
446 D(condlogrels) \
447 D(pars) \
448 D(unattached) \
449 D(disunatt) \
450 D_GLOBAL(dvar, dvars) \
451 D_GLOBAL(when, whens) \
452 D_GLOBAL(bnd, bnds)
453
454 int slv_destroy(slv_system_t sys)
455 {
456 int ret = 0;
457 if (sys->ct != NULL) {
458 if ( CF(sys,cdestroy) == NULL ) {
459 ERROR_REPORTER_HERE(ASC_PROG_FATAL,"slv_destroy: SlvClientToken 0x%p not freed by %s",
460 sys->ct,SF(sys,name));
461 } else {
462 if ( SF(sys,cdestroy)(sys,sys->ct) ) {
463 ret++;
464 }
465 }
466 }
467 if (ret) {
468 ERROR_REPORTER_HERE(ASC_PROG_FATAL,"slv_destroy: slv_system_t 0x%p not freed.",sys);
469 } else {
470
471 SLV_FREE_BUFS(SLV_FREE_BUF, SLV_FREE_BUF_GLOBAL)
472
473 DEFINE_SET_INCIDENCES(SLV_FREE_INCIDENCE,SLV_FREE_INCIDENCE)
474
475 ascfree( (POINTER)sys );
476 }
477 return ret;
478 }
479
480 /*---------------------------------------------------------------*/
481
482 void slv_destroy_client(slv_system_t sys)
483 {
484
485 if (sys->ct != NULL) {
486 if ( CF(sys,cdestroy) == NULL ) {
487 ERROR_REPORTER_HERE(ASC_PROG_ERR,
488 "SlvClientToken 0x%p not freed in slv_destroy_client",sys->ct);
489 } else {
490 if ( SF(sys,cdestroy)(sys,sys->ct) ) {
491 ERROR_REPORTER_HERE(ASC_PROG_ERR,"slv_destroy_client: SlvClientToken not freed");
492 } else {
493 sys->ct = NULL;
494 }
495 }
496 }
497 }
498
499 /*---------------------------------------------------------
500 get/set instance
501 */
502
503 SlvBackendToken slv_instance(slv_system_t sys)
504 {
505 if (sys == NULL) {
506 ERROR_REPORTER_HERE(ASC_PROG_ERR,"slv_instance: called with NULL system.");
507 return NULL;
508 } else {
509 return sys->instance;
510 }
511 }
512
513 void slv_set_instance(slv_system_t sys,SlvBackendToken instance)
514 {
515 if (sys == NULL) {
516 ERROR_REPORTER_HERE(ASC_PROG_ERR,"slv_set_instance: called with NULL system.");
517 return;
518 } else {
519 sys->instance = instance;
520 }
521 }
522
523 dof_t *slv_get_dofdata(slv_system_t sys)
524 {
525 return &(sys->dof);
526 }
527
528 dof_t *slv_get_log_dofdata(slv_system_t sys)
529 {
530 return &(sys->logdof);
531 }
532
533 int32 slv_get_num_models(slv_system_t sys)
534 {
535 if (sys == NULL) {
536 ERROR_REPORTER_HERE(ASC_PROG_ERR,"slv_get_num_models: called with NULL system.");
537 return 0;
538 } else {
539 return sys->nmodels;
540 }
541 }
542 void slv_set_num_models(slv_system_t sys, int32 nmod)
543 {
544 if (sys == NULL) {
545 ERROR_REPORTER_HERE(ASC_PROG_ERR,"slv_set_num_models: called with NULL system.");
546 } else {
547 sys->nmodels = nmod;
548 }
549 }
550
551
552 void slv_set_symbol_list(slv_system_t sys,
553 struct gl_list_t *sv)
554 {
555 if (sys->symbollist != NULL) {
556 DestroySymbolValuesList(sys->symbollist);
557 }
558 sys->symbollist = sv;
559 }
560
561 /*--------------------------------------------------------]
562 Macros to declare
563
564 slv_set_master_*_list(slv_system_t sys, string var_variable **list, int size)
565 slv_set_*_buf(slv_system_t sys, string var_variable **list, int size)
566 */
567
568 #define DEFINE_SET_MASTER_LIST_METHOD(NAME,PROP,TYPE) \
569 void slv_set_master_##NAME##_list(slv_system_t sys, struct TYPE **vlist, int size){ \
570 SFUN(sys->PROP.master); \
571 sys->PROP.mnum = size; \
572 sys->PROP.master = vlist; \
573 }
574
575
576
577 #define DEFINE_SET_MASTER_LIST_METHODS(D) \
578 D(var,vars,var_variable) \
579 D(par,pars,var_variable) \
580 D(unattached,unattached,var_variable) \
581 D(dvar,dvars,dis_discrete) \
582 D(disunatt,disunatt,dis_discrete) \
583 D(rel,rels,rel_relation) \
584 D(condrel,condrels,rel_relation) \
585 D(obj,objs,rel_relation) \
586 D(logrel,logrels,logrel_relation) \
587 D(condlogrel,condlogrels,logrel_relation) \
588 D(when,whens,w_when) \
589 D(bnd,bnds,bnd_boundary)
590
591 DEFINE_SET_MASTER_LIST_METHODS(DEFINE_SET_MASTER_LIST_METHOD)
592
593 /*------------------------------------------------------------
594 Macros to declare
595
596 slv_set_NAME_buf(slv_system_t sts, struct TYPE *PROP)
597 */
598
599 #define DEFINE_SET_BUF_METHOD(NAME,PROP,TYPE) \
600 void slv_set_##NAME##_buf(slv_system_t sys, struct TYPE *PROP){ \
601 if(sys->PROP.buf !=NULL ){ \
602 Asc_Panic(2,"slv_set_" #NAME "_buf","bad call."); \
603 }else{ \
604 sys->PROP.buf = PROP; \
605 } \
606 }
607
608 #define DEFINE_SET_BUF_METHOD_GLOBAL(NAME,PROP,TYPE) \
609 void slv_set_##NAME##_buf(slv_system_t sys, struct TYPE *buf, int len){ \
610 if(sys->PROP.buf != NULL){ \
611 Asc_Panic(2,"slv_set_" #NAME "_buf","bad call."); \
612 }else{ \
613 sys->PROP.buf = buf; \
614 sys->PROP.bufnum = len; \
615 } \
616 }
617
618 #define DEFINE_SET_BUF_METHODS(D, D_GLOBAL) \
619 D(var,vars,var_variable) \
620 D(par,pars,var_variable) \
621 D(unattached,unattached,var_variable) \
622 D(disunatt,disunatt,dis_discrete) \
623 D(rel,rels,rel_relation) \
624 D(condrel,condrels,rel_relation) \
625 D(obj,objs,rel_relation) \
626 D(logrel,logrels,logrel_relation) \
627 D(condlogrel,condlogrels,logrel_relation) \
628 D_GLOBAL(dvar, dvars, dis_discrete) \
629 D_GLOBAL(when, whens, w_when) \
630 D_GLOBAL(bnd,bnds,bnd_boundary)
631
632
633 DEFINE_SET_BUF_METHODS(DEFINE_SET_BUF_METHOD, DEFINE_SET_BUF_METHOD_GLOBAL)
634
635 void slv_set_extrel_list(slv_system_t sys,struct ExtRelCache **erlist,
636 int size)
637 {
638 if (sys->extrels.erlist !=NULL ) {
639 Asc_Panic(2,"slv_set_extrel_list",
640 "bad call.");
641 }
642 sys->extrels.num_extrels = size;
643 sys->extrels.erlist = erlist;
644 }
645
646 struct ExtRelCache **slv_get_extrel_list(slv_system_t sys)
647 {
648 return sys->extrels.erlist;
649 }
650
651 int slv_get_num_extrels(slv_system_t sys)
652 {
653 return sys->extrels.num_extrels;
654 }
655
656
657 /*********************************************************************\
658 client functions.
659 \*********************************************************************/
660 int Solv_C_CheckHalt()
661 {
662 if (Solv_C_CheckHalt_Flag)
663 return 1;
664 else
665 return 0;
666 }
667
668 const char *slv_solver_name(int sindex)
669 {
670 static char errname[] = "ErrorSolver";
671 if (sindex >= 0 && sindex < NORC) {
672 if ( SlvClientsData[sindex].name == NULL ) {
673 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_solver_name: unnamed solver: index='%d'",sindex);
674 return errname;
675 } else {
676 return SlvClientsData[sindex].name;
677 }
678 } else {
679 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_solver_name: invalid solver index '%d'", sindex);
680 return errname;
681 }
682 }
683
684 const mtx_block_t *slv_get_solvers_blocks(slv_system_t sys)
685 {
686 if (sys == NULL) {
687 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_solvers_blocks called with NULL system");
688 return NULL;
689 } else {
690 return &(sys->dof.blocks);
691 }
692 }
693
694 const mtx_block_t *slv_get_solvers_log_blocks(slv_system_t sys)
695 {
696 if (sys == NULL) {
697 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_solvers_log_blocks called with NULL system");
698 return NULL;
699 } else {
700 return &(sys->logdof.blocks);
701 }
702 }
703
704 void slv_set_solvers_blocks(slv_system_t sys,int len, mtx_region_t *data)
705 {
706 if (sys == NULL || len < 0) {
707 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_solvers_blocks called with NULL system or bad len.");
708 } else {
709 if (len && data==NULL) {
710 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_solvers_blocks called with bad data.");
711 } else {
712 if (sys->dof.blocks.nblocks && sys->dof.blocks.block != NULL) {
713 ascfree(sys->dof.blocks.block);
714 }
715 sys->dof.blocks.block = data;
716 sys->dof.blocks.nblocks = len;
717 }
718 }
719 }
720
721 void slv_set_solvers_log_blocks(slv_system_t sys,int len, mtx_region_t *data)
722 {
723 if (sys == NULL || len < 0) {
724 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_solvers_log_blocks called with NULL system or bad len.");
725 } else {
726 if (len && data==NULL) {
727 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_solvers_log_blocks called with bad data.");
728 } else {
729 if (sys->logdof.blocks.nblocks && sys->logdof.blocks.block != NULL) {
730 ascfree(sys->logdof.blocks.block);
731 }
732 sys->logdof.blocks.block = data;
733 sys->logdof.blocks.nblocks = len;
734 }
735 }
736 }
737
738 void slv_check_var_initialization(slv_system_t sys){
739 struct var_variable **vp;
740 for (vp = slv_get_solvers_var_list(sys); *vp != NULL; vp++) {
741 if (!AtomAssigned((struct Instance *)var_instance(*vp))) {
742 var_set_value(*vp,var_nominal(*vp));
743 }
744 }
745 }
746
747 void slv_check_dvar_initialization(slv_system_t sys)
748 {
749 struct dis_discrete **vp;
750
751 for (vp = slv_get_solvers_dvar_list(sys); *vp != NULL; vp++) {
752 if (!AtomAssigned((struct Instance *)dis_instance(*vp))) {
753 dis_set_boolean_value(*vp,1);
754 }
755 }
756 }
757
758
759 void slv_bnd_initialization(slv_system_t sys)
760 {
761 struct bnd_boundary **bp;
762 int32 value;
763
764 for (bp = slv_get_solvers_bnd_list(sys); *bp != NULL; bp++) {
765 value = bndman_calc_satisfied(*bp);
766 bnd_set_cur_status(*bp,value);
767 bnd_set_pre_status(*bp,value);
768 bnd_set_crossed(*bp,FALSE);
769 if (bnd_kind(*bp) == e_bnd_rel) {
770 value = bndman_calc_at_zero(*bp);
771 bnd_set_at_zero(*bp,value);
772 } else {
773 bnd_set_at_zero(*bp,FALSE);
774 }
775 }
776 }
777
778 struct gl_list_t *slv_get_symbol_list(slv_system_t sys)
779 {
780 if (sys==NULL) {
781 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_symbol_list called with NULL system.");
782 return NULL;
783 }
784 return sys->symbollist;
785 }
786
787 /*---------------------------------------------------------
788 Macros to define
789
790 slv_set_solvers_*_list
791 slv_get_solvers_*_list
792 slv_get_master_*_list
793 */
794 #define DEFINE_SET_SOLVERS_LIST_METHOD(NAME,PROP,TYPE) \
795 void slv_set_solvers_##NAME##_list(slv_system_t sys, struct TYPE **vlist, int size){ \
796 if(sys->PROP.master==NULL){ \
797 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"slv_set_solvers_" #NAME "_list: called before slv_set_master_" #NAME "_list."); \
798 /* might be ok, no return */ \
799 } \
800 sys->PROP.snum = size; \
801 sys->PROP.solver = vlist; \
802 }
803
804 #define DEFINE_SET_SOLVERS_LIST_METHOD_RETURN(NAME,PROP,TYPE) \
805 void slv_set_solvers_##NAME##_list(slv_system_t sys, struct TYPE **vlist, int size){ \
806 if(sys->PROP.master==NULL){ \
807 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"slv_set_solvers_" #NAME "_list: called before slv_set_master_" #NAME "_list."); \
808 return; /* can't be OK, so return now */ \
809 } \
810 sys->PROP.snum = size; \
811 sys->PROP.solver = vlist; \
812 }
813
814 #define DEFINE_GET_SOLVERS_LIST_METHOD(NAME,PROP,TYPE) \
815 struct TYPE **slv_get_solvers_##NAME##_list(slv_system_t sys){ \
816 if (sys->PROP.solver == NULL) { \
817 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_solvers_" #NAME "_list: returning NULL (?)."); \
818 } \
819 return sys->PROP.solver; \
820 }
821
822 #define DEFINE_GETSET_LIST_METHODS(D,D_RETURN) \
823 D_RETURN(var,vars,var_variable) \
824 D(par,pars,var_variable) \
825 D(unattached,unattached,var_variable) \
826 D_RETURN(dvar,dvars,dis_discrete) \
827 D(disunatt,disunatt,dis_discrete) \
828 D_RETURN(rel,rels,rel_relation) \
829 D_RETURN(obj,objs,rel_relation) \
830 D_RETURN(condrel,condrels,rel_relation) \
831 D_RETURN(logrel,logrels,logrel_relation) \
832 D_RETURN(condlogrel,condlogrels,logrel_relation) \
833 D_RETURN(when,whens,w_when) \
834 D_RETURN(bnd,bnds,bnd_boundary)
835
836 /* the slv_set_solvers_*_list methods: some have a 'return' when sys->PROP.master==NULL; others do not: */
837 DEFINE_GETSET_LIST_METHODS(DEFINE_SET_SOLVERS_LIST_METHOD, DEFINE_SET_SOLVERS_LIST_METHOD_RETURN) /*;*/
838
839 /* the slv_get_solvers_*_list methods: all have the same form so it's DEFINE...(D,D) in this case: */
840 DEFINE_GETSET_LIST_METHODS(DEFINE_GET_SOLVERS_LIST_METHOD, DEFINE_GET_SOLVERS_LIST_METHOD) /*;*/
841
842 #define DEFINE_GET_MASTER_LIST_METHOD(NAME,PROP,TYPE) \
843 struct TYPE **slv_get_master_##NAME##_list(slv_system_t sys){ \
844 if (sys->PROP.master == NULL) { \
845 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_master_" #NAME "_list returning NULL (?)."); \
846 } \
847 return sys->PROP.master; \
848 }
849
850 /* the slv_get_master_*_list are also all of the same form, so DEFINE...(D,D) */
851 DEFINE_GETSET_LIST_METHODS(DEFINE_GET_MASTER_LIST_METHOD,DEFINE_GET_MASTER_LIST_METHOD) /*;*/
852
853 /*----------------------------------------------------------------------
854 Macros to define:
855
856 slv_get_num_solvers_TYPE
857 slv_get_num_master_TYPE
858 */
859
860 #define DEFINE_SOLVERS_GET_NUM_METHOD(TYPE) \
861 int slv_get_num_solvers_##TYPE(slv_system_t sys){ \
862 if(sys==NULL){ \
863 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"slv_get_num_solvers_" #TYPE " called with NULL system."); \
864 return 0; \
865 } \
866 return sys->TYPE.snum; \
867 }
868
869 #define DEFINE_MASTER_GET_NUM_METHOD(TYPE) \
870 int slv_get_num_master_##TYPE(slv_system_t sys){ \
871 if(sys==NULL){ \
872 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"slv_get_num_master_" #TYPE " called with NULL system."); \
873 return 0; \
874 } \
875 return sys->TYPE.mnum; \
876 }
877
878 #define DEFINE_SLV_METHODS(D) \
879 D(vars) \
880 D(pars) \
881 D(unattached) \
882 D(dvars) \
883 D(disunatt) \
884 D(rels) \
885 D(condrels) \
886 D(objs) \
887 D(logrels) \
888 D(condlogrels) \
889 D(whens) \
890 D(bnds)
891
892 DEFINE_SLV_METHODS(DEFINE_SOLVERS_GET_NUM_METHOD) /*;*/
893 DEFINE_SLV_METHODS(DEFINE_MASTER_GET_NUM_METHOD) /*;*/
894
895 void slv_set_obj_relation(slv_system_t sys,struct rel_relation *obj)
896 {
897 if (sys==NULL) {
898 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_obj_relation called with NULL system (?).");
899 return;
900 }
901 sys->obj = obj;
902 }
903
904 struct rel_relation *slv_get_obj_relation(slv_system_t sys)
905 {
906 if (sys==NULL) {
907 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_obj_relation called with NULL system (?)");
908 return NULL;
909 }
910 return sys->obj;
911 }
912
913 void slv_set_obj_variable(slv_system_t sys,struct var_variable *objvar,
914 unsigned maximize)
915 {
916 if (sys==NULL) {
917 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_obj_variable called with NULL system.");
918 return;
919 }
920 sys->objvar = objvar;
921 if (objvar!=NULL) {
922 if (maximize) {
923 sys->objvargrad = -1;
924 } else {
925 sys->objvargrad = 1;
926 }
927 } else {
928 sys->objvargrad = 0;
929 }
930 }
931
932 struct var_variable *slv_get_obj_variable(slv_system_t sys)
933 {
934 if (sys==NULL) {
935 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_obj_variable called with NULL system.");
936 return NULL;
937 }
938 return sys->objvar;
939 }
940
941 real64 slv_get_obj_variable_gradient(slv_system_t sys)
942 {
943 if (sys==NULL) {
944 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_obj_variable_gradient called with NULL system.");
945 return 0.0;
946 }
947 return sys->objvargrad;
948 }
949
950
951 void slv_set_need_consistency(slv_system_t sys, int32 need_consistency)
952 {
953 if (sys==NULL) {
954 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_need_consistency called with NULL system.");
955 return;
956 }
957
958 sys->need_consistency = need_consistency;
959 }
960
961
962 int32 slv_need_consistency(slv_system_t sys)
963 {
964 if (sys==NULL) {
965 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_need_consistency called with NULL system.");
966 return 0;
967 }
968 return sys->need_consistency;
969 }
970
971 /*----------------------------------------------------------------
972 Macros to define
973
974 slv_count_vars
975 rels
976 dvars
977 logrels
978 whens
979 bnds
980 */
981
982 #define DEFINE_SLV_COUNT_METHOD(NAME,FILTER,TYPE) \
983 static int slv_count_##NAME(FILTER##_filter_t *filter, struct TYPE **list){ \
984 int ret=0; \
985 assert(list!=NULL); \
986 while(*list!=NULL){ \
987 ret += FILTER##_apply_filter(*list,filter); \
988 list++; \
989 } \
990 return ret; \
991 }
992
993 #define DEFINE_SLV_COUNT_METHODS(D) \
994 D(vars,var,var_variable) \
995 D(rels,rel,rel_relation) \
996 D(dvars,dis,dis_discrete) \
997 D(logrels,logrel,logrel_relation) \
998 D(whens,when,w_when) \
999 D(bnds,bnd,bnd_boundary)
1000
1001 DEFINE_SLV_COUNT_METHODS(DEFINE_SLV_COUNT_METHOD) /*;*/
1002
1003 /*--------------------------------------------------------------
1004 Methods to define
1005 slv_count_solvers_*
1006 slv_count_master_*
1007 */
1008
1009 /** This macro automates the declaration of the slv_count_solvers_* methods */
1010 #define DEFINE_SLV_COUNT_SOLVER_METHOD(NAME,PROP,TYPE,COUNT) \
1011 int slv_count_solvers_ ## NAME ( slv_system_t sys, TYPE ##_filter_t *xxx){ \
1012 if(sys==NULL || sys->PROP.solver == NULL || xxx==NULL){ \
1013 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_cound_solvers_" #NAME " called with NULL"); \
1014 return 0; \
1015 } \
1016 return slv_count_##COUNT(xxx,sys->PROP.solver); \
1017 }
1018
1019 /** This macro automates the declaration of the slv_count_master_* methods */
1020 #define DEFINE_SLV_COUNT_MASTER_METHOD(NAME,PROP,TYPE,COUNT) \
1021 int slv_count_master_ ## NAME ( slv_system_t sys, TYPE ##_filter_t *xxx){ \
1022 if(sys==NULL || sys->PROP.master == NULL || xxx==NULL){ \
1023 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_cound_master_" #NAME " called with NULL"); \
1024 return 0; \
1025 } \
1026 return slv_count_##COUNT(xxx,sys->PROP.master); \
1027 }
1028
1029 /** The macro makes all the various * declarations of the methods of type D (master or solvers) */
1030 #define DEFINE_COUNT_METHODS(D) \
1031 D(vars,vars,var,vars) \
1032 D(pars,pars,var,vars) \
1033 D(unattached,unattached,var,vars) \
1034 D(dvars,dvars,dis,dvars) \
1035 D(disunatt,disunatt,dis,dvars) \
1036 D(rels,rels,rel,rels) \
1037 D(condrels,condrels,rel,rels) \
1038 D(objs,objs,rel,rels) \
1039 D(logrels,logrels,logrel,logrels) \
1040 D(condlogrels,condlogrels,logrel,logrels) \
1041 D(whens,whens,when,whens) \
1042 D(bnds,bnds,bnd,bnds)
1043
1044 /** Invoke the DEFINE_COUNT_METHODS macro for SOLVERS methods */
1045 DEFINE_COUNT_METHODS(DEFINE_SLV_COUNT_SOLVER_METHOD) /*;*/
1046 /** Invoke the DEFINE_COUNT_METHODS macro for MASTER methods */
1047 DEFINE_COUNT_METHODS(DEFINE_SLV_COUNT_MASTER_METHOD) /*;*/
1048
1049 /*------------------------------------------------------*/
1050
1051 static void printwarning(const char * fname, slv_system_t sys)
1052 {
1053 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,
1054 "%s called with bad registered client (%s).",fname,
1055 slv_solver_name(slv_get_selected_solver(sys)));
1056 }
1057
1058 static void printinfo(slv_system_t sys, const char *rname)
1059 {
1060 if (CF(sys,name) == NULL ) {
1061 ERROR_REPORTER_NOLINE(ASC_PROG_NOTE,
1062 "Client %s does not support function '%s'.",
1063 slv_solver_name(slv_get_selected_solver(sys)),rname);
1064 }
1065 }
1066
1067 int slv_eligible_solver(slv_system_t sys)
1068 {
1069 if ( CF(sys,celigible) == NULL ) {
1070 printwarning("slv_eligible_solver",sys);
1071 return 0;
1072 }
1073 return SF(sys,celigible)(sys);
1074 }
1075
1076 int slv_select_solver(slv_system_t sys,int solver){
1077
1078 int status_index;
1079 SlvClientDestroyF *destroy;
1080
1081 if (sys ==NULL) {
1082 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_select_solver called with NULL system.");
1083 return -1;
1084 }
1085 if ( solver >= 0 && solver < NORC ) {
1086 if (sys->ct != NULL && solver != sys->solver) {
1087 CONSOLE_DEBUG("g_SlvNumberOfRegisteredClients = %d, sys->solver = %d", g_SlvNumberOfRegisteredClients, sys->solver);
1088 asc_assert(sys->solver >= -1);
1089 asc_assert(g_SlvNumberOfRegisteredClients > 0);
1090 asc_assert(sys->solver < g_SlvNumberOfRegisteredClients);
1091 destroy = SlvClientsData[sys->solver].cdestroy;
1092 if(destroy!=NULL) {
1093 (destroy)(sys,sys->ct);
1094 sys->ct = NULL;
1095 } else {
1096 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_select_solver: 'cdestroy' is undefined on solver '%s' (index %d).",
1097 slv_solver_name(sys->solver), sys->solver);
1098 }
1099 }
1100
1101 if (sys->ct != NULL) {
1102 return sys->solver;
1103 }
1104
1105 status_index = solver;
1106 sys->solver = solver;
1107 if ( CF(sys,ccreate) != NULL) {
1108 sys->ct = SF(sys,ccreate)(sys,&status_index);
1109 } else {
1110 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_select_solver create failed due to bad client '%s'.",
1111 slv_solver_name(sys->solver));
1112 return sys->solver;
1113 }
1114 if (sys->ct==NULL) {
1115 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"SlvClientCreate failed in slv_select_solver.");
1116 sys->solver = -1;
1117 } else {
1118 if (status_index) {
1119 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"SlvClientCreate succeeded with warning %d %s.",
1120 status_index," in slv_select_solver");
1121 }
1122 /* we could do a better job explaining the client warnings... */
1123 sys->solver = solver;
1124 }
1125 } else {
1126 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_select_solver: invalid solver index '%d'.",
1127 solver);
1128 return -1;
1129 }
1130 return sys->solver;
1131 }
1132
1133
1134 int slv_switch_solver(slv_system_t sys,int solver)
1135 {
1136 int status_index;
1137
1138 if (sys ==NULL) {
1139 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_switch_solver called with NULL system.");
1140 return -1;
1141 }
1142 if( solver >= 0 && solver < g_SlvNumberOfRegisteredClients ){
1143 status_index = solver;
1144 sys->solver = solver;
1145 if ( CF(sys,ccreate) != NULL) {
1146 sys->ct = SF(sys,ccreate)(sys,&status_index);
1147 } else {
1148 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_switch_solver create failed due to bad client '%s'.",
1149 slv_solver_name(sys->solver));
1150 return sys->solver;
1151 }
1152 if (sys->ct==NULL) {
1153 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"SlvClientCreate failed in slv_switch_solver.");
1154 sys->solver = -1;
1155 } else {
1156 if (status_index) {
1157 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"SlvClientCreate succeeded with warning %d %s.",
1158 status_index," in slv_switch_solver");
1159 }
1160 sys->solver = solver;
1161 }
1162 } else {
1163 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"slv_switch_solver called with unknown client '%d'.",solver);
1164 return -1;
1165 }
1166 return sys->solver;
1167 }
1168
1169 void slv_set_char_parameter(char **cp, CONST char *newvalue)
1170 {
1171 if (cp != NULL) {
1172 if (*cp != NULL) {
1173 ascfree(*cp);
1174 }
1175 *cp = ascstrdup(newvalue);
1176 }
1177 }
1178
1179 void slv_destroy_parms(slv_parameters_t *p) {
1180 int32 i,j;
1181 for(i = 0; i < p->num_parms; i++){
1182 switch(p->parms[i].type) {
1183 case char_parm:
1184 ASC_FREE(p->parms[i].info.c.value);
1185 for (j = 0; j < p->parms[i].info.c.high; j++) {
1186 ASC_FREE(p->parms[i].info.c.argv[j]);
1187 }
1188 ASC_FREE(p->parms[i].info.c.argv);
1189 /* FALL THROUGH */
1190 case int_parm:
1191 case bool_parm:
1192 case real_parm:
1193 ASC_FREE(p->parms[i].name);
1194 ASC_FREE(p->parms[i].interface_label);
1195 ASC_FREE(p->parms[i].description);
1196 break;
1197 default:
1198 ERROR_REPORTER_NOLINE(ASC_PROG_WARNING,"Unrecognized parameter type in slv_destroy_parms.");
1199 }
1200 }
1201 if (p->parms && p->dynamic_parms) {
1202 ASC_FREE(p->parms);
1203 }
1204 CONSOLE_DEBUG("Destroyed slv_parameters_t");
1205 }
1206
1207 /*------------------------------------------------------------------------------
1208 IMPROVED (says I) FUNCTIONS FOR DECLARING SOLVER PARAMETERS -- JP
1209 */
1210 /** @page solver-parameters
1211
1212 Additional info on new solver parameter routines. This routine attempts
1213 to make declaration of new parameters possible with simple syntax, without
1214 requiring changes to the underlying data structure. Also aim to eliminate
1215 the extensive #defines used in the old approach, and eliminate the risk of
1216 messing up the parameter list by forgetting to update something.
1217
1218 Usage:
1219 1. declare IDs for the parameters you'll be using via an 'enum'
1220 (last ID is XXXX_PARAMS_COUNT)
1221 2. allocate space for your slv_parameters_t::parms of size XXXX_PARAMS_COUNT
1222 3. for each parameter, call slv_param_* as follows:
1223
1224 slv_param_int(p,XXXX_PARAM_NAME,(SlvParameterInitInt){
1225 {"codename","guiname",3 (==guipagenum) "description"}
1226 ,1 (==default value) ,0 (==min), 100 (==max)
1227 });
1228
1229 4. to access a value from your code, use SLV_PARAM_BOOL(p,XXX_PARAM_NAME) etc
1230 (as defined in slv_common.h)
1231
1232 See example stuff in ida.c
1233 */
1234
1235 static void slv_define_param_meta(struct slv_parameter *p1, const SlvParameterInitMeta *meta, const int index){
1236 /* copy the codename, guiname and description */
1237 asc_assert(meta!=NULL);
1238 asc_assert(p1!=NULL);
1239 p1->name = ascstrdup(meta->codename);
1240 p1->interface_label = ascstrdup(meta->guiname);
1241 p1->description = ascstrdup(meta->description);
1242 p1->display = meta->guipagenum;
1243
1244 /* record the index of this parameter */
1245 p1->number = index;
1246 }
1247
1248 int slv_param_int(slv_parameters_t *p, const int index
1249 ,const SlvParameterInitInt init
1250 ){
1251 struct slv_parameter *p1;
1252 if(p == NULL)return -1;
1253 p1 = &(p->parms[index]);
1254
1255 p1->type = int_parm;
1256 p1->info.i.value = init.val;
1257 p1->info.i.low = init.low;
1258 p1->info.i.high = init.high;
1259
1260 slv_define_param_meta(p1, &(init.meta), index);
1261 return ++(p->num_parms);
1262 }
1263
1264 int slv_param_bool(slv_parameters_t *p, const int index
1265 ,const SlvParameterInitBool init
1266 ){
1267 struct slv_parameter *p1;
1268 if(p == NULL)return -1;
1269 p1 = &(p->parms[index]);
1270
1271 p1->type = bool_parm;
1272 p1->info.b.value = init.val;
1273 p1->info.b.low = 0;
1274 p1->info.b.high = 1;
1275
1276 slv_define_param_meta(p1, &(init.meta), index);
1277 return ++(p->num_parms);
1278 }
1279
1280 int slv_param_real(slv_parameters_t *p, const int index
1281 ,const SlvParameterInitReal init
1282 ){
1283 struct slv_parameter *p1;
1284
1285 if(p == NULL)return -1;
1286 p1 = &(p->parms[index]);
1287
1288 p1->type = real_parm;
1289 p1->info.r.value = init.val;
1290 p1->info.r.low = init.low;
1291 p1->info.r.high = init.high;
1292
1293 slv_define_param_meta(p1, &(init.meta), index);
1294 return ++(p->num_parms);
1295 }
1296
1297 int slv_param_char(slv_parameters_t *p, const int index
1298 ,const SlvParameterInitChar init
1299 ,char *options[]
1300 ){
1301 int i, noptions;
1302 struct slv_parameter *p1;
1303 if(p == NULL)return -1;
1304 p1 = &(p->parms[index]);
1305 p1->type = char_parm;
1306
1307 /* find the length by hunting for the NULL at the end */
1308 for(i=0; options[i]!=NULL; ++i){
1309 /* CONSOLE_DEBUG("FOUND init.options[%d]='%s'",i,options[i]); */
1310 }
1311 noptions = i;
1312 /* CONSOLE_DEBUG("THERE ARE %d CHAR OPTIONS IN PARAMETER '%s'", noptions, init.meta.codename); */
1313
1314 p1->info.c.high = noptions;
1315 p1->info.c.value = strdup(init.val);
1316 p1->info.c.argv = ASC_NEW_ARRAY(char *,noptions);
1317
1318 for(i = 0; i < noptions; ++i){
1319 p1->info.c.argv[i] = strdup(options[i]);
1320 /* CONSOLE_DEBUG("Copied '%s' --> argv[%d] = '%s'",options[i],i,p1->info.c.argv[i]); */
1321 }
1322
1323 slv_define_param_meta(p1, &(init.meta), index);
1324 return ++(p->num_parms);
1325 }
1326
1327 int32 slv_define_parm(slv_parameters_t *p,
1328 enum parm_type type,
1329 char *name,
1330 char *interface_label,
1331 char *description,
1332 union parm_arg value,
1333 union parm_arg low,
1334 union parm_arg high,
1335 int32 display)
1336 {
1337 int32 len,length,i, err=1;
1338 if (p == NULL) {
1339 return -1;
1340 }
1341 length = p->num_parms;
1342
1343 switch (type) {
1344 case int_parm:
1345 err = 0;
1346 p->parms[length].info.i.value = value.argi;
1347 p->parms[length].info.i.low = low.argi;
1348 p->parms[length].info.i.high = high.argi;
1349 break;
1350
1351 case bool_parm:
1352 err = 0;
1353 p->parms[length].info.b.value = value.argb;
1354 p->parms[length].info.b.low = low.argb;
1355 p->parms[length].info.b.high = high.argb;
1356 break;
1357
1358 case real_parm:
1359 err = 0;
1360 p->parms[length].info.r.value = value.argr;
1361 p->parms[length].info.r.low = low.argr;
1362 p->parms[length].info.r.high = high.argr;
1363 break;
1364
1365 case char_parm:
1366 err = 0;
1367 p->parms[length].info.c.argv =
1368 (char **)ascmalloc(high.argi*sizeof(char *));
1369 for (i = 0; i < high.argi; i++) {
1370 len = strlen(low.argv[i]);
1371 p->parms[length].info.c.argv[i] =ASC_NEW_ARRAY(char,len+1);
1372 strcpy(p->parms[length].info.c.argv[i],low.argv[i]);
1373 }
1374
1375 p->parms[length].info.c.value =
1376 (char *)ascmalloc(strlen(value.argc)+1*sizeof(char));
1377 strcpy(p->parms[length].info.c.value,value.argc);
1378
1379 p->parms[length].info.c.high = high.argi;
1380 break;
1381
1382 default:
1383 return -1;
1384 }
1385 if (!err) {
1386 p->parms[length].type = type;
1387 p->parms[length].number = length;
1388
1389 len = strlen(name);
1390 p->parms[length].name = ASC_NEW_ARRAY(char,len+1);
1391 strcpy(p->parms[length].name,name);
1392
1393 len = strlen(interface_label);
1394 p->parms[length].interface_label = ASC_NEW_ARRAY(char,len+1);
1395 strcpy(p->parms[length].interface_label,interface_label);
1396
1397 len = strlen(description);
1398 p->parms[length].description = ASC_NEW_ARRAY(char,len+1);
1399 strcpy(p->parms[length].description,description);
1400
1401 p->parms[length].display = display;
1402 } else {
1403 p->parms[length].type = -1;
1404 }
1405 p->num_parms++;
1406 return p->num_parms;
1407 }
1408
1409 /*--------------------------------*/
1410
1411
1412 int slv_get_selected_solver(slv_system_t sys)
1413 {
1414 if (sys!=NULL) return sys->solver;
1415 return -1;
1416 }
1417
1418 int32 slv_get_default_parameters(int sindex,
1419 slv_parameters_t *parameters)
1420 {
1421 if (sindex >= 0 && sindex < NORC) {
1422 if ( SlvClientsData[sindex].getdefparam == NULL ) {
1423 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_default_parameters called with parameterless index.");
1424 return 0;
1425 } else {
1426 /* send NULL system when setting up interface */
1427 (SlvClientsData[sindex].getdefparam)(NULL,NULL,parameters);
1428 return 1;
1429 }
1430 } else {
1431 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_get_default_parameters called with unregistered index.");
1432 return 0;
1433 }
1434 }
1435
1436 /*-----------------------------------------------------------
1437 These macros do some more elimination of repetition. Here we're
1438 trying to replace some more complex 'method-like' calls on
1439 slv_system_t:
1440
1441 These macros use macro-argument-concatenation and macro stringification.
1442 Verified that the former works with Visual C++.
1443 http://www.codeproject.com/macro/metamacros.asp
1444 */
1445
1446 /** Define a method like 'void slv_METHODNAME(sys)' */
1447 #define DEFINE_SLV_PROXY_METHOD_VOID(METHOD) \
1448 void slv_ ## METHOD (slv_system_t sys){ \
1449 if(CF(sys,METHOD)==NULL){ \
1450 printwarning(#METHOD,sys); \
1451 return; \
1452 } \
1453 SF(sys,METHOD)(sys,sys->ct); \
1454 }
1455
1456 /** Define a method like 'RETURNTYPE slv_METHOD(sys)'; */
1457 #define DEFINE_SLV_PROXY_METHOD(METHOD,PROP,RETTYPE,ERRVAL) \
1458 RETTYPE slv_ ## METHOD (slv_system_t sys){ \
1459 if(CF(sys,PROP)==NULL){ \
1460 printinfo(sys, #METHOD); \
1461 return ERRVAL; \
1462 } \
1463 return SF(sys,PROP)(sys,sys->ct); \
1464 }
1465
1466 /** Define a method like 'void slv_METHOD(sys,TYPE PARAMNAME)'; */
1467 #define DEFINE_SLV_PROXY_METHOD_PARAM(METHOD,PROP,PARAMTYPE,PARAMNAME) \
1468 void slv_ ## METHOD (slv_system_t sys, PARAMTYPE PARAMNAME){ \
1469 if(CF(sys,PROP)==NULL){ \
1470 printwarning(#METHOD,sys); \
1471 return; \
1472 } \
1473 SF(sys,PROP)(sys,sys->ct, PARAMNAME); \
1474 }
1475
1476 DEFINE_SLV_PROXY_METHOD_PARAM(get_parameters,getparam,slv_parameters_t*,parameters) /*;*/
1477
1478 void slv_set_parameters(slv_system_t sys,slv_parameters_t *parameters)
1479 {
1480 if ( CF(sys,setparam) == NULL ) {
1481 printwarning("slv_set_parameters",sys);
1482 return;
1483 }
1484 if (parameters->whose != sys->solver) {
1485 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,
1486 "slv_set_parameters cannot pass parameters from one solver to a"
1487 " another.");
1488 return;
1489 }
1490 SF(sys,setparam)(sys,sys->ct,parameters);
1491 }
1492
1493 DEFINE_SLV_PROXY_METHOD_PARAM(get_status,getstatus,slv_status_t*,status) /*;*/
1494 DEFINE_SLV_PROXY_METHOD(get_linsol_sys, getlinsol, linsol_system_t, NULL) /*;*/
1495 DEFINE_SLV_PROXY_METHOD(get_sys_mtx, getsysmtx, mtx_matrix_t, NULL) /*;*/
1496 DEFINE_SLV_PROXY_METHOD(get_linsolqr_sys, getlinsys, linsolqr_system_t, NULL) /*;*/
1497 DEFINE_SLV_PROXY_METHOD_PARAM(dump_internals,dumpinternals,int,level) /*;*/
1498 DEFINE_SLV_PROXY_METHOD(presolve,presolve,int,-1) /*;*/
1499 DEFINE_SLV_PROXY_METHOD(resolve,resolve,int,-1) /*;*/
1500 DEFINE_SLV_PROXY_METHOD(iterate,iterate,int,-1) /*;*/
1501 DEFINE_SLV_PROXY_METHOD(solve,solve,int,-1) /*;*/
1502
1503 /*-----------------------------------------------------------*/
1504
1505 SlvClientToken slv_get_client_token(slv_system_t sys)
1506 {
1507 if (sys==NULL) {
1508 FPRINTF(stderr,"slv_get_client_token called with NULL system.");
1509 return NULL;
1510 }
1511 return sys->ct;
1512 }
1513
1514
1515 void slv_set_client_token(slv_system_t sys, SlvClientToken ct)
1516 {
1517 if (sys==NULL) {
1518 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_client_token called with NULL system.");
1519 return;
1520 }
1521 sys->ct = ct;
1522 }
1523
1524 void slv_set_solver_index(slv_system_t sys, int solver)
1525 {
1526 if (sys==NULL) {
1527 ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"slv_set_solver_index called with NULL system.");
1528 return;
1529 }
1530 sys->solver = solver;
1531 }
1532
1533 /*********************************************************************\
1534 unregistered client functions that need to go elsewhere(other files).
1535 hereunder are utility calls which are unstandardized
1536 \*********************************************************************/
1537
1538 boolean slv_change_basis(slv_system_t sys, int32 var, mtx_range_t *rng)
1539 {
1540 (void)sys;
1541 (void)var;
1542 (void)rng;
1543 ASC_PANIC("fix me");
1544 return 0;
1545 }
1546
1547 /*
1548 * This routine is provided as the start of some report generation
1549 * capabilities. It operates off the main solve system and
1550 * writes out the relation residuals and variable values for
1551 * the entire problem to the named file.
1552 * Isn't very bright.
1553 */
1554
1555 void slv_print_output(FILE *out, slv_system_t sys)
1556 {
1557 struct rel_relation **rp;
1558 struct var_variable **vp;
1559 int nrels, nvars,c;
1560
1561 vp = slv_get_master_var_list(sys);
1562 nvars = slv_get_num_master_vars(sys);
1563 FPRINTF(out,"%-6s %-12s\n",
1564 "INDEX","LEVEL");
1565 for (c=0; c<nvars; c++) {
1566 FPRINTF(out," % -6d % -12.8e\n",c, var_value(vp[c]));
1567 }
1568 PUTC('\n',out);
1569
1570 rp = slv_get_master_rel_list(sys);
1571 nrels = slv_get_num_master_rels(sys);
1572 FPRINTF(out,"%-6s %-12s\n",
1573 "INDEX","RESDUAL");
1574 for (c=0; c<nrels; c++) {
1575 FPRINTF(out," % -6d % -12.8e\n",c, rel_residual(rp[c]));
1576 }
1577 }
1578
1579 int32 slv_obj_select_list(slv_system_t sys,int32 **rip)
1580 {
1581 int32 len,count,i, *ra;
1582 static rel_filter_t rfilter;
1583 struct rel_relation **rlist=NULL;
1584 len = slv_get_num_solvers_objs(sys);
1585 ra = *rip = (int32 *)ascmalloc((len+1)*sizeof(int32 *));
1586 rfilter.matchbits = (REL_INCLUDED);
1587 rfilter.matchvalue =(REL_INCLUDED);
1588 rlist = slv_get_solvers_obj_list(sys);
1589 count = 0;
1590 for (i = 0; i < len; i++) {
1591 if (rel_apply_filter(rlist[i],&rfilter)) {
1592 ra[count] = i;
1593 count++;
1594 }
1595 }
1596 ra[count] = -1;
1597 return count;
1598 }
1599
1600 int32 slv_get_obj_num(slv_system_t sys)
1601 {
1602 int32 len,i;
1603 struct rel_relation *obj;
1604 struct rel_relation **rlist=NULL;
1605 len = slv_get_num_solvers_objs(sys);
1606 rlist = slv_get_solvers_obj_list(sys);
1607 obj = slv_get_obj_relation(sys);
1608 if (obj != NULL) {
1609 for (i = 0; i < len; i++) {
1610 if (rlist[i] == obj) {
1611 return i;
1612 }
1613 }
1614 }
1615 return -1;
1616 }
1617
1618 int32 slv_near_bounds(slv_system_t sys,real64 epsilon,
1619 int32 **vip)
1620 {
1621 int32 len,i, *va, vindex;
1622 real64 comp;
1623 static var_filter_t vfilter;
1624 struct var_variable **vlist=NULL;
1625 len = slv_get_num_solvers_vars(sys);
1626 va = *vip = (int32 *)ascmalloc((2*len+2)*sizeof(int32 *));
1627 vfilter.matchbits = (VAR_FIXED | VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE);
1628 vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE);
1629 vlist = slv_get_solvers_var_list(sys);
1630 va[0] = va[1] = 0;
1631 vindex = 2;
1632 for (i = 0; i < len; i++) {
1633 if (var_apply_filter(vlist[i],&vfilter)) {
1634 comp = (var_value(vlist[i]) - var_lower_bound(vlist[i]))
1635 / var_nominal(vlist[i]);
1636 if (comp < epsilon) {
1637 va[vindex] = i;
1638 vindex++;
1639 va[0]++;
1640 }
1641 }
1642 }
1643 for (i = 0; i < len; i++) {
1644 if (var_apply_filter(vlist[i],&vfilter)) {
1645 comp = (var_upper_bound(vlist[i]) - var_value(vlist[i]))
1646 / var_nominal(vlist[i]);
1647 if (comp < epsilon) {
1648 va[vindex] = i;
1649 vindex++;
1650 va[1]++;
1651 }
1652 }
1653 }
1654 return vindex - 2;
1655 }
1656
1657 int32 slv_far_from_nominals(slv_system_t sys,real64 bignum,
1658 int32 **vip)
1659 {
1660 int32 len,i, *va, vindex;
1661 real64 comp;
1662 static var_filter_t vfilter;
1663 struct var_variable **vlist=NULL;
1664 len = slv_get_num_solvers_vars(sys);
1665 va = *vip = (int32 *)ascmalloc((len+1)*sizeof(int32 *));
1666 vfilter.matchbits = (VAR_FIXED | VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE);
1667 vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE);
1668 vlist = slv_get_solvers_var_list(sys);
1669 vindex = 0;
1670 for (i = 0; i < len; i++) {
1671 if (var_apply_filter(vlist[i],&vfilter)) {
1672 comp = fabs(var_value(vlist[i]) - var_nominal(vlist[i]))
1673 / var_nominal(vlist[i]);
1674 if (comp > bignum) {
1675 va[vindex] = i;
1676 vindex++;
1677 }
1678 }
1679 }
1680 return vindex;
1681 }
1682
1683 #ifdef IDA_NEW_ANALYSE
1684 const void *slv_get_diffvars(slv_system_t sys){
1685 return sys->diffvars;
1686 }
1687 int slv_set_diffvars(slv_system_t sys,void *diffvars){
1688 sys->diffvars = diffvars;
1689 }
1690 #endif
1691

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22