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

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