source: trunk/optimizer/src/pgapack/pgapack/source/utility.c @ 816

Last change on this file since 816 was 816, checked in by liveletlive, 17 years ago

Committing the newer version of PGAPack.

File size: 17.6 KB
Line 
1/*
2 * 
3 *  *********************************************************************
4 *  (C) COPYRIGHT 1995 UNIVERSITY OF CHICAGO
5 *  *********************************************************************
6 * 
7 *  This software was authored by
8 * 
9 *  D. Levine
10 *  Mathematics and Computer Science Division Argonne National Laboratory
11 *  Argonne IL 60439
12 *  levine@mcs.anl.gov
13 *  (708) 252-6735
14 *  (708) 252-5986 (FAX)
15 * 
16 *  with programming assistance of participants in Argonne National
17 *  Laboratory's SERS program.
18 * 
19 *  This program contains material protectable under copyright laws of the
20 *  United States.  Permission is hereby granted to use it, reproduce it,
21 *  to translate it into another language, and to redistribute it to
22 *  others at no charge except a fee for transferring a copy, provided
23 *  that you conspicuously and appropriately publish on each copy the
24 *  University of Chicago's copyright notice, and the disclaimer of
25 *  warranty and Government license included below.  Further, permission
26 *  is hereby granted, subject to the same provisions, to modify a copy or
27 *  copies or any portion of it, and to distribute to others at no charge
28 *  materials containing or derived from the material.
29 * 
30 *  The developers of the software ask that you acknowledge its use in any
31 *  document referencing work based on the  program, such as published
32 *  research.  Also, they ask that you supply to Argonne National
33 *  Laboratory a copy of any published research referencing work based on
34 *  the software.
35 * 
36 *  Any entity desiring permission for further use must contact:
37 * 
38 *  J. Gleeson
39 *  Industrial Technology Development Center Argonne National Laboratory
40 *  Argonne IL 60439
41 *  gleesonj@smtplink.eid.anl.gov
42 *  (708) 252-6055
43 * 
44 *  ********************************************************************
45 *  DISCLAIMER
46 * 
47 *  THIS PROGRAM WAS PREPARED AS AN ACCOUNT OF WORK SPONSORED BY AN AGENCY
48 *  OF THE UNITED STATES GOVERNMENT.  NEITHER THE UNIVERSITY OF CHICAGO,
49 *  THE UNITED STATES GOVERNMENT NOR ANY OF THEIR EMPLOYEES MAKE ANY
50 *  WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
51 *  RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
52 *  INFORMATION OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT
53 *  INFRINGE PRIVATELY OWNED RIGHTS.
54 * 
55 *  **********************************************************************
56 *  GOVERNMENT LICENSE
57 * 
58 *  The Government is granted for itself and others acting on its behalf a
59 *  paid-up, non-exclusive, irrevocable worldwide license in this computer
60 *  software to reproduce, prepare derivative works, and perform publicly
61 *  and display publicly.
62 */
63
64/*****************************************************************************
65*     FILE: utility.c: This file contains routines that perform utility
66*                      functions.
67*
68*     Authors: David M. Levine, Philip L. Hallstrom, David M. Noelle,
69*              Brian P. Walenz
70*****************************************************************************/
71
72#include <pgapack.h>
73
74/*U****************************************************************************
75  PGAMean - calculates the mean value of an array of elements
76
77  Category: Utility
78
79  Inputs:
80    ctx  - context variable
81    a    - array to take the mean of
82    n    - number of elements in array a
83
84  Outputs:
85    The mean of the n elements in array a
86
87  Example:
88    PGAContext *ctx;
89    double a[100], mean;
90    :
91    mean = PGAMean(ctx, a, 100);
92
93****************************************************************************U*/
94double PGAMean ( PGAContext *ctx, double *a, int n)
95{
96    int i;
97    double result;
98
99    PGADebugEntered("PGAMean");
100
101    result = 0.;
102    for( i=n-1; i>=0; i-- )
103        result += a[i];
104
105    PGADebugExited("PGAMean");
106
107    return (result / (double) n );
108}
109
110
111/*U****************************************************************************
112  PGAStddev - calculates the standard deviation of an array of elements
113
114  Category: Utility
115
116  Inputs:
117    ctx  - context variable
118    a    - array to take the standard deviation of
119    n    - number of elements in array a
120    mean - the mean of the elements in array a
121
122  Outputs:
123    The standard deviation of the n elements in array a
124
125  Example:
126    PGAContext *ctx;
127    double a[100], mean, sigma;
128    :
129    mean  = PGAMean(ctx, a, 100);
130    sigma = PGAStddev(ctx, a, 100, mean);
131
132****************************************************************************U*/
133double PGAStddev ( PGAContext *ctx, double *a, int n, double mean)
134{
135    int i;
136    double result;
137
138    PGADebugEntered("PGAStddev");
139
140    result = 0;
141    for(i=n-1; i>=0; i--)
142        result += (a[i] - mean) * (a[i] - mean);
143    result  = sqrt(result/n);
144
145    PGADebugExited("PGAStddev");
146    return (result);
147}
148
149/*U****************************************************************************
150  PGARound - Mathematically round a double to an integer, using 0.5 as the
151  cutoff value.
152
153  Category: Utility
154
155  Inputs:
156     ctx - context variable
157     x - the number to be rounded
158
159  Outputs:
160     The rounded number.
161
162  Example:
163     PGAContext *ctx;
164     int y;
165     y = PGARound(ctx, -78.6);
166
167****************************************************************************U*/
168int PGARound(PGAContext *ctx, double x)
169{
170    double ipart, frac;
171
172    PGADebugEntered("PGARound");
173
174    frac = modf(x, &ipart);
175    if (frac <= -0.5)
176      ipart--;
177    else if (frac >= 0.5)
178      ipart++;
179
180    PGADebugExited("PGARound");
181
182    return ((int)ipart);
183}
184
185/*U****************************************************************************
186  PGACopyIndividual - copies string p1 in population pop1 to position p2 in
187  population pop2
188
189  Category: Generation
190
191  Inputs:
192     ctx  - context variable
193     p1   - string to copy
194     pop1 - symbolic constant of population containing string p1
195     p2   - string to copy p1 to
196     pop2 - symbolic constant of population containing string p2
197
198  Outputs:
199     String p2 is an exact copy of string p1.
200
201  Example:
202    PGAContext *ctx;
203    int i,j;
204    :
205    PGACopyIndividual(ctx, i, PGA_OLDPOP, j, PGA_NEWPOP);
206
207****************************************************************************U*/
208void PGACopyIndividual( PGAContext *ctx, int p1, int pop1, int p2, int pop2)
209{
210    PGAIndividual *source, *dest;
211
212    PGADebugEntered("PGACopyIndividual");
213
214    source = PGAGetIndividual ( ctx, p1, pop1 );
215    dest   = PGAGetIndividual ( ctx, p2, pop2 );
216
217    dest->evalfunc     = source->evalfunc;
218    dest->fitness      = source->fitness;
219    dest->evaluptodate = source->evaluptodate;
220
221    (*ctx->cops.CopyString)(ctx, p1, pop1, p2, pop2);
222
223    PGADebugExited("PGACopyIndividual");
224}
225
226/*U****************************************************************************
227  PGACheckSum - maps a string to a number to be used a verification check
228  PGA_DATATYPE_USER is not supported.
229
230  Category: Utility
231
232  Inputs:
233     ctx    - context variable
234     p      - string index
235     pop    - symbolic constant for the population
236
237  Outputs:
238     An integer representing the "value" of the string.
239
240  Example:
241     PGAContext *ctx;
242     int p, sum;
243     :
244     sum = PGACheckSum(ctx, p, PGA_NEWPOP);
245
246****************************************************************************U*/
247int PGACheckSum(PGAContext *ctx, int p, int pop)
248{
249    long stringlen, totalchars, charbits, i, j, checksum, totalbytes, out_bit;
250    unsigned char *message, specimen;
251
252    PGADebugEntered("PGACheckSum");
253
254    stringlen = PGAGetStringLength(ctx);
255    switch (ctx->ga.datatype) {
256      case PGA_DATATYPE_BINARY:
257        totalbytes = ctx->ga.tw * sizeof(PGABinary);
258        break;
259      case PGA_DATATYPE_INTEGER:
260        totalbytes = stringlen * sizeof(PGAInteger);
261        break;
262      case PGA_DATATYPE_REAL:
263        totalbytes = stringlen * sizeof(PGAReal);
264        break;
265      case PGA_DATATYPE_CHARACTER:
266        totalbytes = stringlen * sizeof(PGACharacter);
267        break;
268      default:
269        totalbytes = 0;
270        PGAError(ctx, "PGACheckSum: User datatype checksum may be invalid.",
271                 PGA_WARNING, PGA_VOID, NULL);
272        break;
273      }
274
275    message = (unsigned char *)PGAGetIndividual(ctx, p, pop)->chrom;
276    totalchars = totalbytes / sizeof(unsigned char);
277    charbits = sizeof(unsigned char) * 8;
278    checksum = 0;
279    for (i = 0; i < totalchars; i++) {
280      specimen = *(message + i);
281      for (j = 0; j < charbits; j++) {
282        out_bit = (checksum & 0x80000000) == 1;
283        checksum = (checksum << 1) + ((specimen & 0x80) == 0x80);
284        if (out_bit)
285          checksum ^= 0x04c11db7;
286        specimen <<= 1;
287      }
288    }
289
290    PGADebugExited("PGACheckSum");
291
292    return (checksum);
293}
294
295/*U***************************************************************************
296  PGAGetWorstIndex - returns the index of the string with the worst
297  evaluation function value in population pop
298
299  Category: Utility
300
301  Inputs:
302     ctx - context variable
303     pop - symbolic constant of the population to find the worst string in
304
305  Outputs:
306     Index of the string with the worst evaluation function value
307
308  Example:
309     PGAContext *ctx;
310     int worst;
311     :
312     worst = PGAGetWorstIndex(ctx,PGA_OLDPOP);
313
314***************************************************************************U*/
315int PGAGetWorstIndex(PGAContext *ctx, int pop)
316{
317    int     p, worst_indx = 0;
318    double  eval, worst_eval;
319
320    PGADebugEntered("PGAGetWorstIndex");
321
322    for (p = 0; p < ctx->ga.PopSize; p++)
323        if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop))
324            PGAError(ctx, "PGAGetWorstIndex: Evaluate function not up to "
325                     "date:", PGA_FATAL, PGA_INT, (void *) &p);
326
327    worst_eval = PGAGetEvaluation(ctx, 0, pop);
328    switch (PGAGetOptDirFlag(ctx)) {
329    case PGA_MAXIMIZE:
330        for (p = 1; p < ctx->ga.PopSize; p++) {
331            eval = PGAGetEvaluation(ctx, p, pop);
332            if (eval < worst_eval) {
333                worst_indx = p;
334                worst_eval = eval;
335            }
336        }
337        break;
338
339    case PGA_MINIMIZE:
340        for (p = 1; p < ctx->ga.PopSize; p++) {
341            eval = PGAGetEvaluation(ctx, p, pop);
342            if (eval > worst_eval) {
343                worst_indx = p;
344                worst_eval = eval;
345            }
346        }
347        break;   
348    }
349
350    PGADebugExited("PGAGetWorstIndex");
351
352    return (worst_indx);
353}
354
355/*U***************************************************************************
356  PGAGetBestIndex - returns the index of the string with the best evaluation
357  function value in population pop
358
359  Category: Utility
360
361  Inputs:
362     ctx - context variable
363     pop - symbolic constant of the population to find the best string in
364
365  Outputs:
366     Index of the string with the best evaluation function value
367
368  Example:
369     PGAContext *ctx;
370     int best;
371     :
372     best = PGAGetBestIndex(ctx,PGA_OLDPOP);
373
374***************************************************************************U*/
375int PGAGetBestIndex(PGAContext *ctx, int pop)
376{
377     int     p, Best_indx = 0;
378     double  eval, Best_eval;
379
380    PGADebugEntered("PGAGetBestIndex");
381     
382     for (p = 0; p < ctx->ga.PopSize; p++)
383         if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop))
384             PGAError(ctx, "PGAGetBestIndex: Evaluate function not up to "
385                      "date:", PGA_FATAL, PGA_INT, (void *) &p);
386     
387     Best_eval = PGAGetEvaluation(ctx, 0, pop);
388
389     switch (PGAGetOptDirFlag(ctx)) {
390     case PGA_MAXIMIZE :
391         for (p = 1; p < ctx->ga.PopSize; p++) {
392             eval = PGAGetEvaluation(ctx, p, pop);
393             if (eval > Best_eval) {
394                 Best_indx = p;
395                 Best_eval = eval;
396             }
397         }
398         break;
399     case PGA_MINIMIZE :
400         for (p = 1; p < ctx->ga.PopSize; p++) {
401             eval = PGAGetEvaluation(ctx, p, pop);
402             if (eval < Best_eval) {
403                 Best_indx = p;
404                 Best_eval = eval;
405             }
406         }
407         break;
408     }
409     
410    PGADebugExited("PGAGetBestIndex");
411
412     return (Best_indx);
413}
414
415
416/*I****************************************************************************
417  PGAGetIndividual - translate string index and population symbolic constant
418  into pointer to an individual
419
420  Inputs:
421     ctx - context variable
422     p   - string index
423     pop - symbolic constant of the population the string is in
424
425  Outputs:
426     Address of the PGAIndividual structure for string p in population pop
427
428  Example:
429    PGAIndividual *source;
430    PGAContext *ctx;
431    int p;
432    :
433    source = PGAGetIndividual ( ctx, p, PGA_NEWPOP );
434
435****************************************************************************I*/
436PGAIndividual *PGAGetIndividual ( PGAContext *ctx, int p, int pop)
437{
438    PGAIndividual *ind;
439
440    PGADebugEntered("PGAGetIndividual");
441
442#ifdef OPTIMIZE
443    ind = (pop == PGA_OLDPOP) ? ctx->ga.oldpop : ctx->ga.newpop;
444
445    if (p>=0)
446      ind += p;
447    else
448      ind += (p == PGA_TEMP1) ? ctx->ga.PopSize : ctx->ga.PopSize+1;
449#else
450    if (pop == PGA_OLDPOP)
451      ind = ctx->ga.oldpop;
452    else
453      if (pop == PGA_NEWPOP)
454        ind = ctx->ga.newpop;
455      else
456        PGAError(ctx, "PGAGetIndividual: Invalid value of pop:",
457                 PGA_FATAL, PGA_INT, (void *) &pop );
458
459    if (p>0 && p<ctx->ga.PopSize)
460      ind += p;
461    else
462      if (p == PGA_TEMP1)
463        ind += ctx->ga.PopSize;
464      else
465        if (p == PGA_TEMP2)
466          ind += ctx->ga.PopSize + 1;
467        else
468          PGAError(ctx, "PGAGetIndividual: Invalid value of p:",
469                   PGA_FATAL, PGA_INT, (void *) &p );
470#endif
471
472    PGADebugExited("PGAGetIndividual");
473
474    return(ind);
475}
476
477
478/*I****************************************************************************
479   PGAUpdateAverage - Updates the average fitness statistic for reporting.
480
481   Inputs:
482       ctx - context variable
483       pop - symbolic constant of the population
484
485   Outputs:
486
487   Example:
488
489**************************************************************************I*/
490void PGAUpdateAverage(PGAContext *ctx, int pop)
491{
492    double ThisGensTotal = 0;
493    int p;
494
495    PGADebugEntered("PGAUpdateAverage");
496   
497    for (p = 0; p < ctx->ga.PopSize; p++)
498        if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop))
499            PGAError(ctx, "PGAUpdateOnline: Evaluate function not up to "
500                     "date:", PGA_FATAL, PGA_INT, (void *) &p);
501
502    for (p = 0; p < ctx->ga.PopSize; p++)
503        ThisGensTotal += PGAGetEvaluation(ctx, p, pop);
504   
505    ctx->rep.Average = ThisGensTotal / (double)ctx->ga.PopSize;
506   
507    PGADebugExited("PGAUpdateAverage");
508}
509
510
511/*I****************************************************************************
512  PGAUpdateOnline - Updates the online value based on the results in
513  the new generation
514
515  Inputs:
516     ctx - context variable
517     pop - symbolic constant of the population whose statistics to use
518
519  Outputs:
520     Updates an internal field in the context variable
521
522  Example:
523     PGAContext *ctx;
524     :
525     PGAUpdateOnline(ctx,PGA_NEWPOP);
526
527**************************************************************************I*/
528void PGAUpdateOnline(PGAContext *ctx, int pop)
529{
530     double ThisGensTotal = 0;
531     int p;
532
533    PGADebugEntered("PGAUpdateOnline");
534
535     for (p = 0; p < ctx->ga.PopSize; p++)
536          if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop))
537               PGAError(ctx, "PGAUpdateOnline: Evaluate function not up to "
538                        "date:", PGA_FATAL, PGA_INT, (void *) &p);
539
540     for (p = 0; p < ctx->ga.PopSize; p++)
541          ThisGensTotal += PGAGetEvaluation(ctx, p, pop);
542
543     PGADebugPrint(ctx, PGA_DEBUG_PRINTVAR, "PGAUpdateOnline",
544                   "ThisGensTotal = ", PGA_DOUBLE, (void *) &ThisGensTotal);
545
546     ctx->rep.Online = (ctx->rep.Online * ctx->ga.PopSize * (ctx->ga.iter - 1)
547                        + ThisGensTotal) / ctx->ga.iter / ctx->ga.PopSize;
548
549    PGADebugExited("PGAUpdateOnline");
550
551}
552
553/*I****************************************************************************
554  PGAUpdateOffline - Updates the offline value based on the results in
555  the new generation
556
557  Inputs:
558     ctx - context variable
559     pop - symbolic constant of the population whose statistics to use
560
561  Outputs:
562     Updates an internal field in the context variable
563
564  Example:
565     PGAContext *ctx;
566     :
567     PGAUpdateOffline(ctx,PGA_NEWPOP);
568
569**************************************************************************I*/
570void PGAUpdateOffline(PGAContext *ctx, int pop)
571{
572     int p;
573
574    PGADebugEntered("PGAUpdateOffline");
575
576     for (p = 0; p < ctx->ga.PopSize; p++)
577          if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop))
578               PGAError(ctx, "PGAUpdateOffline: Evaluate function not up to "
579                        "date:", PGA_FATAL, PGA_INT, (void *) &p);
580
581     p = PGAGetBestIndex(ctx, pop);
582
583     ctx->rep.Offline = ((ctx->ga.iter - 1) * ctx->rep.Offline +
584                         PGAGetEvaluation(ctx, p, pop)) / ctx->ga.iter;
585
586    PGADebugExited("PGAUpdateOffline");
587}
588
589/*I****************************************************************************
590  PGAComputeSimilarity - computes the percentage of the population that have
591  the same evaluation function
592
593  Inputs:
594     ctx - context variable
595     pop - symbolic constant of the population whose statistics to use
596
597  Outputs:
598     returns a count of the number of  population members that have the same
599     evaluation function value
600
601  Example:
602     PGAContext *ctx;
603     :
604     PGAComputeSimilarity(ctx,PGA_NEWPOP);
605
606**************************************************************************I*/
607int PGAComputeSimilarity(PGAContext *ctx, PGAIndividual *pop)
608{
609     int max = 0, curr = 1, i;
610     double prev;
611
612    PGADebugEntered("PGAComputeSimilarity");
613
614     for(i=0; i < ctx->ga.PopSize; i++)
615     {
616          ctx->scratch.dblscratch[i] = (pop + i)->evalfunc;
617          ctx->scratch.intscratch[i] = i;
618     }
619
620     PGADblHeapSort(ctx, ctx->scratch.dblscratch, ctx->scratch.intscratch,
621                    ctx->ga.PopSize);
622
623     prev = ctx->scratch.dblscratch[0];
624
625     for(i = 1; i < ctx->ga.PopSize; i++)
626     {
627          if (ctx->scratch.dblscratch[i] == prev)
628               curr++;
629          else
630          {
631               if (curr > max)
632                    max = curr;
633               curr = 1;
634          }
635     }
636
637    PGADebugExited("PGAComputeSimilarity");
638
639     return(100 * max / ctx->ga.PopSize);
640}
Note: See TracBrowser for help on using the repository browser.