source: vis_dev/glu-2.3/src/cmuBdd/bddsize.c @ 104

Last change on this file since 104 was 13, checked in by cecile, 13 years ago

library glu 2.3

File size: 8.1 KB
Line 
1/* BDD size and profile routines */
2
3
4#include "bddint.h"
5
6
7static
8void
9bdd_mark_bdd(bdd f)
10{
11  int curr_marking, this_marking;
12
13  BDD_SETUP(f);
14  curr_marking=BDD_MARK(f);
15  this_marking=(1 << TAG(f));
16  if (curr_marking & this_marking)
17    return;
18  BDD_MARK(f)=curr_marking | this_marking;
19  if (BDD_IS_CONST(f))
20    return;
21  bdd_mark_bdd(BDD_THEN(f));
22  bdd_mark_bdd(BDD_ELSE(f));
23}
24
25
26static
27int
28bdd_count_no_nodes(bdd f)
29{
30  BDD_SETUP(f);
31  return (BDD_MARK(f) > 0);
32}
33
34
35static
36int
37bdd_count_nodes(bdd f)
38{
39  int mark;
40
41  BDD_SETUP(f);
42  mark=BDD_MARK(f);
43  return (((mark & 0x1) != 0)+((mark & 0x2) != 0));
44}
45
46
47static
48int (*(counting_fns[]))(bdd)=
49{
50  bdd_count_no_nodes,
51  bdd_count_nodes,
52};
53
54
55static
56long
57cmu_bdd_size_step(bdd f, int (*count_fn)(bdd))
58{
59  long result;
60
61  BDD_SETUP(f);
62  if (!BDD_MARK(f))
63    return (0l);
64  result=(*count_fn)(f);
65  if (!BDD_IS_CONST(f))
66    result+=cmu_bdd_size_step(BDD_THEN(f), count_fn)+cmu_bdd_size_step(BDD_ELSE(f), count_fn);
67  BDD_MARK(f)=0;
68  return (result);
69}
70
71
72/* cmu_bdd_size(bddm, f, negout) returns the number of nodes in f when */
73/* negout is nonzero.  If negout is zero, we pretend that the BDDs */
74/* don't have negative-output pointers. */
75
76long
77cmu_bdd_size(cmu_bdd_manager bddm, bdd f, int negout)
78{
79  bdd g;
80
81  if (bdd_check_arguments(1, f))
82    {
83      g=BDD_ONE(bddm);
84      {
85        BDD_SETUP(g);
86        BDD_MARK(g)=0;
87      }
88      bdd_mark_bdd(f);
89      return (cmu_bdd_size_step(f, counting_fns[!negout]));
90    }
91  return (0l);
92}
93
94
95/* cmu_bdd_size_multiple is like cmu_bdd_size, but takes a null-terminated */
96/* array of BDDs and accounts for sharing of nodes. */
97
98long
99cmu_bdd_size_multiple(cmu_bdd_manager bddm, bdd* fs, int negout)
100{
101  long size;
102  bdd *f;
103  bdd g;
104
105  bdd_check_array(fs);
106  g=BDD_ONE(bddm);
107  {
108    BDD_SETUP(g);
109    BDD_MARK(g)=0;
110  }
111  for (f=fs; *f; ++f)
112    bdd_mark_bdd(*f);
113  size=0l;
114  for (f=fs; *f; ++f)
115    size+=cmu_bdd_size_step(*f, counting_fns[!negout]);
116  return (size);
117}
118
119
120static
121void
122cmu_bdd_profile_step(cmu_bdd_manager bddm, bdd f, long *level_counts, int (*count_fn)(bdd))
123{
124  BDD_SETUP(f);
125  if (!BDD_MARK(f))
126    return;
127  if (BDD_IS_CONST(f))
128    level_counts[bddm->vars]+=(*count_fn)(f);
129  else
130    {
131      level_counts[BDD_INDEX(bddm, f)]+=(*count_fn)(f);
132      cmu_bdd_profile_step(bddm, BDD_THEN(f), level_counts, count_fn);
133      cmu_bdd_profile_step(bddm, BDD_ELSE(f), level_counts, count_fn);
134    }
135  BDD_MARK(f)=0;
136}
137
138
139/* cmu_bdd_profile(bddm, f, level_counts, negout) returns a "node profile" */
140/* of f, i.e., the number of nodes at each level in f.  negout is as in */
141/* cmu_bdd_size.  level_counts should be an array of size cmu_bdd_vars(bddm)+1 */
142/* to hold the profile. */
143
144void
145cmu_bdd_profile(cmu_bdd_manager bddm, bdd f, long *level_counts, int negout)
146{
147  bdd_index_type i;
148  bdd g;
149
150  for (i=0; i <= bddm->vars; ++i)
151    level_counts[i]=0l;
152  if (bdd_check_arguments(1, f))
153    {
154      g=BDD_ONE(bddm);
155      {
156        BDD_SETUP(g);
157        BDD_MARK(g)=0;
158      }
159      bdd_mark_bdd(f);
160      cmu_bdd_profile_step(bddm, f, level_counts, counting_fns[!negout]);
161    }
162}
163
164
165/* cmu_bdd_profile_multiple is to cmu_bdd_profile as cmu_bdd_size_multiple is to */
166/* cmu_bdd_size. */
167
168void
169cmu_bdd_profile_multiple(cmu_bdd_manager bddm, bdd *fs, long *level_counts, int negout)
170{
171  bdd_index_type i;
172  bdd *f;
173  bdd g;
174
175  bdd_check_array(fs);
176  for (i=0; i <= bddm->vars; ++i)
177    level_counts[i]=0l;
178  g=BDD_ONE(bddm);
179  {
180    BDD_SETUP(g);
181    BDD_MARK(g)=0;
182  }
183  for (f=fs; *f; ++f)
184    bdd_mark_bdd(*f);
185  for (f=fs; *f; ++f)
186    cmu_bdd_profile_step(bddm, *f, level_counts, counting_fns[!negout]);
187}
188
189
190static
191void
192bdd_highest_ref_step(cmu_bdd_manager bddm, bdd f, hash_table h)
193{
194  long *hash_result;
195  long f_index;
196
197  BDD_SETUP(f);
198  if (BDD_IS_CONST(f))
199    return;
200  f_index=BDD_INDEX(bddm, f);
201  if ((hash_result=(long *)bdd_lookup_in_hash_table(h, BDD_THEN(f))))
202    {
203      if (*hash_result > f_index)
204        *hash_result=f_index;
205    }
206  else
207    {
208      bdd_insert_in_hash_table(h, BDD_THEN(f), (pointer)&f_index);
209      bdd_highest_ref_step(bddm, BDD_THEN(f), h);
210    }
211  if ((hash_result=(long *)bdd_lookup_in_hash_table(h, BDD_ELSE(f))))
212    {
213      if (*hash_result > f_index)
214        *hash_result=f_index;
215    }
216  else
217    {
218      bdd_insert_in_hash_table(h, BDD_ELSE(f), (pointer)&f_index);
219      bdd_highest_ref_step(bddm, BDD_ELSE(f), h);
220    }
221}
222
223
224static
225void
226bdd_dominated_step(cmu_bdd_manager bddm, bdd f, long *func_counts, hash_table h)
227{
228  long *hash_result;
229
230  hash_result=(long *)bdd_lookup_in_hash_table(h, f);
231  if (*hash_result >= 0)
232    func_counts[*hash_result]-=2;
233  if (*hash_result > -2)
234    {
235      BDD_SETUP(f);
236      *hash_result= -2;
237      if (!BDD_IS_CONST(f))
238        {
239          bdd_dominated_step(bddm, BDD_THEN(f), func_counts, h);
240          bdd_dominated_step(bddm, BDD_ELSE(f), func_counts, h);
241        }
242    }
243}
244
245
246/* cmu_bdd_function_profile(bddm, f, func_counts) returns a "function */
247/* profile" for f.  The nth entry of the function profile array is the */
248/* number of subfunctions of f which may be obtained by restricting */
249/* the variables whose index is less than n.  An entry of zero */
250/* indicates that f is independent of the variable with the */
251/* corresponding index. */
252
253void
254cmu_bdd_function_profile(cmu_bdd_manager bddm, bdd f, long *func_counts)
255{
256  long i;
257  bdd_index_type j;
258  hash_table h;
259
260  /* The number of subfunctions obtainable by restricting the */
261  /* variables of index < n is the number of subfunctions whose top */
262  /* variable has index n plus the number of subfunctions obtainable */
263  /* by restricting the variables of index < n+1 minus the number of */
264  /* these latter subfunctions whose highest reference is by a node at */
265  /* level n. */
266  /* The strategy will be to start with the number of subfunctions */
267  /* whose top variable has index n.  We compute the highest level at */
268  /* which each subfunction is referenced.  Then we work bottom up; at */
269  /* level n we add in the result from level n+1 and subtract the */
270  /* number of subfunctions whose highest reference is at level n. */
271  cmu_bdd_profile(bddm, f, func_counts, 0);
272  if (bdd_check_arguments(1, f))
273    {
274      /* Encode the profile.  The low bit of a count will be zero for */
275      /* those levels where f actually has a node. */
276      for (j=0; j < bddm->vars; ++j)
277        if (!func_counts[j])
278          func_counts[j]=1;
279        else
280          func_counts[j]<<=1;
281      h=bdd_new_hash_table(bddm, sizeof(long));
282      /* For each subfunction in f, compute the highest level where it is */
283      /* referenced.  f itself is conceptually referenced at the highest */
284      /* possible level, which we represent by -1. */
285      i= -1;
286      bdd_insert_in_hash_table(h, f, (pointer)&i);
287      bdd_highest_ref_step(bddm, f, h);
288      /* Walk through these results.  For each subfunction, decrement the */
289      /* count at the highest level where it is referenced. */
290      bdd_dominated_step(bddm, f, func_counts, h);
291      cmu_bdd_free_hash_table(h);
292      /* Now add each level n+1 result to that of level n. */
293      for (i=bddm->vars-1, j=i+1; i>= 0; --i)
294        if (func_counts[i] != 1)
295          {
296            func_counts[i]=(func_counts[i] >> 1)+func_counts[j];
297            j=i;
298          }
299        else
300          func_counts[i]=0;
301    }
302}
303
304
305/* cmu_bdd_function_profile_multiple is to cmu_bdd_function_profile as */
306/* cmu_bdd_size_multiple is to cmu_bdd_size. */
307
308void
309cmu_bdd_function_profile_multiple(cmu_bdd_manager bddm, bdd *fs, long *func_counts)
310{
311  long i;
312  bdd_index_type j;
313  bdd *f;
314  long *hash_result;
315  hash_table h;
316
317  bdd_check_array(fs);
318  /* See cmu_bdd_function_profile for the strategy involved here. */
319  cmu_bdd_profile_multiple(bddm, fs, func_counts, 0);
320  for (j=0; j < bddm->vars; ++j)
321    if (!func_counts[j])
322      func_counts[j]=1;
323    else
324      func_counts[j]<<=1;
325  h=bdd_new_hash_table(bddm, sizeof(long));
326  for (f=fs; *f; ++f)
327    bdd_highest_ref_step(bddm, *f, h);
328  i= -1;
329  for (f=fs; *f; ++f)
330    if ((hash_result=(long *)bdd_lookup_in_hash_table(h, *f)))
331      *hash_result= -1;
332    else
333      bdd_insert_in_hash_table(h, *f, (pointer)&i);
334  for (f=fs; *f; ++f)
335    bdd_dominated_step(bddm, *f, func_counts, h);
336  cmu_bdd_free_hash_table(h);
337  for (i=bddm->vars-1, j=i+1; i>= 0; --i)
338    if (func_counts[i] != 1)
339      {
340        func_counts[i]=(func_counts[i] >> 1)+func_counts[j];
341        j=i;
342      }
343    else
344      func_counts[i]=0;
345}
Note: See TracBrowser for help on using the repository browser.