abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddGenetic.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddGenetic.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Genetic algorithm for variable reordering.]
8 
9  Description [Internal procedures included in this file:
10  <ul>
11  <li> cuddGa()
12  </ul>
13  Static procedures included in this module:
14  <ul>
15  <li> make_random()
16  <li> sift_up()
17  <li> build_dd()
18  <li> largest()
19  <li> rand_int()
20  <li> array_hash()
21  <li> array_compare()
22  <li> find_best()
23  <li> find_average_fitness()
24  <li> PMX()
25  <li> roulette()
26  </ul>
27 
28  The genetic algorithm implemented here is as follows. We start with
29  the current DD order. We sift this order and use this as the
30  reference DD. We only keep 1 DD around for the entire process and
31  simply rearrange the order of this DD, storing the various orders
32  and their corresponding DD sizes. We generate more random orders to
33  build an initial population. This initial population is 3 times the
34  number of variables, with a maximum of 120. Each random order is
35  built (from the reference DD) and its size stored. Each random
36  order is also sifted to keep the DD sizes fairly small. Then a
37  crossover is performed between two orders (picked randomly) and the
38  two resulting DDs are built and sifted. For each new order, if its
39  size is smaller than any DD in the population, it is inserted into
40  the population and the DD with the largest number of nodes is thrown
41  out. The crossover process happens up to 50 times, and at this point
42  the DD in the population with the smallest size is chosen as the
43  result. This DD must then be built from the reference DD.]
44 
45  SeeAlso []
46 
47  Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi]
48 
49  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
50 
51  All rights reserved.
52 
53  Redistribution and use in source and binary forms, with or without
54  modification, are permitted provided that the following conditions
55  are met:
56 
57  Redistributions of source code must retain the above copyright
58  notice, this list of conditions and the following disclaimer.
59 
60  Redistributions in binary form must reproduce the above copyright
61  notice, this list of conditions and the following disclaimer in the
62  documentation and/or other materials provided with the distribution.
63 
64  Neither the name of the University of Colorado nor the names of its
65  contributors may be used to endorse or promote products derived from
66  this software without specific prior written permission.
67 
68  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
69  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
70  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
71  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
72  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
73  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
74  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
75  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
76  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
78  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
79  POSSIBILITY OF SUCH DAMAGE.]
80 
81 ******************************************************************************/
82 
83 #include "misc/util/util_hack.h"
84 #include "cuddInt.h"
85 
87 
88 
89 
90 /*---------------------------------------------------------------------------*/
91 /* Constant declarations */
92 /*---------------------------------------------------------------------------*/
93 
94 /*---------------------------------------------------------------------------*/
95 /* Stucture declarations */
96 /*---------------------------------------------------------------------------*/
97 
98 /*---------------------------------------------------------------------------*/
99 /* Type declarations */
100 /*---------------------------------------------------------------------------*/
101 
102 /*---------------------------------------------------------------------------*/
103 /* Variable declarations */
104 /*---------------------------------------------------------------------------*/
105 
106 #ifndef lint
107 static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.28 2004/08/13 18:04:48 fabio Exp $";
108 #endif
109 
110 static int popsize; /* the size of the population */
111 static int numvars; /* the number of input variables in the ckt. */
112 /* storedd stores the population orders and sizes. This table has two
113 ** extra rows and one extras column. The two extra rows are used for the
114 ** offspring produced by a crossover. Each row stores one order and its
115 ** size. The order is stored by storing the indices of variables in the
116 ** order in which they appear in the order. The table is in reality a
117 ** one-dimensional array which is accessed via a macro to give the illusion
118 ** it is a two-dimensional structure.
119 */
120 static int *storedd;
121 static st__table *computed; /* hash table to identify existing orders */
122 static int *repeat; /* how many times an order is present */
123 static int large; /* stores the index of the population with
124  ** the largest number of nodes in the DD */
125 static int result;
126 static int cross; /* the number of crossovers to perform */
127 
128 /*---------------------------------------------------------------------------*/
129 /* Macro declarations */
130 /*---------------------------------------------------------------------------*/
131 
132 /* macro used to access the population table as if it were a
133 ** two-dimensional structure.
134 */
135 #define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)]
136 
137 #ifdef __cplusplus
138 extern "C" {
139 #endif
140 
141 /**AutomaticStart*************************************************************/
142 
143 /*---------------------------------------------------------------------------*/
144 /* Static function prototypes */
145 /*---------------------------------------------------------------------------*/
146 
147 static int make_random (DdManager *table, int lower);
148 static int sift_up (DdManager *table, int x, int x_low);
149 static int build_dd (DdManager *table, int num, int lower, int upper);
150 static int largest (void);
151 static int rand_int (int a);
152 static int array_hash (const char *array, int modulus);
153 static int array_compare (const char *array1, const char *array2);
154 static int find_best (void);
155 #ifdef DD_STATS
156 static double find_average_fitness (void);
157 #endif
158 static int PMX (int maxvar);
159 static int roulette (int *p1, int *p2);
160 
161 /**AutomaticEnd***************************************************************/
162 
163 #ifdef __cplusplus
164 }
165 #endif
166 
167 /*---------------------------------------------------------------------------*/
168 /* Definition of exported functions */
169 /*---------------------------------------------------------------------------*/
170 
171 /*---------------------------------------------------------------------------*/
172 /* Definition of internal functions */
173 /*---------------------------------------------------------------------------*/
174 
175 
176 /**Function********************************************************************
177 
178  Synopsis [Genetic algorithm for DD reordering.]
179 
180  Description [Genetic algorithm for DD reordering.
181  The two children of a crossover will be stored in
182  storedd[popsize] and storedd[popsize+1] --- the last two slots in the
183  storedd array. (This will make comparisons and replacement easy.)
184  Returns 1 in case of success; 0 otherwise.]
185 
186  SideEffects [None]
187 
188  SeeAlso []
189 
190 ******************************************************************************/
191 int
193  DdManager * table /* manager */,
194  int lower /* lowest level to be reordered */,
195  int upper /* highest level to be reorderded */)
196 {
197  int i,n,m; /* dummy/loop vars */
198  int index;
199 #ifdef DD_STATS
200  double average_fitness;
201 #endif
202  int small; /* index of smallest DD in population */
203 
204  /* Do an initial sifting to produce at least one reasonable individual. */
205  if (!cuddSifting(table,lower,upper)) return(0);
206 
207  /* Get the initial values. */
208  numvars = upper - lower + 1; /* number of variables to be reordered */
209  if (table->populationSize == 0) {
210  popsize = 3 * numvars; /* population size is 3 times # of vars */
211  if (popsize > 120) {
212  popsize = 120; /* Maximum population size is 120 */
213  }
214  } else {
215  popsize = table->populationSize; /* user specified value */
216  }
217  if (popsize < 4) popsize = 4; /* enforce minimum population size */
218 
219  /* Allocate population table. */
220  storedd = ABC_ALLOC(int,(popsize+2)*(numvars+1));
221  if (storedd == NULL) {
222  table->errorCode = CUDD_MEMORY_OUT;
223  return(0);
224  }
225 
226  /* Initialize the computed table. This table is made up of two data
227  ** structures: A hash table with the key given by the order, which says
228  ** if a given order is present in the population; and the repeat
229  ** vector, which says how many copies of a given order are stored in
230  ** the population table. If there are multiple copies of an order, only
231  ** one has a repeat count greater than 1. This copy is the one pointed
232  ** by the computed table.
233  */
234  repeat = ABC_ALLOC(int,popsize);
235  if (repeat == NULL) {
236  table->errorCode = CUDD_MEMORY_OUT;
237  ABC_FREE(storedd);
238  return(0);
239  }
240  for (i = 0; i < popsize; i++) {
241  repeat[i] = 0;
242  }
244  if (computed == NULL) {
245  table->errorCode = CUDD_MEMORY_OUT;
246  ABC_FREE(storedd);
247  ABC_FREE(repeat);
248  return(0);
249  }
250 
251  /* Copy the current DD and its size to the population table. */
252  for (i = 0; i < numvars; i++) {
253  STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
254  }
255  STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
256 
257  /* Store the initial order in the computed table. */
258  if ( st__insert(computed,(char *)storedd,(char *) 0) == st__OUT_OF_MEM) {
259  ABC_FREE(storedd);
260  ABC_FREE(repeat);
261  st__free_table(computed);
262  return(0);
263  }
264  repeat[0]++;
265 
266  /* Insert the reverse order as second element of the population. */
267  for (i = 0; i < numvars; i++) {
268  STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
269  }
270 
271  /* Now create the random orders. make_random fills the population
272  ** table with random permutations. The successive loop builds and sifts
273  ** the DDs for the reverse order and each random permutation, and stores
274  ** the results in the computed table.
275  */
276  if (!make_random(table,lower)) {
277  table->errorCode = CUDD_MEMORY_OUT;
278  ABC_FREE(storedd);
279  ABC_FREE(repeat);
280  st__free_table(computed);
281  return(0);
282  }
283  for (i = 1; i < popsize; i++) {
284  result = build_dd(table,i,lower,upper); /* build and sift order */
285  if (!result) {
286  ABC_FREE(storedd);
287  ABC_FREE(repeat);
288  st__free_table(computed);
289  return(0);
290  }
291  if ( st__lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
292  repeat[index]++;
293  } else {
294  if ( st__insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
295  st__OUT_OF_MEM) {
296  ABC_FREE(storedd);
297  ABC_FREE(repeat);
298  st__free_table(computed);
299  return(0);
300  }
301  repeat[i]++;
302  }
303  }
304 
305 #if 0
306 #ifdef DD_STATS
307  /* Print the initial population. */
308  (void) fprintf(table->out,"Initial population after sifting\n");
309  for (m = 0; m < popsize; m++) {
310  for (i = 0; i < numvars; i++) {
311  (void) fprintf(table->out," %2d",STOREDD(m,i));
312  }
313  (void) fprintf(table->out," : %3d (%d)\n",
314  STOREDD(m,numvars),repeat[m]);
315  }
316 #endif
317 #endif
318 
319  small = find_best();
320 #ifdef DD_STATS
321  average_fitness = find_average_fitness();
322  (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
323 #endif
324 
325  /* Decide how many crossovers should be tried. */
326  if (table->numberXovers == 0) {
327  cross = 3*numvars;
328  if (cross > 60) { /* do a maximum of 50 crossovers */
329  cross = 60;
330  }
331  } else {
332  cross = table->numberXovers; /* use user specified value */
333  }
334 
335  /* Perform the crossovers to get the best order. */
336  for (m = 0; m < cross; m++) {
337  if (!PMX(table->size)) { /* perform one crossover */
338  table->errorCode = CUDD_MEMORY_OUT;
339  ABC_FREE(storedd);
340  ABC_FREE(repeat);
341  st__free_table(computed);
342  return(0);
343  }
344  /* The offsprings are left in the last two entries of the
345  ** population table. These are now considered in turn.
346  */
347  for (i = popsize; i <= popsize+1; i++) {
348  result = build_dd(table,i,lower,upper); /* build and sift child */
349  if (!result) {
350  ABC_FREE(storedd);
351  ABC_FREE(repeat);
352  st__free_table(computed);
353  return(0);
354  }
355  large = largest(); /* find the largest DD in population */
356 
357  /* If the new child is smaller than the largest DD in the current
358  ** population, enter it into the population in place of the
359  ** largest DD.
360  */
361  if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
362  /* Look up the largest DD in the computed table.
363  ** Decrease its repetition count. If the repetition count
364  ** goes to 0, remove the largest DD from the computed table.
365  */
366  result = st__lookup_int(computed,(char *)&STOREDD(large,0),
367  &index);
368  if (!result) {
369  ABC_FREE(storedd);
370  ABC_FREE(repeat);
371  st__free_table(computed);
372  return(0);
373  }
374  repeat[index]--;
375  if (repeat[index] == 0) {
376  int *pointer = &STOREDD(index,0);
377  result = st__delete(computed, (const char **)&pointer, NULL);
378  if (!result) {
379  ABC_FREE(storedd);
380  ABC_FREE(repeat);
381  st__free_table(computed);
382  return(0);
383  }
384  }
385  /* Copy the new individual to the entry of the
386  ** population table just made available and update the
387  ** computed table.
388  */
389  for (n = 0; n <= numvars; n++) {
390  STOREDD(large,n) = STOREDD(i,n);
391  }
392  if ( st__lookup_int(computed,(char *)&STOREDD(large,0),
393  &index)) {
394  repeat[index]++;
395  } else {
396  if ( st__insert(computed,(char *)&STOREDD(large,0),
397  (char *)(long)large) == st__OUT_OF_MEM) {
398  ABC_FREE(storedd);
399  ABC_FREE(repeat);
400  st__free_table(computed);
401  return(0);
402  }
403  repeat[large]++;
404  }
405  }
406  }
407  }
408 
409  /* Find the smallest DD in the population and build it;
410  ** that will be the result.
411  */
412  small = find_best();
413 
414  /* Print stats on the final population. */
415 #ifdef DD_STATS
416  average_fitness = find_average_fitness();
417  (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
418 #endif
419 
420  /* Clean up, build the result DD, and return. */
421  st__free_table(computed);
422  computed = NULL;
423  result = build_dd(table,small,lower,upper);
424  ABC_FREE(storedd);
425  ABC_FREE(repeat);
426  return(result);
427 
428 } /* end of cuddGa */
429 
430 
431 /*---------------------------------------------------------------------------*/
432 /* Definition of static functions */
433 /*---------------------------------------------------------------------------*/
434 
435 /**Function********************************************************************
436 
437  Synopsis [Generates the random sequences for the initial population.]
438 
439  Description [Generates the random sequences for the initial population.
440  The sequences are permutations of the indices between lower and
441  upper in the current order.]
442 
443  SideEffects [None]
444 
445  SeeAlso []
446 
447 ******************************************************************************/
448 static int
450  DdManager * table,
451  int lower)
452 {
453  int i,j; /* loop variables */
454  int *used; /* is a number already in a permutation */
455  int next; /* next random number without repetitions */
456 
457  used = ABC_ALLOC(int,numvars);
458  if (used == NULL) {
459  table->errorCode = CUDD_MEMORY_OUT;
460  return(0);
461  }
462 #if 0
463 #ifdef DD_STATS
464  (void) fprintf(table->out,"Initial population before sifting\n");
465  for (i = 0; i < 2; i++) {
466  for (j = 0; j < numvars; j++) {
467  (void) fprintf(table->out," %2d",STOREDD(i,j));
468  }
469  (void) fprintf(table->out,"\n");
470  }
471 #endif
472 #endif
473  for (i = 2; i < popsize; i++) {
474  for (j = 0; j < numvars; j++) {
475  used[j] = 0;
476  }
477  /* Generate a permutation of {0...numvars-1} and use it to
478  ** permute the variables in the layesr from lower to upper.
479  */
480  for (j = 0; j < numvars; j++) {
481  do {
482  next = rand_int(numvars-1);
483  } while (used[next] != 0);
484  used[next] = 1;
485  STOREDD(i,j) = table->invperm[next+lower];
486  }
487 #if 0
488 #ifdef DD_STATS
489  /* Print the order just generated. */
490  for (j = 0; j < numvars; j++) {
491  (void) fprintf(table->out," %2d",STOREDD(i,j));
492  }
493  (void) fprintf(table->out,"\n");
494 #endif
495 #endif
496  }
497  ABC_FREE(used);
498  return(1);
499 
500 } /* end of make_random */
501 
502 
503 /**Function********************************************************************
504 
505  Synopsis [Moves one variable up.]
506 
507  Description [Takes a variable from position x and sifts it up to
508  position x_low; x_low should be less than x. Returns 1 if successful;
509  0 otherwise]
510 
511  SideEffects [None]
512 
513  SeeAlso []
514 
515 ******************************************************************************/
516 static int
518  DdManager * table,
519  int x,
520  int x_low)
521 {
522  int y;
523  int size;
524 
525  y = cuddNextLow(table,x);
526  while (y >= x_low) {
527  size = cuddSwapInPlace(table,y,x);
528  if (size == 0) {
529  return(0);
530  }
531  x = y;
532  y = cuddNextLow(table,x);
533  }
534  return(1);
535 
536 } /* end of sift_up */
537 
538 
539 /**Function********************************************************************
540 
541  Synopsis [Builds a DD from a given order.]
542 
543  Description [Builds a DD from a given order. This procedure also
544  sifts the final order and inserts into the array the size in nodes
545  of the result. Returns 1 if successful; 0 otherwise.]
546 
547  SideEffects [None]
548 
549  SeeAlso []
550 
551 ******************************************************************************/
552 static int
554  DdManager * table,
555  int num /* the index of the individual to be built */,
556  int lower,
557  int upper)
558 {
559  int i,j; /* loop vars */
560  int position;
561  int index;
562  int limit; /* how large the DD for this order can grow */
563  int size;
564 
565  /* Check the computed table. If the order already exists, it
566  ** suffices to copy the size from the existing entry.
567  */
568  if (computed && st__lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
569  STOREDD(num,numvars) = STOREDD(index,numvars);
570 #ifdef DD_STATS
571  (void) fprintf(table->out,"\nCache hit for index %d", index);
572 #endif
573  return(1);
574  }
575 
576  /* Stop if the DD grows 20 times larges than the reference size. */
577  limit = 20 * STOREDD(0,numvars);
578 
579  /* Sift up the variables so as to build the desired permutation.
580  ** First the variable that has to be on top is sifted to the top.
581  ** Then the variable that has to occupy the secon position is sifted
582  ** up to the second position, and so on.
583  */
584  for (j = 0; j < numvars; j++) {
585  i = STOREDD(num,j);
586  position = table->perm[i];
587  result = sift_up(table,position,j+lower);
588  if (!result) return(0);
589  size = table->keys - table->isolated;
590  if (size > limit) break;
591  }
592 
593  /* Sift the DD just built. */
594 #ifdef DD_STATS
595  (void) fprintf(table->out,"\n");
596 #endif
597  result = cuddSifting(table,lower,upper);
598  if (!result) return(0);
599 
600  /* Copy order and size to table. */
601  for (j = 0; j < numvars; j++) {
602  STOREDD(num,j) = table->invperm[lower+j];
603  }
604  STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
605  return(1);
606 
607 } /* end of build_dd */
608 
609 
610 /**Function********************************************************************
611 
612  Synopsis [Finds the largest DD in the population.]
613 
614  Description [Finds the largest DD in the population. If an order is
615  repeated, it avoids choosing the copy that is in the computed table
616  (it has repeat[i] > 1).]
617 
618  SideEffects [None]
619 
620  SeeAlso []
621 
622 ******************************************************************************/
623 static int
624 largest(void)
625 {
626  int i; /* loop var */
627  int big; /* temporary holder to return result */
628 
629  big = 0;
630  while (repeat[big] > 1) big++;
631  for (i = big + 1; i < popsize; i++) {
632  if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) {
633  big = i;
634  }
635  }
636  return(big);
637 
638 } /* end of largest */
639 
640 
641 /**Function********************************************************************
642 
643  Synopsis [Generates a random number between 0 and the integer a.]
644 
645  Description []
646 
647  SideEffects [None]
648 
649  SeeAlso []
650 
651 ******************************************************************************/
652 static int
654  int a)
655 {
656  return(Cudd_Random() % (a+1));
657 
658 } /* end of rand_int */
659 
660 
661 /**Function********************************************************************
662 
663  Synopsis [Hash function for the computed table.]
664 
665  Description [Hash function for the computed table. Returns the bucket
666  number.]
667 
668  SideEffects [None]
669 
670  SeeAlso []
671 
672 ******************************************************************************/
673 static int
675  const char * array,
676  int modulus)
677 {
678  int val = 0;
679  int i;
680  int *intarray;
681 
682  intarray = (int *) array;
683 
684  for (i = 0; i < numvars; i++) {
685  val = val * 997 + intarray[i];
686  }
687 
688  return ((val < 0) ? -val : val) % modulus;
689 
690 } /* end of array_hash */
691 
692 
693 /**Function********************************************************************
694 
695  Synopsis [Comparison function for the computed table.]
696 
697  Description [Comparison function for the computed table. Returns 0 if
698  the two arrays are equal; 1 otherwise.]
699 
700  SideEffects [None]
701 
702  SeeAlso []
703 
704 ******************************************************************************/
705 static int
707  const char * array1,
708  const char * array2)
709 {
710  int i;
711  int *intarray1, *intarray2;
712 
713  intarray1 = (int *) array1;
714  intarray2 = (int *) array2;
715 
716  for (i = 0; i < numvars; i++) {
717  if (intarray1[i] != intarray2[i]) return(1);
718  }
719  return(0);
720 
721 } /* end of array_compare */
722 
723 
724 /**Function********************************************************************
725 
726  Synopsis [Returns the index of the fittest individual.]
727 
728  Description []
729 
730  SideEffects [None]
731 
732  SeeAlso []
733 
734 ******************************************************************************/
735 static int
737 {
738  int i,small;
739 
740  small = 0;
741  for (i = 1; i < popsize; i++) {
742  if (STOREDD(i,numvars) < STOREDD(small,numvars)) {
743  small = i;
744  }
745  }
746  return(small);
747 
748 } /* end of find_best */
749 
750 
751 /**Function********************************************************************
752 
753  Synopsis [Returns the average fitness of the population.]
754 
755  Description []
756 
757  SideEffects [None]
758 
759  SeeAlso []
760 
761 ******************************************************************************/
762 #ifdef DD_STATS
763 static double
764 find_average_fitness(void)
765 {
766  int i;
767  int total_fitness = 0;
768  double average_fitness;
769 
770  for (i = 0; i < popsize; i++) {
771  total_fitness += STOREDD(i,numvars);
772  }
773  average_fitness = (double) total_fitness / (double) popsize;
774  return(average_fitness);
775 
776 } /* end of find_average_fitness */
777 #endif
778 
779 
780 /**Function********************************************************************
781 
782  Synopsis [Performs the crossover between two parents.]
783 
784  Description [Performs the crossover between two randomly chosen
785  parents, and creates two children, x1 and x2. Uses the Partially
786  Matched Crossover operator.]
787 
788  SideEffects [None]
789 
790  SeeAlso []
791 
792 ******************************************************************************/
793 static int
795  int maxvar)
796 {
797  int cut1,cut2; /* the two cut positions (random) */
798  int mom,dad; /* the two randomly chosen parents */
799  int *inv1; /* inverse permutations for repair algo */
800  int *inv2;
801  int i; /* loop vars */
802  int u,v; /* aux vars */
803 
804  inv1 = ABC_ALLOC(int,maxvar);
805  if (inv1 == NULL) {
806  return(0);
807  }
808  inv2 = ABC_ALLOC(int,maxvar);
809  if (inv2 == NULL) {
810  ABC_FREE(inv1);
811  return(0);
812  }
813 
814  /* Choose two orders from the population using roulette wheel. */
815  if (!roulette(&mom,&dad)) {
816  ABC_FREE(inv1);
817  ABC_FREE(inv2);
818  return(0);
819  }
820 
821  /* Choose two random cut positions. A cut in position i means that
822  ** the cut immediately precedes position i. If cut1 < cut2, we
823  ** exchange the middle of the two orderings; otherwise, we
824  ** exchange the beginnings and the ends.
825  */
826  cut1 = rand_int(numvars-1);
827  do {
828  cut2 = rand_int(numvars-1);
829  } while (cut1 == cut2);
830 
831 #if 0
832  /* Print out the parents. */
833  (void) fprintf(table->out,
834  "Crossover of %d (mom) and %d (dad) between %d and %d\n",
835  mom,dad,cut1,cut2);
836  for (i = 0; i < numvars; i++) {
837  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
838  (void) fprintf(table->out,"%2d ",STOREDD(mom,i));
839  }
840  (void) fprintf(table->out,"\n");
841  for (i = 0; i < numvars; i++) {
842  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
843  (void) fprintf(table->out,"%2d ",STOREDD(dad,i));
844  }
845  (void) fprintf(table->out,"\n");
846 #endif
847 
848  /* Initialize the inverse permutations: -1 means yet undetermined. */
849  for (i = 0; i < maxvar; i++) {
850  inv1[i] = -1;
851  inv2[i] = -1;
852  }
853 
854  /* Copy the portions whithin the cuts. */
855  for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) {
856  STOREDD(popsize,i) = STOREDD(dad,i);
857  inv1[STOREDD(popsize,i)] = i;
858  STOREDD(popsize+1,i) = STOREDD(mom,i);
859  inv2[STOREDD(popsize+1,i)] = i;
860  }
861 
862  /* Now apply the repair algorithm outside the cuts. */
863  for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) {
864  v = i;
865  do {
866  u = STOREDD(mom,v);
867  v = inv1[u];
868  } while (v != -1);
869  STOREDD(popsize,i) = u;
870  inv1[u] = i;
871  v = i;
872  do {
873  u = STOREDD(dad,v);
874  v = inv2[u];
875  } while (v != -1);
876  STOREDD(popsize+1,i) = u;
877  inv2[u] = i;
878  }
879 
880 #if 0
881  /* Print the results of crossover. */
882  for (i = 0; i < numvars; i++) {
883  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
884  (void) fprintf(table->out,"%2d ",STOREDD(popsize,i));
885  }
886  (void) fprintf(table->out,"\n");
887  for (i = 0; i < numvars; i++) {
888  if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
889  (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i));
890  }
891  (void) fprintf(table->out,"\n");
892 #endif
893 
894  ABC_FREE(inv1);
895  ABC_FREE(inv2);
896  return(1);
897 
898 } /* end of PMX */
899 
900 
901 /**Function********************************************************************
902 
903  Synopsis [Selects two parents with the roulette wheel method.]
904 
905  Description [Selects two distinct parents with the roulette wheel method.]
906 
907  SideEffects [The indices of the selected parents are returned as side
908  effects.]
909 
910  SeeAlso []
911 
912 ******************************************************************************/
913 static int
915  int * p1,
916  int * p2)
917 {
918  double *wheel;
919  double spin;
920  int i;
921 
922  wheel = ABC_ALLOC(double,popsize);
923  if (wheel == NULL) {
924  return(0);
925  }
926 
927  /* The fitness of an individual is the reciprocal of its size. */
928  wheel[0] = 1.0 / (double) STOREDD(0,numvars);
929 
930  for (i = 1; i < popsize; i++) {
931  wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars);
932  }
933 
934  /* Get a random number between 0 and wheel[popsize-1] (that is,
935  ** the sum of all fitness values. 2147483561 is the largest number
936  ** returned by Cudd_Random.
937  */
938  spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0;
939 
940  /* Find the lucky element by scanning the wheel. */
941  for (i = 0; i < popsize; i++) {
942  if (spin <= wheel[i]) break;
943  }
944  *p1 = i;
945 
946  /* Repeat the process for the second parent, making sure it is
947  ** distinct from the first.
948  */
949  do {
950  spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0;
951  for (i = 0; i < popsize; i++) {
952  if (spin <= wheel[i]) break;
953  }
954  } while (i == *p1);
955  *p2 = i;
956 
957  ABC_FREE(wheel);
958  return(1);
959 
960 } /* end of roulette */
961 
962 
964 
965 
static int large
Definition: cuddGenetic.c:123
void st__free_table(st__table *table)
Definition: st.c:81
static int sift_up(DdManager *table, int x, int x_low)
Definition: cuddGenetic.c:517
static int * storedd
Definition: cuddGenetic.c:120
int st__delete(st__table *table, const char **keyp, char **value)
Definition: st.c:375
int st__insert(st__table *table, const char *key, char *value)
Definition: st.c:171
int size
Definition: cuddInt.h:361
static int roulette(int *p1, int *p2)
Definition: cuddGenetic.c:914
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddReorder.c:508
int populationSize
Definition: cuddInt.h:430
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int st__lookup_int(st__table *table, char *key, int *value)
Definition: st.c:134
int cuddGa(DdManager *table, int lower, int upper)
Definition: cuddGenetic.c:192
static st__table * computed
Definition: cuddGenetic.c:121
static int cross
Definition: cuddGenetic.c:126
st__table * st__init_table(st__compare_func_type compare, st__hash_func_type hash)
Definition: st.c:72
long Cudd_Random(void)
Definition: cuddUtil.c:2702
static int find_best(void)
Definition: cuddGenetic.c:736
unsigned int keys
Definition: cuddInt.h:369
static int build_dd(DdManager *table, int num, int lower, int upper)
Definition: cuddGenetic.c:553
static int array_hash(const char *array, int modulus)
Definition: cuddGenetic.c:674
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
Definition: st.h:52
static int array_compare(const char *array1, const char *array2)
Definition: cuddGenetic.c:706
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
int numberXovers
Definition: cuddInt.h:431
static int size
Definition: cuddSign.c:86
static int popsize
Definition: cuddGenetic.c:110
#define st__OUT_OF_MEM
Definition: st.h:113
static int largest(void)
Definition: cuddGenetic.c:624
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int * repeat
Definition: cuddGenetic.c:122
static int rand_int(int a)
Definition: cuddGenetic.c:653
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
static ABC_NAMESPACE_IMPL_START char rcsid[] DD_UNUSED
Definition: cuddGenetic.c:107
#define STOREDD(i, j)
Definition: cuddGenetic.c:135
int * perm
Definition: cuddInt.h:386
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
static int make_random(DdManager *table, int lower)
Definition: cuddGenetic.c:449
static int PMX(int maxvar)
Definition: cuddGenetic.c:794