1 |
/* |
2 |
* Instance Checking Routines |
3 |
* by Tom Epperly |
4 |
* Created: 5/4/1990 |
5 |
* Version: $Revision: 1.25 $ |
6 |
* Version control file: $RCSfile: check.c,v $ |
7 |
* Date last modified: $Date: 1998/06/23 13:44:24 $ |
8 |
* Last modified by: $Author: ballan $ |
9 |
* |
10 |
* This file is part of the Ascend Language Interpreter. |
11 |
* |
12 |
* Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly |
13 |
* |
14 |
* The Ascend Language Interpreter is free software; you can redistribute |
15 |
* it and/or modify it under the terms of the GNU General Public License as |
16 |
* published by the Free Software Foundation; either version 2 of the |
17 |
* License, or (at your option) any later version. |
18 |
* |
19 |
* The Ascend Language Interpreter is distributed in hope that it will be |
20 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
22 |
* General Public License for more details. |
23 |
* |
24 |
* You should have received a copy of the GNU General Public License |
25 |
* along with the program; if not, write to the Free Software Foundation, |
26 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
27 |
* COPYING. |
28 |
* |
29 |
*/ |
30 |
|
31 |
#include <stdarg.h> |
32 |
#include <ascend/utilities/ascConfig.h> |
33 |
#include <ascend/utilities/ascMalloc.h> |
34 |
#include <ascend/utilities/ascPanic.h> |
35 |
#include <ascend/general/pool.h> |
36 |
#include <ascend/general/list.h> |
37 |
#include <ascend/general/dstring.h> |
38 |
|
39 |
#include "symtab.h" |
40 |
#include "slist.h" |
41 |
|
42 |
#include "functype.h" |
43 |
#include "expr_types.h" |
44 |
#include "stattypes.h" |
45 |
#include "statio.h" |
46 |
#include "module.h" |
47 |
#include "statement.h" |
48 |
#include "instance_types.h" /* for sizes */ |
49 |
#include "parentchild.h" |
50 |
#include "atomvalue.h" |
51 |
#include "instquery.h" |
52 |
#include "mathinst.h" |
53 |
#include "visitinst.h" |
54 |
#include "arrayinst.h" |
55 |
#include "instance_io.h" |
56 |
#include "instantiate.h" |
57 |
#include "find.h" |
58 |
#include "logical_relation.h" |
59 |
#include "rel_blackbox.h" |
60 |
#include "relation.h" |
61 |
#include "logrelation.h" |
62 |
#include "relation_util.h" |
63 |
#include "logrel_util.h" |
64 |
#include "exprio.h" |
65 |
#include "child.h" |
66 |
#include "type_desc.h" |
67 |
#include "library.h" |
68 |
#include "instance_types.h" |
69 |
#include "instance_name.h" |
70 |
#include "cmpfunc.h" |
71 |
#include "check.h" |
72 |
|
73 |
/* |
74 |
* If 1, statistics can take a real long time. |
75 |
*/ |
76 |
#define EXTRAPATHS 0 |
77 |
|
78 |
#define CLIQUE_WARNINGS 10000 |
79 |
#define NONZERO(x) ((x) ? (x) : 1) |
80 |
/* array of statements we don't want written in errors */ |
81 |
static int *g_suppressions = NULL; |
82 |
#define SUP(st) (g_suppressions[st]) |
83 |
|
84 |
/* |
85 |
* the following is a little batch of lists for catching unassigned |
86 |
* constants by type. |
87 |
* They should always be null outside the scope of an executing check |
88 |
* function since we have no operator for deallocating them. |
89 |
*/ |
90 |
static struct { |
91 |
struct gl_list_t *rlist; |
92 |
struct gl_list_t *blist; |
93 |
struct gl_list_t *ilist; |
94 |
struct gl_list_t *slist; |
95 |
} g_cons = {NULL,NULL,NULL,NULL}; |
96 |
|
97 |
static |
98 |
int CheckInstanceType(FILE *f, CONST struct Instance *i, |
99 |
CONST struct Instance *parent) |
100 |
{ |
101 |
switch(InstanceKind(i)) { |
102 |
case MODEL_INST: |
103 |
case REAL_ATOM_INST: |
104 |
case BOOLEAN_ATOM_INST: |
105 |
case INTEGER_ATOM_INST: |
106 |
case SET_ATOM_INST: |
107 |
case SYMBOL_ATOM_INST: |
108 |
|
109 |
case LREL_INST: |
110 |
case REL_INST: |
111 |
case WHEN_INST: |
112 |
case ARRAY_INT_INST: |
113 |
case ARRAY_ENUM_INST: |
114 |
|
115 |
case REAL_INST: |
116 |
case INTEGER_INST: |
117 |
case BOOLEAN_INST: |
118 |
case SET_INST: |
119 |
case SYMBOL_INST: |
120 |
|
121 |
case REAL_CONSTANT_INST: |
122 |
case INTEGER_CONSTANT_INST: |
123 |
case BOOLEAN_CONSTANT_INST: |
124 |
case SYMBOL_CONSTANT_INST: |
125 |
case DUMMY_INST: |
126 |
return 0; |
127 |
default: |
128 |
ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Instance is not of a valid type in CheckInstanceType"); |
129 |
FPRINTF(f,"A child of "); |
130 |
WriteInstanceName(f,parent,NULL); |
131 |
FPRINTF(f," is an incorrect data type. Please report this bug!"); |
132 |
return 1; |
133 |
} |
134 |
} |
135 |
|
136 |
/* |
137 |
* at present, the lists are unsorted because we want them in order found |
138 |
*/ |
139 |
static void AppendUnique(struct gl_list_t *l, CONST struct Instance *i) |
140 |
{ |
141 |
if (gl_ptr_search(l,i,0)==0) gl_append_ptr(l,(VOIDPTR)i); |
142 |
} |
143 |
|
144 |
/* |
145 |
*this function now records rather than reporting constants. |
146 |
* It's pretty gross. Blame the whiney users. |
147 |
*/ |
148 |
static |
149 |
void CheckUnassignedConstants(FILE *f, CONST struct Instance *i) |
150 |
{ |
151 |
unsigned long c,len; |
152 |
struct Instance *child; |
153 |
|
154 |
(void)f; /* stop gcc whine about unused parameter */ |
155 |
|
156 |
len = NumberChildren(i); |
157 |
for(c=1;c<=len;c++){ |
158 |
child = InstanceChild(i,c); |
159 |
if (child != NULL){ |
160 |
switch(InstanceKind(child)){ |
161 |
case REAL_CONSTANT_INST: |
162 |
if (IsWild(RealAtomDims(child)) || !AtomAssigned(child)) { |
163 |
AppendUnique(g_cons.rlist,child); |
164 |
} |
165 |
break; |
166 |
case INTEGER_CONSTANT_INST: |
167 |
if (!AtomAssigned(child)) { |
168 |
AppendUnique(g_cons.ilist,child); |
169 |
} |
170 |
break; |
171 |
case BOOLEAN_CONSTANT_INST: |
172 |
if (!AtomAssigned(child)) { |
173 |
AppendUnique(g_cons.blist,child); |
174 |
} |
175 |
break; |
176 |
case SYMBOL_CONSTANT_INST: |
177 |
if (!AtomAssigned(child)) { |
178 |
AppendUnique(g_cons.slist,child); |
179 |
} |
180 |
break; |
181 |
default: |
182 |
break; |
183 |
} |
184 |
} |
185 |
} |
186 |
} |
187 |
|
188 |
static |
189 |
void CheckIncompleteArray(FILE *f, CONST struct Instance *i) |
190 |
{ |
191 |
unsigned long c,len; |
192 |
struct Instance *child; |
193 |
struct TypeDescription *desc; |
194 |
len = NumberChildren(i); |
195 |
for(c=1;c<=len;c++){ |
196 |
child = InstanceChild(i,c); |
197 |
if (child != NULL){ |
198 |
switch(InstanceKind(child)){ |
199 |
case ARRAY_INT_INST: |
200 |
case ARRAY_ENUM_INST: |
201 |
desc = InstanceTypeDesc(child); |
202 |
if ((!GetArrayBaseIsRelation(desc)) && |
203 |
(!RectangleArrayExpanded(child)) && |
204 |
(!GetArrayBaseIsLogRel(desc)) ) { |
205 |
WriteInstanceName(f,child,NULL); |
206 |
FPRINTF(f,"[UNDEFINED]\n"); |
207 |
} |
208 |
default: |
209 |
break; |
210 |
} |
211 |
} |
212 |
} |
213 |
} |
214 |
|
215 |
static |
216 |
void CheckCompleteness(FILE *f, CONST struct Instance *i,int pass) |
217 |
{ |
218 |
unsigned long c, length; |
219 |
CONST struct BitList *blist; |
220 |
CONST struct TypeDescription *desc; |
221 |
CONST struct StatementList *slist; |
222 |
CONST struct Statement *stat; |
223 |
CONST struct gl_list_t *list; |
224 |
if (pass) { |
225 |
blist = InstanceBitList(i); |
226 |
if (blist!=NULL && !BitListEmpty(blist)){ |
227 |
ERROR_REPORTER_START_NOLINE(ASC_PROG_WARNING); |
228 |
WriteInstanceName(f,i,NULL); |
229 |
FPRINTF(f," has the following unexecuted statements.\n"); |
230 |
desc = InstanceTypeDesc(i); |
231 |
slist = GetStatementList(desc); |
232 |
list = GetList(slist); |
233 |
length = gl_length(list); |
234 |
assert(length == BLength(blist)); |
235 |
for(c=1;c<=length;c++){ |
236 |
if (ReadBit(blist,c-1)){ |
237 |
stat = (struct Statement *)gl_fetch(list,c); |
238 |
WSEMSPARSE(f,stat,"Unable to execute",g_suppressions); |
239 |
} |
240 |
} |
241 |
error_reporter_end_flush(); |
242 |
} |
243 |
} |
244 |
if (IncompleteArray(i)) { |
245 |
ERROR_REPORTER_START_NOLINE(ASC_PROG_WARNING); |
246 |
WriteInstanceName(f,i,NULL); |
247 |
FPRINTF(f," has the following incomplete arrays.\n"); |
248 |
error_reporter_end_flush(); |
249 |
CheckIncompleteArray(f,i); |
250 |
} |
251 |
CheckUnassignedConstants(f,i); |
252 |
} |
253 |
|
254 |
static |
255 |
int SuppressNullInstance(CONST struct TypeDescription *d) |
256 |
{ |
257 |
if (d==NULL) return 0; |
258 |
switch (GetBaseType(d)) { |
259 |
case relation_type: |
260 |
return SUP(REL); |
261 |
case logrel_type: |
262 |
return SUP(LOGREL); |
263 |
case when_type: |
264 |
return SUP(WHEN); |
265 |
case set_type: |
266 |
case real_type: |
267 |
case integer_type: |
268 |
case boolean_type: |
269 |
case symbol_type: |
270 |
case real_constant_type: |
271 |
case integer_constant_type: |
272 |
case boolean_constant_type: |
273 |
case symbol_constant_type: |
274 |
case dummy_type: |
275 |
case model_type: |
276 |
return (SUP(ISA) || SUP(ALIASES)); |
277 |
case patch_type: |
278 |
case array_type: |
279 |
return 0; |
280 |
} |
281 |
return 0; |
282 |
} |
283 |
|
284 |
static |
285 |
void RecursiveCheckInstance(FILE *f, CONST struct Instance *i, |
286 |
CONST struct Instance *parent,CONST int pass) |
287 |
{ |
288 |
CONST struct Instance *ptr; |
289 |
struct TypeDescription *desc; |
290 |
struct InstanceName name; |
291 |
unsigned long c=0; |
292 |
/* check for erroneous instance types */ |
293 |
if (CheckInstanceType(f,i,parent)) return; |
294 |
/* check for unexecuted statements */ |
295 |
CheckCompleteness(f,i,pass); |
296 |
/* check if i is connected to its parent */ |
297 |
if (parent != NULL && |
298 |
InstanceKind(i) != DUMMY_INST && |
299 |
SearchForParent(i,parent) == 0 |
300 |
){ |
301 |
WriteInstanceName(f,parent,NULL); |
302 |
FPRINTF(f," thinks that it is a parent of "); |
303 |
WriteInstanceName(f,i,NULL); |
304 |
FPRINTF(f,"\nbut "); |
305 |
WriteInstanceName(f,i,NULL); |
306 |
FPRINTF(f," doesn't have it in its parent list.\n"); |
307 |
} |
308 |
desc = InstanceTypeDesc(i); |
309 |
/* check the clique links */ |
310 |
ptr = NextCliqueMember(i); |
311 |
while(ptr != i){ |
312 |
ptr = NextCliqueMember(ptr); |
313 |
if (InstanceTypeDesc(ptr) != desc){ |
314 |
FPRINTF(f,"CLIQUE ERROR\n"); |
315 |
WriteInstanceName(f,i,NULL); |
316 |
FPRINTF(f," is of type %s and ", SCP(InstanceType(i))); |
317 |
WriteInstanceName(f,ptr,NULL); |
318 |
FPRINTF(f," is of type %s.\n",SCP(InstanceType(ptr))); |
319 |
} |
320 |
if ((++c % CLIQUE_WARNINGS)==0){ |
321 |
FPRINTF(f,"POSSIBLE ERROR\n"); |
322 |
WriteInstanceName(f,i,NULL); |
323 |
FPRINTF(f," is in a clique with %lu or more instances.\n",c); |
324 |
FPRINTF(f, |
325 |
"This is very large, so it may indicate an improper clique link.\n"); |
326 |
} |
327 |
} |
328 |
if (c > CLIQUE_WARNINGS){ |
329 |
FPRINTF(f,"Please ignore the clique warnings. "); |
330 |
FPRINTF(f,"The clique was properly terminated.\n"); |
331 |
} |
332 |
/* check i's parents */ |
333 |
for(c=NumberParents(i);c>=1;c--){ |
334 |
ptr = InstanceParent(i,c); |
335 |
if (!ChildIndex(ptr,i)){ |
336 |
WriteInstanceName(f,i,NULL); |
337 |
FPRINTF(f," thinks that "); |
338 |
WriteInstanceName(f,ptr,NULL); |
339 |
FPRINTF(f," is one of its parents.\n"); |
340 |
FPRINTF(f,"But "); |
341 |
WriteInstanceName(f,ptr,NULL); |
342 |
FPRINTF(f," doesn't think that "); |
343 |
WriteInstanceName(f,i,NULL); |
344 |
FPRINTF(f," is one of its children.\n"); |
345 |
} |
346 |
} |
347 |
/* check children */ |
348 |
for(c=NumberChildren(i);c>=1;c--){ |
349 |
ptr = InstanceChild(i,c); |
350 |
if (ptr) { |
351 |
RecursiveCheckInstance(f,ptr,i,pass); |
352 |
} else { |
353 |
if(!SuppressNullInstance(ChildRefines(i,c))) { |
354 |
ERROR_REPORTER_START_NOLINE(ASC_USER_WARNING); |
355 |
FPRINTF(f,"Instance '"); |
356 |
WriteInstanceName(f,i,NULL); |
357 |
FPRINTF(f,"' is missing part '"); |
358 |
name = ChildName(i,c); |
359 |
switch(InstanceNameType(name)){ |
360 |
case IntArrayIndex: |
361 |
FPRINTF(f,"[%ld]'",InstanceIntIndex(name)); |
362 |
break; |
363 |
case StrArrayIndex: |
364 |
FPRINTF(f,"[%s]'",SCP(InstanceStrIndex(name))); |
365 |
break; |
366 |
case StrName: |
367 |
FPRINTF(f,"%s'",SCP(InstanceNameStr(name))); |
368 |
break; |
369 |
default: |
370 |
FPRINTF(f,"<BAD NAME>"); |
371 |
break; |
372 |
} |
373 |
error_reporter_end_flush(); |
374 |
} |
375 |
} |
376 |
} |
377 |
} |
378 |
|
379 |
static void InitConsLists(void) |
380 |
{ |
381 |
g_cons.rlist = gl_create(100); |
382 |
g_cons.blist = gl_create(10); |
383 |
g_cons.slist = gl_create(20); |
384 |
g_cons.ilist = gl_create(20); |
385 |
} |
386 |
static void ClearConsLists(void) |
387 |
{ |
388 |
gl_destroy(g_cons.rlist); |
389 |
g_cons.rlist=NULL; |
390 |
gl_destroy(g_cons.blist); |
391 |
g_cons.blist=NULL; |
392 |
gl_destroy(g_cons.slist); |
393 |
g_cons.slist=NULL; |
394 |
gl_destroy(g_cons.ilist); |
395 |
g_cons.ilist=NULL; |
396 |
} |
397 |
|
398 |
static FILE *g_diagf; |
399 |
/* |
400 |
* global pointer so gliterate will have a file to print to in WriteConsLists |
401 |
*/ |
402 |
|
403 |
static |
404 |
void Diagnose(struct Instance *i) { |
405 |
if (InstanceKind(i)== REAL_CONSTANT_INST) { |
406 |
if (IsWild(RealAtomDims(i))) { |
407 |
FPRINTF(g_diagf,"Undimensioned "); |
408 |
} |
409 |
if (!AtomAssigned(i)) { |
410 |
FPRINTF(g_diagf,"Unassigned "); |
411 |
} |
412 |
FPRINTF(g_diagf,"real constant "); |
413 |
WriteInstanceName(g_diagf,i,NULL); |
414 |
FPRINTF(g_diagf,"\n"); |
415 |
} else { |
416 |
FPRINTF(g_diagf,"Unassigned constant "); |
417 |
WriteInstanceName(g_diagf,i,NULL); |
418 |
FPRINTF(g_diagf,"\n"); |
419 |
} |
420 |
} |
421 |
|
422 |
/* writes out the unassigned foo based on the flags given (pr,b,s,i) */ |
423 |
static void WriteConsLists(FILE *f, int pr, int pb, int pi, int ps) |
424 |
{ |
425 |
g_diagf = f; |
426 |
if (pr) gl_iterate(g_cons.rlist,(void (*)(VOIDPTR))Diagnose); |
427 |
if (pb) gl_iterate(g_cons.blist,(void (*)(VOIDPTR))Diagnose); |
428 |
if (pi) gl_iterate(g_cons.ilist,(void (*)(VOIDPTR))Diagnose); |
429 |
if (ps) gl_iterate(g_cons.slist,(void (*)(VOIDPTR))Diagnose); |
430 |
} |
431 |
|
432 |
void CheckInstanceLevel(FILE *f, CONST struct Instance *i,int pass) |
433 |
{ |
434 |
InitConsLists(); |
435 |
g_suppressions = GetStatioSuppressions(); |
436 |
if (pass<5) g_suppressions[ASGN]=1; |
437 |
if (pass<4) g_suppressions[WHEN]=1; |
438 |
if (pass<3) g_suppressions[LOGREL]=1; |
439 |
if (pass<2) g_suppressions[REL]=1; |
440 |
RecursiveCheckInstance(f,i,NULL,pass); |
441 |
DestroySuppressions(g_suppressions); |
442 |
WriteConsLists(f,1,1,1,1); |
443 |
ClearConsLists(); |
444 |
} |
445 |
|
446 |
void CheckInstanceStructure(FILE *f,CONST struct Instance *i) |
447 |
{ |
448 |
InitConsLists(); |
449 |
RecursiveCheckInstance(f,i,NULL,5); |
450 |
WriteConsLists(f,0,1,1,1); |
451 |
ClearConsLists(); |
452 |
} |
453 |
|
454 |
/*********************************************************************\ |
455 |
Implementation of the InstanceStatistics procedure. |
456 |
\*********************************************************************/ |
457 |
|
458 |
struct TypeCount { |
459 |
CONST char *name; /* the name of the type. !symchar */ |
460 |
enum inst_t basetype; /* kind of the instance */ |
461 |
unsigned count; /* the number present in the instance tree */ |
462 |
}; |
463 |
|
464 |
/*********************************************************************\ |
465 |
Global for counting number of each type present in the instance |
466 |
tree. |
467 |
\*********************************************************************/ |
468 |
static struct gl_list_t *g_type_count_list=NULL; |
469 |
/* a list of struct TypeCount */ |
470 |
|
471 |
/*********************************************************************\ |
472 |
Globals for counting instances |
473 |
\*********************************************************************/ |
474 |
static unsigned long g_num_complex_instances=0; |
475 |
/* number of models and atoms(excluding children of atoms) */ |
476 |
static unsigned long g_num_model_instances=0; |
477 |
/* number of models */ |
478 |
static unsigned long g_model_bytes=0; |
479 |
/* number of model bytes */ |
480 |
static unsigned long g_num_atom_instances=0; |
481 |
/* number of atoms (nonfundamental) */ |
482 |
static unsigned long g_atom_bytes=0; |
483 |
/* number of atom bytes */ |
484 |
static unsigned long g_tree_bytes=0; |
485 |
/* number of nonshared instance tree bytes, |
486 |
(ignore struct relation*, set_t*, dim_type *, char *)*/ |
487 |
static unsigned long g_num_constant_real=0; |
488 |
static unsigned long g_num_constant_bool=0; |
489 |
static unsigned long g_num_constant_int=0; |
490 |
static unsigned long g_num_constant_sym=0; |
491 |
static unsigned long g_num_constant_all=0; |
492 |
/* number of constants of various types */ |
493 |
static unsigned long g_num_atom_children=0; |
494 |
/* number of children of atoms or relations */ |
495 |
static unsigned long g_num_relation_instances=0; |
496 |
/* number of relations */ |
497 |
static struct gl_list_t *g_relation_guts = NULL; |
498 |
/* list of token relation guts */ |
499 |
static unsigned long g_num_array_instances=0; |
500 |
/* number of array instances */ |
501 |
static unsigned long g_num_unsel_instances=0; |
502 |
/* number of unselected instances */ |
503 |
/*********************************************************************\ |
504 |
The total number of instances should be equal to: |
505 |
g_num_complex_instances + g_num_atom_children + |
506 |
g_num_relation_instances + g_num_array_instances + |
507 |
g_num_constant_all |
508 |
\*********************************************************************/ |
509 |
|
510 |
/*********************************************************************\ |
511 |
Globals for counting number of parents |
512 |
All of the following are counted for models, atoms(excluding |
513 |
children of atoms), and arrays. Relations and children of atoms |
514 |
aren't counted because they can realistically only have one |
515 |
parent. |
516 |
Parents of constants aren't counted yet. need more vars. |
517 |
\*********************************************************************/ |
518 |
static unsigned g_minimum_parents=0; |
519 |
static unsigned g_maximum_parents=0; |
520 |
static unsigned g_extra_paths=0; |
521 |
static unsigned g_extra_parents=0; |
522 |
static unsigned g_extra_parents_sum=0; |
523 |
static unsigned g_total_parents=0; |
524 |
|
525 |
/*********************************************************************\ |
526 |
Globals for counting numbers of children |
527 |
The following are counted for models, atoms(excluding children |
528 |
of atoms), arrays, and relations. These globals are used to |
529 |
report the minimum, maximum, and average number of children. |
530 |
\*********************************************************************/ |
531 |
static unsigned g_minimum_children=0; |
532 |
static unsigned g_maximum_children=0; |
533 |
static unsigned g_total_children=0; |
534 |
|
535 |
/*********************************************************************\ |
536 |
Globals for counting the number of cliques |
537 |
This global is used to estimate the number and min, max, and average |
538 |
size of the cliques in this tree. |
539 |
\*********************************************************************/ |
540 |
static struct gl_list_t *g_clique_list=NULL; /* of struct Instance * */ |
541 |
|
542 |
/*********************************************************************\ |
543 |
Globals for estimating the number of relations in which each real appears. |
544 |
These are used to estimate the min, max, and average size of the relation |
545 |
list. |
546 |
\*********************************************************************/ |
547 |
static unsigned g_total_variables=0; |
548 |
static unsigned g_minimum_relations=0; |
549 |
static unsigned g_maximum_relations=0; |
550 |
static unsigned g_total_relations=0; |
551 |
|
552 |
|
553 |
/*********************************************************************\ |
554 |
Globals for counting the number of terms in a relation. |
555 |
A count is also made of all the reals in relations. This is |
556 |
to get an estimate of how expensive the relations are. |
557 |
\*********************************************************************/ |
558 |
static unsigned long g_total_reals_in_rels=0; |
559 |
static unsigned long g_relation_terms=0; |
560 |
|
561 |
/*********************************************************************\ |
562 |
Globals for calculating the minimum, maximum, and average number |
563 |
of array elements per array. |
564 |
\*********************************************************************/ |
565 |
static unsigned g_total_array_children=0; |
566 |
|
567 |
/*********************************************************************\ |
568 |
\*********************************************************************/ |
569 |
|
570 |
long g_token_counts[NUM_EXPR_ENUMS]; |
571 |
|
572 |
/* this sorts by inst_t with a secondary alpha sort */ |
573 |
static |
574 |
int CompareTypeCounts(CONST struct TypeCount *one, |
575 |
CONST struct TypeCount *two) |
576 |
{ |
577 |
if (one == two) return 0; |
578 |
if (!one) return 1; /* NULLs float to top */ |
579 |
if (!two) return -1; /* NULLs float to top */ |
580 |
|
581 |
if (one->basetype==two->basetype) { |
582 |
return strcmp(one->name,two->name); |
583 |
} else { |
584 |
return (one->basetype < two->basetype) ? -1 : 1; |
585 |
} |
586 |
} |
587 |
|
588 |
static unsigned CliqueSize(CONST struct Instance *i) |
589 |
{ |
590 |
unsigned result = 0; |
591 |
CONST struct Instance *ptr; |
592 |
ptr = i; |
593 |
do { |
594 |
result++; |
595 |
ptr = NextCliqueMember(ptr); |
596 |
} while(ptr != i); |
597 |
return result; |
598 |
} |
599 |
|
600 |
static unsigned MinimumCliqueSize(struct gl_list_t *l) |
601 |
{ |
602 |
unsigned result = UINT_MAX,size; |
603 |
unsigned long c, length; |
604 |
CONST struct Instance *i; |
605 |
for(c=1, length = gl_length(l);c <= length;c++){ |
606 |
i = gl_fetch(l,c); |
607 |
size = CliqueSize(i); |
608 |
if (size < result) result = size; |
609 |
} |
610 |
return length ? result : 0; |
611 |
} |
612 |
|
613 |
static unsigned MaximumCliqueSize(struct gl_list_t *l) |
614 |
{ |
615 |
unsigned result = 0,size; |
616 |
unsigned long c, length; |
617 |
CONST struct Instance *i; |
618 |
for(c=1, length = gl_length(l);c <= length;c++){ |
619 |
i = gl_fetch(l,c); |
620 |
size = CliqueSize(i); |
621 |
if (size > result) result = size; |
622 |
} |
623 |
return length ? result : 0; |
624 |
} |
625 |
|
626 |
static double AverageCliqueSize(struct gl_list_t *l) |
627 |
{ |
628 |
unsigned long total_clique_members=0; |
629 |
unsigned long c, length; |
630 |
CONST struct Instance *i; |
631 |
for(c=1, length = gl_length(l);c <= length;c++){ |
632 |
i = gl_fetch(l,c); |
633 |
total_clique_members += CliqueSize(i); |
634 |
} |
635 |
return length ? (double)total_clique_members/(double)length : 1; |
636 |
} |
637 |
|
638 |
static void IncrementTypeCount(CONST struct Instance *i) |
639 |
{ |
640 |
unsigned long tindex; |
641 |
struct TypeCount rec,*ptr; |
642 |
symchar *name; |
643 |
|
644 |
name = InstanceType(i); |
645 |
if (*SCP(name)) { |
646 |
rec.name = SCP(name); |
647 |
} else { |
648 |
rec.name = "UNNAMED ARRAY NODE"; |
649 |
} |
650 |
rec.basetype = InstanceKind(i); |
651 |
tindex = gl_search(g_type_count_list,&rec, (CmpFunc)CompareTypeCounts); |
652 |
if (tindex != 0){ |
653 |
/* increment the current count by one */ |
654 |
ptr = (struct TypeCount *)gl_fetch(g_type_count_list,tindex); |
655 |
ptr->count++; |
656 |
} else{ /* add a new type count to the list */ |
657 |
ptr = ASC_NEW(struct TypeCount); |
658 |
ptr->name = rec.name; |
659 |
ptr->count = 1; |
660 |
ptr->basetype = rec.basetype; |
661 |
gl_insert_sorted(g_type_count_list,ptr, (CmpFunc)CompareTypeCounts); |
662 |
} |
663 |
} |
664 |
|
665 |
static int InClique(CONST struct Instance *test, |
666 |
CONST struct Instance *clique) |
667 |
/* return true iff test is in clique */ |
668 |
{ |
669 |
CONST struct Instance *ptr; |
670 |
ptr = clique; |
671 |
do{ |
672 |
if (ptr == test) return 1; |
673 |
ptr = NextCliqueMember(ptr); |
674 |
} while(ptr != clique); |
675 |
return 0; |
676 |
} |
677 |
|
678 |
static void CheckCliqueList(CONST struct Instance *i) |
679 |
{ |
680 |
unsigned c, length; |
681 |
CONST struct Instance *clique; |
682 |
for(c=1, length = gl_length(g_clique_list); c <= length;c++){ |
683 |
clique = gl_fetch(g_clique_list,c); |
684 |
if (InClique(i,clique)) return; |
685 |
} |
686 |
/* add to clique list */ |
687 |
gl_append_ptr(g_clique_list,(VOIDPTR)i); |
688 |
} |
689 |
|
690 |
static |
691 |
void AccParents(CONST struct Instance *i) |
692 |
{ |
693 |
unsigned long temp; |
694 |
#if EXTRAPATHS |
695 |
unsigned long c; |
696 |
struct gl_list_t *plist; |
697 |
#endif |
698 |
temp = NumberParents(i); |
699 |
if (temp < g_minimum_parents) { |
700 |
g_minimum_parents = temp; |
701 |
} |
702 |
if (temp > g_maximum_parents) { |
703 |
g_maximum_parents = temp; |
704 |
} |
705 |
if (temp > 1 && !InstanceUniversal(i)) { |
706 |
g_extra_parents++; |
707 |
g_extra_parents_sum += (temp-1); |
708 |
#if EXTRAPATHS |
709 |
plist = AllPaths(i); |
710 |
g_extra_paths += gl_length(plist); |
711 |
for(c=1;c <= gl_length(plist);c++){ |
712 |
gl_free_and_destroy(gl_fetch(plist,c)); |
713 |
} |
714 |
gl_destroy(plist); |
715 |
#endif /* extrapaths */ |
716 |
} |
717 |
g_total_parents += temp; |
718 |
} |
719 |
|
720 |
static |
721 |
void AccStatistics(CONST struct Instance *i) |
722 |
{ |
723 |
unsigned long temp; |
724 |
CONST struct relation *rel; |
725 |
enum Expr_enum reltype; |
726 |
|
727 |
IncrementTypeCount(i); |
728 |
if (NextCliqueMember(i) != i) |
729 |
CheckCliqueList(i); |
730 |
switch(InstanceKind(i)){ |
731 |
case MODEL_INST: |
732 |
g_num_complex_instances++; |
733 |
g_num_model_instances++; |
734 |
AccParents(i); |
735 |
temp = NumberChildren(i); |
736 |
if (temp < g_minimum_children) g_minimum_children = temp; |
737 |
if (temp > g_maximum_children) g_maximum_children = temp; |
738 |
g_total_children += temp; |
739 |
g_model_bytes += |
740 |
(sizeof(struct ModelInstance) + temp*sizeof(struct Instance *)); |
741 |
break; |
742 |
case REAL_ATOM_INST: |
743 |
g_num_complex_instances++; |
744 |
g_num_atom_instances++; |
745 |
g_atom_bytes += GetByteSize(InstanceTypeDesc(i)); |
746 |
AccParents(i); |
747 |
temp = NumberChildren(i); |
748 |
if (temp < g_minimum_children) g_minimum_children = temp; |
749 |
if (temp > g_maximum_children) g_maximum_children = temp; |
750 |
g_total_children += temp; |
751 |
g_total_variables++; |
752 |
temp = RelationsCount(i); |
753 |
if (temp < g_minimum_relations) g_minimum_relations = temp; |
754 |
if (temp > g_maximum_relations) g_maximum_relations = temp; |
755 |
g_total_relations += temp; |
756 |
break; |
757 |
case BOOLEAN_ATOM_INST: |
758 |
g_num_complex_instances++; |
759 |
g_num_atom_instances++; |
760 |
g_atom_bytes += GetByteSize(InstanceTypeDesc(i)); |
761 |
AccParents(i); |
762 |
temp = NumberChildren(i); |
763 |
if (temp < g_minimum_children) g_minimum_children = temp; |
764 |
if (temp > g_maximum_children) g_maximum_children = temp; |
765 |
g_total_children += temp; |
766 |
break; |
767 |
case INTEGER_ATOM_INST: |
768 |
g_num_complex_instances++; |
769 |
g_num_atom_instances++; |
770 |
g_atom_bytes += GetByteSize(InstanceTypeDesc(i)); |
771 |
AccParents(i); |
772 |
temp = NumberChildren(i); |
773 |
if (temp < g_minimum_children) g_minimum_children = temp; |
774 |
if (temp > g_maximum_children) g_maximum_children = temp; |
775 |
g_total_children += temp; |
776 |
break; |
777 |
case SET_ATOM_INST: |
778 |
g_num_complex_instances++; |
779 |
g_num_atom_instances++; |
780 |
g_atom_bytes += GetByteSize(InstanceTypeDesc(i)); |
781 |
AccParents(i); |
782 |
temp = NumberChildren(i); |
783 |
if (temp < g_minimum_children) g_minimum_children = temp; |
784 |
if (temp > g_maximum_children) g_maximum_children = temp; |
785 |
g_total_children += temp; |
786 |
break; |
787 |
case SYMBOL_ATOM_INST: |
788 |
g_num_complex_instances++; |
789 |
g_num_atom_instances++; |
790 |
g_atom_bytes += GetByteSize(InstanceTypeDesc(i)); |
791 |
AccParents(i); |
792 |
temp = NumberChildren(i); |
793 |
if (temp < g_minimum_children) g_minimum_children = temp; |
794 |
if (temp > g_maximum_children) g_maximum_children = temp; |
795 |
g_total_children += temp; |
796 |
break; |
797 |
case REL_INST: |
798 |
g_num_relation_instances++; |
799 |
temp = NumberChildren(i); |
800 |
if (temp < g_minimum_children) g_minimum_children = temp; |
801 |
if (temp > g_maximum_children) g_maximum_children = temp; |
802 |
g_total_children += temp; |
803 |
/* count terms */ |
804 |
rel = GetInstanceRelation(i,&reltype); |
805 |
if (rel&&(reltype==e_token)) { |
806 |
g_relation_terms += RelationLength(rel,0); |
807 |
g_relation_terms += RelationLength(rel,1); |
808 |
g_total_reals_in_rels += NumberVariables(rel); |
809 |
} |
810 |
break; |
811 |
case ARRAY_INT_INST: |
812 |
g_num_array_instances++; |
813 |
AccParents(i); |
814 |
temp = NumberChildren(i); |
815 |
if (temp < g_minimum_children) g_minimum_children = temp; |
816 |
if (temp > g_maximum_children) g_maximum_children = temp; |
817 |
g_total_children += temp; |
818 |
g_total_array_children += temp; |
819 |
break; |
820 |
case ARRAY_ENUM_INST: |
821 |
g_num_array_instances++; |
822 |
AccParents(i); |
823 |
temp = NumberChildren(i); |
824 |
if (temp < g_minimum_children) g_minimum_children = temp; |
825 |
if (temp > g_maximum_children) g_maximum_children = temp; |
826 |
g_total_children += temp; |
827 |
g_total_array_children += temp; |
828 |
break; |
829 |
case REAL_CONSTANT_INST: |
830 |
g_num_constant_real++; |
831 |
g_num_constant_all++; |
832 |
break; |
833 |
case INTEGER_CONSTANT_INST: |
834 |
g_num_constant_int++; |
835 |
g_num_constant_all++; |
836 |
break; |
837 |
case BOOLEAN_CONSTANT_INST: |
838 |
g_num_constant_bool++; |
839 |
g_num_constant_all++; |
840 |
break; |
841 |
case SYMBOL_CONSTANT_INST: |
842 |
g_num_constant_sym++; |
843 |
g_num_constant_all++; |
844 |
break; |
845 |
case REAL_INST: |
846 |
g_num_atom_children++; |
847 |
break; |
848 |
case INTEGER_INST: |
849 |
g_num_atom_children++; |
850 |
break; |
851 |
case BOOLEAN_INST: |
852 |
g_num_atom_children++; |
853 |
break; |
854 |
case SET_INST: |
855 |
g_num_atom_children++; |
856 |
break; |
857 |
case SYMBOL_INST: |
858 |
g_num_atom_children++; |
859 |
break; |
860 |
case DUMMY_INST: |
861 |
g_num_unsel_instances++; |
862 |
break; |
863 |
case WHEN_INST: |
864 |
case LREL_INST: |
865 |
/* vicente we should be collecting info here */ |
866 |
break; |
867 |
default: |
868 |
ASC_PANIC("Invalid arguments to AccStatistics.\n"); |
869 |
break; |
870 |
} |
871 |
} |
872 |
|
873 |
static void AccBytes(CONST struct Instance *i) |
874 |
{ |
875 |
g_tree_bytes += InstanceSize(i); |
876 |
} |
877 |
|
878 |
/* |
879 |
* Does not account properly for shared external rels. |
880 |
*/ |
881 |
static void AccTokenStatistics(CONST struct Instance *i) |
882 |
{ |
883 |
unsigned long p,len,llen,rlen; |
884 |
CONST struct relation *rel; |
885 |
enum Expr_enum t; |
886 |
CONST union RelationTermUnion *rside; |
887 |
switch(InstanceKind(i)){ |
888 |
case REL_INST: |
889 |
g_num_relation_instances++; |
890 |
/* count terms */ |
891 |
rel = GetInstanceRelation(i,&t); |
892 |
if (rel&&(t==e_token)) { |
893 |
g_total_reals_in_rels += NumberVariables(rel); |
894 |
|
895 |
/* count all the terms that would be evaluated */ |
896 |
rside = PostFix_RhsSide(rel); |
897 |
rlen = RelationLength(rel,0); |
898 |
g_relation_terms += rlen; |
899 |
rside = PostFix_LhsSide(rel); |
900 |
llen = RelationLength(rel,1); |
901 |
g_relation_terms += llen; |
902 |
/* if not on list, add and count tokens in fine */ |
903 |
if ( !gl_search(g_relation_guts,rside,(CmpFunc)CmpPtrs) ) { |
904 |
gl_append_ptr(g_relation_guts,(VOIDPTR)rside); |
905 |
len = llen; |
906 |
rside = PostFix_LhsSide(rel); |
907 |
for (p=0; p<len; p++) { |
908 |
t = RelationTermType(RelationSideTerm(rside,p)); |
909 |
g_token_counts[t]++; |
910 |
} |
911 |
len = rlen; |
912 |
rside = PostFix_RhsSide(rel); |
913 |
for (p=0; p<len; p++) { |
914 |
t = RelationTermType(RelationSideTerm(rside,p)); |
915 |
g_token_counts[t]++; |
916 |
} |
917 |
} |
918 |
} |
919 |
break; |
920 |
case MODEL_INST: |
921 |
case REAL_ATOM_INST: |
922 |
case BOOLEAN_ATOM_INST: |
923 |
case INTEGER_ATOM_INST: |
924 |
case SET_ATOM_INST: |
925 |
case SYMBOL_ATOM_INST: |
926 |
case ARRAY_INT_INST: |
927 |
case ARRAY_ENUM_INST: |
928 |
case REAL_CONSTANT_INST: |
929 |
case INTEGER_CONSTANT_INST: |
930 |
case BOOLEAN_CONSTANT_INST: |
931 |
case SYMBOL_CONSTANT_INST: |
932 |
case REAL_INST: |
933 |
case INTEGER_INST: |
934 |
case BOOLEAN_INST: |
935 |
case SET_INST: |
936 |
case SYMBOL_INST: |
937 |
case DUMMY_INST: |
938 |
break; |
939 |
default: |
940 |
ASC_PANIC("Invalid arguments to AccTokenStatistics.\n"); |
941 |
break; |
942 |
} |
943 |
} |
944 |
|
945 |
void InstanceTokenStatistics(FILE *f, CONST struct Instance *i) |
946 |
{ |
947 |
int j; |
948 |
if (i==NULL) return; |
949 |
g_relation_guts = gl_create(10000); |
950 |
for (j=0; j < NUM_EXPR_ENUMS; j++) g_token_counts[j] = 0; |
951 |
g_num_relation_instances = g_relation_terms = g_total_reals_in_rels = 0; |
952 |
SilentVisitInstanceTree((struct Instance *)i, |
953 |
(void (*)(struct Instance *))AccTokenStatistics,1,0); |
954 |
FPRINTF(f,"Token relation statistics\n===================\n"); |
955 |
FPRINTF(f,"Total number of relation instances: %lu\n", |
956 |
g_num_relation_instances); |
957 |
FPRINTF(f,"Total number of 'unique' relations: %lu\n", |
958 |
gl_length(g_relation_guts)); |
959 |
FPRINTF(f,"Total number of relation terms: %lu\n", g_relation_terms); |
960 |
FPRINTF(f,"Total number of reals in relation: %lu\n", |
961 |
g_total_reals_in_rels); |
962 |
FPRINTF(f,"Number\t\tType of term:\n"); |
963 |
g_relation_terms = 0; |
964 |
for (j=0; j < NUM_EXPR_ENUMS; j++) { |
965 |
if (g_token_counts[j]) { |
966 |
FPRINTF(f,"%lu\t\t%s\n", g_token_counts[j], ExprEnumName(j)); |
967 |
g_relation_terms += g_token_counts[j]; |
968 |
} |
969 |
} |
970 |
FPRINTF(f,"Total compiled tokens:\t%lu\n",g_relation_terms); |
971 |
FPRINTF(f,"===================\n"); |
972 |
|
973 |
gl_destroy(g_relation_guts); |
974 |
g_relation_guts = NULL; |
975 |
} |
976 |
|
977 |
void InstanceStatistics(FILE *f, CONST struct Instance *i) |
978 |
{ |
979 |
struct TypeCount *count; |
980 |
unsigned long c, length; |
981 |
/* |
982 |
* initialize global variables |
983 |
*/ |
984 |
g_type_count_list = gl_create(50L); |
985 |
g_clique_list = gl_create(300L); |
986 |
g_num_complex_instances = g_num_atom_children = |
987 |
g_num_relation_instances = g_num_array_instances = |
988 |
g_num_unsel_instances = g_maximum_parents = g_total_parents = |
989 |
g_maximum_children = g_total_children = g_total_variables = |
990 |
g_maximum_relations = g_total_relations = g_total_array_children = |
991 |
g_relation_terms = g_total_reals_in_rels = |
992 |
g_num_constant_sym = g_num_constant_real = |
993 |
g_num_constant_bool = g_num_constant_int = |
994 |
g_num_constant_all = g_num_model_instances = |
995 |
g_num_atom_instances = g_model_bytes = g_atom_bytes = |
996 |
g_tree_bytes = g_extra_parents = g_extra_parents_sum = |
997 |
g_extra_paths = |
998 |
0; |
999 |
g_minimum_parents = g_minimum_children = g_minimum_relations = UINT_MAX; |
1000 |
|
1001 |
VisitInstanceTree((struct Instance *)i, |
1002 |
(void (*)(struct Instance *))AccStatistics,1,1); |
1003 |
SilentVisitInstanceTree((struct Instance *)i, |
1004 |
(void (*)(struct Instance *))AccBytes,0,0); |
1005 |
|
1006 |
FPRINTF(f,"General Instance Tree Numbers\n=============================\n"); |
1007 |
FPRINTF(f,"Number of models and complex atoms: %lu\n", |
1008 |
g_num_complex_instances); |
1009 |
FPRINTF(f,"Number of models: %lu (%lu bytes)\n", |
1010 |
g_num_model_instances,g_model_bytes); |
1011 |
FPRINTF(f,"Number of atoms: %lu (%lu bytes)\n", |
1012 |
g_num_atom_instances,g_atom_bytes); |
1013 |
FPRINTF(f,"Number of atom children instances: %lu\n", |
1014 |
g_num_atom_children); |
1015 |
FPRINTF(f,"Number of constant instances: %lu\n", |
1016 |
g_num_constant_all); |
1017 |
if (FindRelationType() !=NULL) { |
1018 |
length = GetByteSize(FindRelationType()); |
1019 |
} else { |
1020 |
length = 0; |
1021 |
} |
1022 |
FPRINTF(f,"Number of relation heads: %lu (%lu bytes)\n", |
1023 |
g_num_relation_instances, length*g_num_relation_instances); |
1024 |
FPRINTF(f,"Number of array instances: %lu\n", |
1025 |
g_num_array_instances); |
1026 |
FPRINTF(f,"Number of unselected instances: %lu\n", |
1027 |
g_num_unsel_instances); |
1028 |
FPRINTF(f,"TOTAL INSTANCES: %lu\n", |
1029 |
g_num_complex_instances + g_num_atom_children + |
1030 |
g_num_relation_instances + g_num_relation_instances + |
1031 |
g_num_array_instances + g_num_constant_all); |
1032 |
FPRINTF(f,"TOTAL BYTES (neglecting shared internals): %lu\n", g_tree_bytes); |
1033 |
|
1034 |
FPRINTF(f,"Instance number by type\n=======================\n"); |
1035 |
length = gl_length(g_type_count_list); |
1036 |
for(c=1; c <= length;c++){ |
1037 |
count = gl_fetch(g_type_count_list,c); |
1038 |
if (count){ |
1039 |
FPRINTF(f,"%-40s %lu\n",count->name,(unsigned long)count->count); |
1040 |
} else { |
1041 |
FPRINTF(f,"NULL pointer in type count list\n"); |
1042 |
} |
1043 |
} |
1044 |
FPRINTF(f,"Parental statistics\n===================\n"); |
1045 |
FPRINTF(f,"Minimum number of parents: %u\n",g_minimum_parents); |
1046 |
FPRINTF(f,"Maximum number of parents: %u\n",g_maximum_parents); |
1047 |
FPRINTF(f,"Average number of parents: %g\n", |
1048 |
(double)g_total_parents/ |
1049 |
(double)NONZERO(g_num_complex_instances + g_num_array_instances)); |
1050 |
FPRINTF(f,"Instances with nP > 1: %u\n",g_extra_parents); |
1051 |
FPRINTF(f,"Total extra parents: %u\n",g_extra_parents_sum); |
1052 |
#if EXTRAPATHS |
1053 |
FPRINTF(f,"Total extra paths: %u\n",g_extra_paths); |
1054 |
#endif /* extrapaths */ |
1055 |
|
1056 |
FPRINTF(f,"Children statistics\n===================\n"); |
1057 |
FPRINTF(f,"Minimum number of children: %u\n",g_minimum_children); |
1058 |
FPRINTF(f,"Maximum number of children: %u\n",g_maximum_children); |
1059 |
FPRINTF(f,"Average number of children: %g\n", |
1060 |
(double)g_total_children/ |
1061 |
(double)NONZERO(g_num_complex_instances + g_num_array_instances + |
1062 |
g_num_relation_instances)); |
1063 |
|
1064 |
FPRINTF(f,"Clique statistics\n=================\n"); |
1065 |
FPRINTF(f,"Number of cliques: %lu\n",gl_length(g_clique_list)); |
1066 |
FPRINTF(f,"Minimum clique size: %u\n",MinimumCliqueSize(g_clique_list)); |
1067 |
FPRINTF(f,"Maximum clique size: %u\n",MaximumCliqueSize(g_clique_list)); |
1068 |
FPRINTF(f,"Average clique size: %g\n",AverageCliqueSize(g_clique_list)); |
1069 |
|
1070 |
FPRINTF(f,"Variable statistics\n===================\n"); |
1071 |
FPRINTF(f,"Number of complex reals: %u\n",g_total_variables); |
1072 |
FPRINTF(f,"Minimum number of relations per real: %u\n", |
1073 |
g_minimum_relations); |
1074 |
FPRINTF(f,"Maximum number of relations per real: %u\n", |
1075 |
g_maximum_relations); |
1076 |
FPRINTF(f,"Average number of relations per real: %g\n", |
1077 |
(double)g_total_relations/(double)NONZERO(g_total_variables)); |
1078 |
|
1079 |
FPRINTF(f,"Constant statistics\n===================\n"); |
1080 |
FPRINTF(f,"Number of constant reals:\t %lu\n",g_num_constant_real); |
1081 |
FPRINTF(f,"Number of constant booleans:\t %lu\n",g_num_constant_bool); |
1082 |
FPRINTF(f,"Number of constant integers:\t %lu\n",g_num_constant_int); |
1083 |
FPRINTF(f,"Number of constant symbols:\t %lu\n",g_num_constant_sym); |
1084 |
|
1085 |
FPRINTF(f,"Relation statistics\n===================\n"); |
1086 |
FPRINTF(f,"Total number of relation terms: %lu\n", g_relation_terms); |
1087 |
FPRINTF(f,"Total number of reals in relation: %lu\n", |
1088 |
g_total_reals_in_rels); |
1089 |
|
1090 |
FPRINTF(f,"Array statistics\n================\n"); |
1091 |
FPRINTF(f,"Average children per array node: %g\n", |
1092 |
(double)g_total_array_children / |
1093 |
(double)NONZERO(g_num_array_instances)); |
1094 |
|
1095 |
gl_destroy(g_clique_list); |
1096 |
gl_free_and_destroy(g_type_count_list); |
1097 |
} |