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

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