1 |
/* |
2 |
* Discrete Variable Module |
3 |
* by Vicente Rico-Ramirez |
4 |
* Created: 06/96 |
5 |
* Version: $Revision: 1.7 $ |
6 |
* Version control file: $RCSfile: discrete.h,v $ |
7 |
* Date last modified: $Date: 1998/03/30 22:06:54 $ |
8 |
* Last modified by: $Author: rv2a $ |
9 |
* |
10 |
* This file is part of the SLV solver. |
11 |
* |
12 |
* The SLV solver is free software; you can redistribute |
13 |
* it and/or modify it under the terms of the GNU General Public License as |
14 |
* published by the Free Software Foundation; either version 2 of the |
15 |
* License, or (at your option) any later version. |
16 |
* |
17 |
* The SLV solver is distributed in hope that it will be |
18 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 |
* General Public License for more details. |
21 |
* |
22 |
* You should have received a copy of the GNU General Public License |
23 |
* along with the program; if not, write to the Free Software Foundation, |
24 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
25 |
* COPYING. COPYING is found in ../compiler. |
26 |
* |
27 |
*/ |
28 |
|
29 |
/* |
30 |
* Contents: Discrete Variable module (ascend) |
31 |
* |
32 |
* Dates: 06/96 - original version |
33 |
* |
34 |
* Description: This is the ascend version of the bvar module. This |
35 |
* version should be used by any user who receives his/her |
36 |
* equations indirectly from an instance tree created by the |
37 |
* ASCEND compiler. |
38 |
* |
39 |
*/ |
40 |
|
41 |
#ifndef dis__already_included |
42 |
#define dis__already_included |
43 |
/* |
44 |
* requires #include <stdio.h> |
45 |
* requires #include "base.h" |
46 |
* requires #include "slv_types.h" |
47 |
* requires #include "list.h" |
48 |
*/ |
49 |
|
50 |
|
51 |
enum discrete_kind { |
52 |
e_dis_boolean_t, |
53 |
e_dis_integer_t, |
54 |
e_dis_symbol_t, |
55 |
e_dis_error_t |
56 |
}; |
57 |
|
58 |
struct dis_discrete { |
59 |
enum discrete_kind t; /* kind of discrete variable */ |
60 |
SlvBackendToken datom; /* the associated ascend ATOM */ |
61 |
struct dis_discrete **sos; /* not implemented yet. Used to represent */ |
62 |
/* integer and symbols in terms of booleans */ |
63 |
struct dis_discrete *source; /* Not implemented yet. This would be used for |
64 |
booleans, members of sos, to point back to |
65 |
the variable which is using it */ |
66 |
struct gl_list_t *whens; /* whens in which this variable is used */ |
67 |
int32 range; /* Ranges for integer or symbols.Sme as above */ |
68 |
int32 cur_value; /* current value */ |
69 |
int32 pre_value; /* previous value */ |
70 |
int32 sindex; /* index in the solver clients list */ |
71 |
int32 mindex; /* index in the slv_system_t master list */ |
72 |
uint32 flags; /* batch of binary flags */ |
73 |
}; |
74 |
|
75 |
/* |
76 |
* Do not dereference this structure except |
77 |
* via macros/functions, because we make no commitments about being |
78 |
* backward compatible with such code. |
79 |
*/ |
80 |
|
81 |
typedef struct dis_filter_structure { |
82 |
uint32 matchbits; |
83 |
uint32 matchvalue; |
84 |
} dis_filter_t; |
85 |
|
86 |
|
87 |
extern struct dis_discrete *dis_create(SlvBackendToken, |
88 |
struct dis_discrete *); |
89 |
/* |
90 |
* dis_create(instance,newdis) |
91 |
* struct dis_discrete *newdis; |
92 |
* SlvBackendToken instance; |
93 |
* |
94 |
* Creates a discrete variable given the variable instance. |
95 |
* If the discrete var supplied is NULL, we allocate the memory for the |
96 |
* discrete var we return, else we just init the memory you hand us and |
97 |
* return it to you. |
98 |
* We set the fields instance. Setting the rest of the information |
99 |
* is the job of the bridge building function between the ascend instance |
100 |
* tree (or other discrete var back end) and the slv_system_t. |
101 |
*/ |
102 |
|
103 |
#ifdef NDEBUG |
104 |
#define dis_instance(dis) ((dis)->datom) |
105 |
#define dis_set_instance(dis,i) ((dis)->datom = (i)) |
106 |
#else |
107 |
#define dis_instance(dis) dis_instanceF(dis) |
108 |
#define dis_set_instance(dis,i) dis_set_instanceF((dis),(i)) |
109 |
#endif /* NDEBUG */ |
110 |
|
111 |
|
112 |
extern SlvBackendToken dis_instanceF(const struct dis_discrete *); |
113 |
extern void dis_set_instanceF(struct dis_discrete *,SlvBackendToken ); |
114 |
/* |
115 |
* i = dis_instance(dis); |
116 |
* dis_set_instance(dis,i); |
117 |
* struct dis_discrete *dis; |
118 |
* SlvBackendToken i; |
119 |
* Returns/sets the ATOM instance associated with the variable. |
120 |
*/ |
121 |
|
122 |
extern char *dis_make_name(const slv_system_t,const struct dis_discrete *); |
123 |
extern char *dis_make_xname(const struct dis_discrete *); |
124 |
/* |
125 |
* name = dis_make_name(sys,dis) |
126 |
* name = dis_make_xname(dis) |
127 |
* struct dis_discrete *dis; |
128 |
* |
129 |
* Creates and returns a sufficiently large string storing the |
130 |
* qualified name of var as known by the solver instance tree. |
131 |
* If the instance is not found, "?" is returned. The string |
132 |
* should be destroyed when no longer in use. |
133 |
* dis_make_xname returns the index name, eg x23 rather than full name. |
134 |
* |
135 |
* The name of a dis is context dependent, so you have to provide the |
136 |
* slv_system_t from which you got the dis. |
137 |
*/ |
138 |
|
139 |
extern void dis_write_name(const slv_system_t, |
140 |
const struct dis_discrete *,FILE *); |
141 |
/* |
142 |
* dis_write_name(sys,dis,file); |
143 |
* Writes a name to the file given. |
144 |
* Does not print any whitespace, including carriage returns. |
145 |
* If sys is NULL, writes full ascend name. If file or var is NULL |
146 |
* does not write. |
147 |
*/ |
148 |
|
149 |
void dis_destroy(struct dis_discrete *); |
150 |
/* |
151 |
* dis_destroy(dis); |
152 |
* struct dis_discrete *dis; |
153 |
* |
154 |
* Since someone else allocates dis en masse, this just sets |
155 |
* our integrity check to ERROR. |
156 |
*/ |
157 |
|
158 |
extern struct gl_list_t *dis_whens_list(struct dis_discrete *); |
159 |
extern void dis_set_whens_list(struct dis_discrete *, struct gl_list_t *); |
160 |
/* |
161 |
* wlist = dis_whens_list(dis) |
162 |
* dis_set_whens_list(dis,wlist) |
163 |
* struct gl_list_t *wlist; |
164 |
* struct dis_discrete *dis; |
165 |
* |
166 |
* Sets or retrieves the list of whens of the given dis |
167 |
*/ |
168 |
|
169 |
#ifdef NDEBUG |
170 |
#define dis_kind(dis) (dis)->t |
171 |
#define dis_set_kind(dis,kind) (dis)->t = (kind) |
172 |
#else |
173 |
#define dis_kind(dis) dis_kindF(dis) |
174 |
#define dis_set_kind(dis,kind) dis_set_kindF((dis),(kind)) |
175 |
#endif /* NDEBUG */ |
176 |
|
177 |
extern enum discrete_kind dis_kindF(const struct dis_discrete *); |
178 |
extern void dis_set_kindF(struct dis_discrete *, enum discrete_kind); |
179 |
/* |
180 |
* enum discrete_kind dis_kind(dis); |
181 |
* void dis_set_kind(dis,kind); |
182 |
* const struct dis_discrete *dis; |
183 |
* enum discrete_kind kind; |
184 |
* Gets/sets the enumerated type that indicates the type of dis. |
185 |
*/ |
186 |
|
187 |
#ifdef NDEBUG |
188 |
#define dis_mindex(dis) (dis)->mindex |
189 |
#define dis_set_mindex(dis,n) (dis)->mindex = (n) |
190 |
#else |
191 |
#define dis_mindex(dis) dis_mindexF(dis) |
192 |
#define dis_set_mindex(dis,n) dis_set_mindexF((dis),(n)) |
193 |
#endif /* NDEBUG */ |
194 |
|
195 |
extern int32 dis_mindexF(const struct dis_discrete *); |
196 |
extern void dis_set_mindexF(struct dis_discrete *,int32); |
197 |
/* |
198 |
* index = dis_mindex(dis) |
199 |
* dis_set_mindex(dis,index) |
200 |
* int32 index; |
201 |
* struct dis_discrete *dis; |
202 |
* |
203 |
* Gets/sets the index of the variable as it appears |
204 |
* in a variable list. |
205 |
*/ |
206 |
|
207 |
#ifdef NDEBUG |
208 |
#define dis_sindex(dis) (dis)->sindex |
209 |
#define dis_set_sindex(dis,n) (dis)->sindex = (n) |
210 |
#else |
211 |
#define dis_sindex(dis) dis_sindexF(dis) |
212 |
#define dis_set_sindex(dis,n) dis_set_sindexF((dis),(n)) |
213 |
#endif /* NDEBUG */ |
214 |
|
215 |
extern int32 dis_sindexF(const struct dis_discrete *); |
216 |
extern void dis_set_sindexF(struct dis_discrete *,int32); |
217 |
/* |
218 |
* index = dis_sindex(dis) |
219 |
* dis_set_sindex(dis,index) |
220 |
* int32 index; |
221 |
* struct dis_discrete *dis; |
222 |
* |
223 |
* Gets/sets the index of the variable as it appears |
224 |
* in a solvers variable list. |
225 |
*/ |
226 |
|
227 |
extern int32 dis_value(const struct dis_discrete *); |
228 |
extern void dis_set_value(struct dis_discrete *,int32); |
229 |
/* |
230 |
* value = dis_value(dis) |
231 |
* dis_set_value(dis,value) |
232 |
* int32 value; |
233 |
* struct dis_discrete *dis; |
234 |
* |
235 |
* Gets/sets the currrent value field of the discrete variable. |
236 |
* dis_set_value also assigns the value before modification to |
237 |
* the previous value field of the dis_discrete |
238 |
*/ |
239 |
|
240 |
|
241 |
extern void dis_set_inst_and_field_value(struct dis_discrete *,int32); |
242 |
extern void dis_set_value_from_inst(struct dis_discrete *,struct gl_list_t *); |
243 |
#define dis_set_boolean_value(dis,val) dis_set_inst_and_field_value(dis,val) |
244 |
/* |
245 |
* void dis_set_inst_and_field_value |
246 |
* Set the current value of the dis_discrete and the value of |
247 |
* the corresponding instance simultaneously. Such a value is |
248 |
* passed as argument |
249 |
* void dis_set_value_from_inst: |
250 |
* Set the current value of a dis_discrete based on the value of the |
251 |
* corresponding instance. |
252 |
* In the case of symbols, dis_set_inst_and_field_value has no effect, |
253 |
* since the value of a symbol instance is not a integer, but a symchar, |
254 |
* and a solver client will never redefine it. |
255 |
* If the token is constant, the asssignment wont be done and the |
256 |
* value is not affected. |
257 |
* the las function is particularly useful for symbol instances. |
258 |
* It is used to assign integer values to the field |
259 |
* value of a dis, using values coming from dis->datom where |
260 |
* datom is a inst. In teh case of symbol, we get an "equivalent" |
261 |
* integer value. |
262 |
* |
263 |
* They also assign the value before modification to |
264 |
* the previous value field of the dis_discrete |
265 |
*/ |
266 |
|
267 |
|
268 |
extern int32 dis_previous_value(const struct dis_discrete *); |
269 |
extern void dis_set_previous_value(struct dis_discrete *,int32); |
270 |
/* |
271 |
* value = dis_previous_value(dis) |
272 |
* dis_set_previous_value(dis,value) |
273 |
* int32 value; |
274 |
* struct dis_discrete *dis; |
275 |
* |
276 |
* Gets/sets the previous value field of the discrete variable. |
277 |
*/ |
278 |
|
279 |
|
280 |
/* |
281 |
* What constitutes a boolean_var |
282 |
* is controlled by the ascend server via the following functions. |
283 |
* Clients shouldn't use these. |
284 |
*/ |
285 |
|
286 |
#define BOOLEAN_VAR_STR "boolean_var" |
287 |
|
288 |
extern boolean boolean_var(SlvBackendToken); |
289 |
|
290 |
/* |
291 |
* e.g. if (boolean_var(inst)) {} |
292 |
* SlvBackendToken inst; |
293 |
* Returns true if the instance in question matches the currently |
294 |
* known definition of boolean_var. |
295 |
*/ |
296 |
|
297 |
extern boolean set_boolean_types(void); |
298 |
/* |
299 |
* Sets (changes) the current definition of boolean_var to match |
300 |
* the current library. Returns 1 if unsuccessful, 0 if ok. |
301 |
*/ |
302 |
|
303 |
extern int32 dis_nominal(struct dis_discrete *); |
304 |
extern void dis_set_nominal(struct dis_discrete *,int32); |
305 |
/* |
306 |
* nominal = dis_nominal(dis) |
307 |
* dis_set_nominal(dis,nominal) |
308 |
* int32 nominal; |
309 |
* struct dis_discrete *dis; |
310 |
* |
311 |
* Gets/sets the nominal value of the boolean variable. |
312 |
* If no nominal field in dis, returns 1. |
313 |
*/ |
314 |
|
315 |
extern uint32 dis_fixed(struct dis_discrete *); |
316 |
extern void dis_set_fixed(struct dis_discrete *, uint32); |
317 |
/* |
318 |
* fixed = dis_fixed(dis) |
319 |
* dis_set_fixed(dis,fixed) |
320 |
* uint32 fixed; |
321 |
* struct dis_discrete *dis; |
322 |
* |
323 |
* Gets/sets the fixed flag of the boolean variable. This |
324 |
* has side effects in the ascend instance, with which |
325 |
* we are keeping the bits in sync. |
326 |
*/ |
327 |
|
328 |
|
329 |
/* |
330 |
* The section of flagbit definitions |
331 |
*/ |
332 |
|
333 |
#define DIS_INCIDENT 0x1 |
334 |
#define DIS_INWHEN 0x2 |
335 |
#define DIS_BVAR 0x4 |
336 |
#define DIS_CONST 0x8 |
337 |
#define DIS_FIXED 0x10 |
338 |
#define DIS_INBLOCK 0x20 |
339 |
#define DIS_ACTIVE 0x40 |
340 |
#define DIS_BOOLEAN 0x80 |
341 |
#define DIS_VAL_MODIFIED 0x100 |
342 |
#define DIS_CHANGES_STRUCTURE 0x200 |
343 |
|
344 |
/* |
345 |
* DIS_INCIDENT is this variable incident on some equation in |
346 |
* the slv_system? |
347 |
* DIS_INWHEN is this variable in some WHEN in the slv_system? |
348 |
* DIS_BVAR do we think this var a 'boolean_var'? |
349 |
* DIS_CONST is this discrete variable a constant |
350 |
* DIS_FIXED is this variable considered fixed currently? |
351 |
* DIS_INBLOCK |
352 |
* DIS_ACTIVE is this variable currently active ? |
353 |
* DIS_BOOLEAN is this variable of type e_dis_boolean_t ? |
354 |
* DIS_VAL_MODIFIED Did the value of this variable change after the |
355 |
* last logical solution ? |
356 |
* DIS_CHANGES_STRUCTURE Is this discrete variable associated with a WHEN |
357 |
* changes the structural analysis of a conditional |
358 |
* model |
359 |
*/ |
360 |
|
361 |
#ifdef NDEBUG |
362 |
#define dis_flags(dis) ((dis)->flags) |
363 |
#define dis_set_flags(dis,f) ((dis)->flags = (f)) |
364 |
#else |
365 |
#define dis_flags(dis) dis_flagsF(dis) |
366 |
#define dis_set_flags(dis,f) dis_set_flagsF((dis),(f)) |
367 |
#endif /* NDEBUG */ |
368 |
|
369 |
extern uint32 dis_flagsF(const struct dis_discrete *); |
370 |
extern void dis_set_flagsF(struct dis_discrete *,uint32); |
371 |
/* |
372 |
* dis_flags(dis); |
373 |
* dis_set_flags(dis,flags); |
374 |
* struct dis_discrete *dis; |
375 |
* uint32 flags; |
376 |
* |
377 |
* dis_flags(dis) returns the flags field of the var. |
378 |
* dis_set_flags(dis,flags) sets the entire flag field to the |
379 |
* value of flags given. This flags value should be composed |
380 |
* of the dis_xxx values defined above. |
381 |
*/ |
382 |
|
383 |
extern uint32 dis_flagbit(const struct dis_discrete *,const uint32); |
384 |
/* |
385 |
* dis_flagbit(dis,name); |
386 |
* struct dis_discrete *dis; |
387 |
* uint32 name; |
388 |
* name should be a DIS_xx flag defined above) |
389 |
* Returns the value of the bit specified from the variable flags. |
390 |
*/ |
391 |
|
392 |
extern void dis_set_flagbit(struct dis_discrete *,uint32, uint32); |
393 |
/* |
394 |
* struct dis_discrete *dis; |
395 |
* unsigned int NAME,oneorzero; |
396 |
* dis_set_flagbit(dis,NAME,oneorzero) |
397 |
* |
398 |
* Sets the bit, which should be referred to by its macro name, |
399 |
* on if oneorzero is >0 and off is oneorzero is 0. |
400 |
* The macro names are the defined up at the top of this file. |
401 |
*/ |
402 |
|
403 |
extern int32 dis_apply_filter(const struct dis_discrete *, |
404 |
const dis_filter_t *); |
405 |
/* |
406 |
* value = dis_apply_filter(dis,filter) |
407 |
* int32 value; |
408 |
* struct dis_discrete *dis; |
409 |
* dis_filter_t *filter; |
410 |
* |
411 |
* Returns 1 if filter and var flags are compatible, 0 elsewise. |
412 |
* See the filter description in rel.h. This is exactly the same. |
413 |
*/ |
414 |
|
415 |
#ifdef NDEBUG |
416 |
#define dis_inwhen(dis) ((dis)->flags & DIS_INWHEN) |
417 |
#define dis_const(dis) ((dis)->flags & DIS_CONST) |
418 |
#define dis_in_block(dis) ((dis)->flags & DIS_INBLOCK) |
419 |
#define dis_incident(dis) ((dis)->flags & DIS_INCIDENT) |
420 |
#define dis_active(dis) ((dis)->flags & DIS_ACTIVE) |
421 |
#define dis_boolean(dis) ((dis)->flags & DIS_BOOLEAN) |
422 |
#define dis_val_modified(dis) ((dis)->flags & DIS_VAL_MODIFIED) |
423 |
#define dis_changes_structure(dis) ((dis)->flags & DIS_CHANGES_STRUCTURE) |
424 |
#else |
425 |
#define dis_inwhen(dis) dis_flagbit((dis),DIS_INWHEN) |
426 |
#define dis_const(dis) dis_flagbit((dis),DIS_CONST) |
427 |
#define dis_in_block(dis) dis_flagbit((dis),DIS_INBLOCK) |
428 |
#define dis_incident(dis) dis_flagbit((dis),DIS_INCIDENT) |
429 |
#define dis_active(dis) dis_flagbit((dis),DIS_ACTIVE) |
430 |
#define dis_boolean(dis) dis_flagbit((dis),DIS_BOOLEAN) |
431 |
#define dis_val_modified(dis) dis_flagbit((dis),DIS_VAL_MODIFIED) |
432 |
#define dis_changes_structure(dis) dis_flagbit((dis),DIS_CHANGES_STRUCTURE) |
433 |
#endif /* NDEBUG */ |
434 |
|
435 |
#define dis_set_inwhen(dis,b) dis_set_flagbit((dis),DIS_INWHEN,(b)) |
436 |
#define dis_set_const(dis,b) dis_set_flagbit((dis),DIS_CONST,(b)) |
437 |
#define dis_set_in_block(dis,b) dis_set_flagbit((dis),DIS_INBLOCK,(b)) |
438 |
#define dis_set_incident(dis,b) dis_set_flagbit((dis),DIS_INCIDENT,(b)) |
439 |
#define dis_set_active(dis,b) dis_set_flagbit((dis),DIS_ACTIVE,(b)) |
440 |
#define dis_set_boolean(dis,b) dis_set_flagbit((dis),DIS_BOOLEAN,(b)) |
441 |
#define dis_set_val_modified(dis,b) \ |
442 |
dis_set_flagbit((dis),DIS_VAL_MODIFIED,(b)) |
443 |
#define dis_set_changes_structure(dis,b) \ |
444 |
dis_set_flagbit((dis),DIS_CHANGES_STRUCTURE,(b)) |
445 |
|
446 |
/* |
447 |
* incident = dis_incident(dis) |
448 |
* dis_set_incident(dis,incident) |
449 |
* uint32 incident; |
450 |
* struct dis_discrete *dis; |
451 |
* |
452 |
* Gets/sets the incident flag of the discrete variable. |
453 |
*/ |
454 |
|
455 |
extern struct dis_discrete **dis_BackendTokens_to_dis(slv_system_t, |
456 |
SlvBackendToken *, |
457 |
int32); |
458 |
/* |
459 |
* dislist = dis_BackendTokens_to_dis(sys,tokenlist,len); |
460 |
* slv_system_t sys; System to get indexing from. |
461 |
* SlvBackendToken tokenlist[]; Array of backend tokens. |
462 |
* int32 len; Tokenlist size. |
463 |
* struct dis_discrete *dislist[]; aka **dislist; |
464 |
* |
465 |
* dislist is NULL iff something is a miss, OTHERWISE it |
466 |
* contains len struct dis_discrete *. |
467 |
* The user should free the array dislist when done with it. |
468 |
* Some entries in the array dislist may be NULL if the tokenlist |
469 |
* contains a token which is not from the sys given. |
470 |
* tokenlist[i] <--> dislist[i]; |
471 |
* |
472 |
* The whole point of a slv_system_t is to isolate the client from |
473 |
* the compiler backend. Clients who find themselves in need of |
474 |
* this function are very much in need of rethinking as well. |
475 |
* For that reason, among others, this function is not heavily |
476 |
* optimized, it is however reasonable for 1-off jobs. |
477 |
* |
478 |
*/ |
479 |
|
480 |
#endif /* dis__already_included */ |