source: trunk/packages/optimizer/src/pgapack/pgapack/source/parallel.c @ 1202

Last change on this file since 1202 was 1202, checked in by liveletlive, 14 years ago

Changes made to include the following items:
1) Hard restart
2) SBX
3) Random population replacement proportion
4) Definitions and macros for the above functions in pgapack.h

File size: 29.4 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: parallel.c: This file contains all the parallel functions
66*     Authors: David M. Levine, Philip L. Hallstrom, David M. Noelle,
67*              Brian P. Walenz
68******************************************************************************/
69
70#include "pgapack.h"
71#include <setjmp.h>
72
73extern jmp_buf pgapack_jmpbuf;
74extern int *pgapack_abortPtr;
75
76#define DEBUG_EVAL 0
77
78/*U****************************************************************************
79  PGARunGM - High-level routine to execute the genetic algorithm using the
80  global model.  It is called after PGACreate and PGASetup have been called.
81  If a NULL communicator is given, a sequential execution method is used,
82  otherwise, work is divided among the processors in the communicator.
83
84  Category: Generation
85
86  Inputs:
87    ctx      - context variable
88    evaluate - a pointer to the user's evaluation function, which must
89    have the calling sequence shown in the example.
90    comm     - an MPI communicator
91
92  Outputs:
93    none
94
95  Example:
96    PGAContext *ctx;
97    double f(PGAContext *ctx, int p, int pop);
98    :
99    PGARunGM(ctx, f, MPI_COMM_WORLD);
100
101****************************************************************************U*/
102void PGARunGM(PGAContext *ctx, double (*f)(PGAContext *, int, int),
103              MPI_Comm comm)
104{
105    int       rank, Restarted, best_p;
106    void    (*CreateNewGeneration)(PGAContext *, int, int);
107
108    /*  Let this be warned:
109     *  The communicator is NOT duplicated.  There might be problems with
110     *  PGAPack and the user program using the same communicator.
111     */
112    PGADebugEntered("PGARunGM");
113
114    rank = PGAGetRank(ctx, comm);
115
116    PGAEvaluate(ctx, PGA_OLDPOP, f, comm);
117       
118    if (rank == 0)
119        PGAFitness(ctx, PGA_OLDPOP);
120
121    if (PGAGetMutationOrCrossoverFlag(ctx))
122        CreateNewGeneration = PGARunMutationOrCrossover;
123    else
124        CreateNewGeneration = PGARunMutationAndCrossover;
125
126    while (!PGADone(ctx, comm)) {
127        if (rank == 0) {
128            Restarted = PGA_FALSE;
129            if (PGARestartCondition(ctx)) {
130                        Restarted = PGA_TRUE;
131                        PGARestart(ctx, PGA_OLDPOP, PGA_NEWPOP);
132            } else {
133                        PGASelect(ctx, PGA_OLDPOP);
134                        CreateNewGeneration(ctx, PGA_OLDPOP, PGA_NEWPOP);
135            }
136        }
137        MPI_Bcast(&Restarted, 1, MPI_INT, 0, comm);
138
139        PGAEvaluate(ctx, PGA_NEWPOP, f, comm);
140        if (rank == 0)
141            PGAFitness(ctx, PGA_NEWPOP);
142
143        /*  If the GA wasn't restarted, update the generation and print
144         *  stuff.  We do this because a restart is NOT counted as a
145         *  complete generation.
146         */
147        if (!Restarted) {
148            PGAUpdateGeneration(ctx, comm);
149            if (rank == 0)
150                PGAPrintReport(ctx, stdout, PGA_OLDPOP);
151        }
152    }
153
154    if (rank == 0) {
155        best_p = PGAGetBestIndex(ctx, PGA_OLDPOP);
156        printf("The Best Evaluation: %e.\n",
157               PGAGetEvaluation(ctx, best_p, PGA_OLDPOP));
158        printf("The Best String:\n");
159        PGAPrintString(ctx, stdout, best_p, PGA_OLDPOP);
160        fflush(stdout);
161    }
162    PGADebugExited("PGARunGM");
163}
164
165
166/*I****************************************************************************
167   PGAEvaluateSeq - Internal evalution function.  Evaluates all strings
168   that need to be evaluated using one processor.
169
170   Category: Fitness & Evaluation
171
172   Inputs:
173      ctx  - context variable
174      pop  - symbolic constant of the population to be evaluated
175      f    - a pointer to a function to evaluate a string.
176
177   Outputs:
178
179   Example:
180
181****************************************************************************I*/
182void PGAEvaluateSeq(PGAContext *ctx, int pop,
183                    double (*f)(PGAContext *, int, int))
184{
185    int     p;
186    double  e;
187
188    PGADebugEntered("PGAEvaluateSeq");
189
190    /*  Standard sequential evaluation.  */
191    if (ctx->sys.UserFortran == PGA_TRUE) {
192        for (p=1; p<=ctx->ga.PopSize; p++)
193            if (!PGAGetEvaluationUpToDateFlag(ctx, p-1, pop)) {
194                e = (*((double(*)(void *, void *, void *))f))(&ctx, &p, &pop);
195                PGASetEvaluation (ctx, p-1, pop, e);
196            }
197    } else {
198        for (p=0; p<ctx->ga.PopSize; p++) {
199            if ((pgapack_abortPtr != NULL) && (*pgapack_abortPtr == 1)) {
200                longjmp(pgapack_jmpbuf, 1);
201            }
202            if (!PGAGetEvaluationUpToDateFlag(ctx, p, pop)) {
203                e = (*f)(ctx, p, pop);
204                PGASetEvaluation(ctx, p, pop, e);
205            }
206        }
207    }
208    PGADebugExited("PGAEvaluateSeq");
209}
210
211
212/*I****************************************************************************
213   PGAEvaluateCoop - Internal evaluation function.  Evaluates all strings
214   that need to be evaluated using two processors cooperatively.  The first
215   is treated as a master, it will send a string to the second for evaluation.
216   While the second is evaluating, the master will _also_ evaluate a string.
217
218   Category: Fitness & Evaluation
219
220   Inputs:
221      ctx  - context variable
222      pop  - symbolic constant of the population to be evaluated
223      f    - a pointer to a function to evaluate a string.
224      comm - an MPI communicator
225
226   Outputs:
227
228   Example:
229
230****************************************************************************I*/
231void PGAEvaluateCoop(PGAContext *ctx, int pop,
232                     double (*f)(PGAContext *, int, int), MPI_Comm comm)
233{
234    MPI_Status      stat;
235    int             p, fp, q;
236    double          e;
237    PGAIndividual  *ind;
238
239    PGADebugEntered("PGAEvaluateCoop");
240
241    q = -1;
242
243    ind = PGAGetIndividual(ctx, 0, pop);
244   
245    for (p=0; p<ctx->ga.PopSize;) {
246        while ((p<ctx->ga.PopSize) && (ind+p)->evaluptodate)  p++;
247        if (p<ctx->ga.PopSize) {
248            PGASendIndividual(ctx, p, pop, 1, PGA_COMM_STRINGTOEVAL, comm);
249            q = p;
250        }
251        p++;
252       
253        while ((p<ctx->ga.PopSize) && (ind+p)->evaluptodate)  p++;
254        if (p<ctx->ga.PopSize) {
255            if (ctx->sys.UserFortran == PGA_TRUE) {
256                fp = p+1;
257                e = (*((double(*)(void *, void *, void *))f))(&ctx, &fp, &pop);
258            } else {
259                e = (*f)(ctx, p, pop);
260            }
261            PGASetEvaluation(ctx, p, pop, e);
262#if DEBUG_EVAL
263            printf("%4d: %10.8e Local\n", p, e); fflush(stdout);
264#endif
265        }
266       
267        if (q >= 0) {
268            MPI_Recv(&e, 1, MPI_DOUBLE, 1, PGA_COMM_EVALOFSTRING, comm, &stat);
269            PGASetEvaluation(ctx, q, pop, e);
270#if DEBUG_EVAL
271            printf("%4d: %10.8e Slave %d\n", p, e, 1); fflush(stdout);
272#endif
273            q = -1;
274        }
275    }   
276   
277    /*  Release the slave  */
278    MPI_Send(&q, 1, MPI_INT, 1, PGA_COMM_DONEWITHEVALS, comm);
279
280    PGADebugExited("PGAEvaluateCoop");
281}
282
283
284
285/*I****************************************************************************
286   PGAEvaluateMS - Internal evaluation function.  Evaluates all strings
287   that need evaluating using three or more processors.  Operates in a
288   standard master-slave execution method.
289
290   Category: Fitness & Evaluation
291
292   Inputs:
293      ctx  - context variable
294      pop  - symbolic constant of the population to be evaluated
295      f    - a pointer to a function to evaluate a string.
296      comm - an MPI communicator
297
298   Outputs:
299
300   Example:
301
302****************************************************************************I*/
303void PGAEvaluateMS(PGAContext *ctx, int pop,
304                   double (*f)(PGAContext *c, int p, int pop), MPI_Comm comm)
305{
306    int    *work;
307    int     i, k, s, p, size, sentout;
308    double  e;
309    MPI_Status stat;
310    PGAIndividual *ind;
311
312    PGADebugEntered("PGAEvaluateMS");
313
314    size = PGAGetNumProcs(ctx, comm);
315
316    work = (int *)malloc(size *sizeof(int));
317    if (work == NULL) {
318        PGAError(ctx, "PGAEvaluateMS:  Couldn't allocate work array",
319                 PGA_FATAL, PGA_VOID, NULL);
320    }
321   
322    sentout = 0;
323    s = 1;
324    ind = PGAGetIndividual(ctx, 0, pop);
325   
326    /*  Send strings to all processes, since they are all unused.  */
327    for (k=0; ((k<ctx->ga.PopSize) && (s<size)); k++) {
328        if ((ind+k)->evaluptodate == PGA_FALSE) {
329            work[s] = k;
330            PGASendIndividual(ctx, k, pop, s, PGA_COMM_STRINGTOEVAL, comm);
331#if DEBUG_EVAL
332            printf("%4d: Sent to slave %d.\n", k, s); fflush(stdout);
333#endif
334            sentout++;
335            s++;
336        }
337    }
338   
339    /*  Move to the next string to be evaluated.  Notice that all we need
340     *  to do is skip any strings that are already evaluated, unlike
341     *  below, where we need to _first_ go to the next string, then
342     *  skip any that are up to date.
343     */
344    while ((k<ctx->ga.PopSize) && (ind+k)->evaluptodate)  k++;
345   
346    /*  While there are still unevaluated individuals, receive whatever
347     *  is waiting, then immediately send a new string to it.  This
348     *  implicitly will balance the load across the machines, as we
349     *  initially sent a string to _each_ process, so _each_ process
350     *  will return an evaluation and get a new one immediately.
351     */
352    while(k<ctx->ga.PopSize) {
353        /*  Receive the next evaluated string.  */
354        MPI_Recv(&e, 1, MPI_DOUBLE, MPI_ANY_SOURCE, PGA_COMM_EVALOFSTRING,
355                 comm, &stat);
356        p = work[stat.MPI_SOURCE];
357        PGASetEvaluation(ctx, p, pop, e);
358       
359#if DEBUG_EVAL
360        printf("%4d: %10.8e Slave %d  Sent %d\n", work[stat.MPI_SOURCE],
361               e, stat.MPI_SOURCE, k); fflush(stdout);
362#endif
363       
364        /*  Immediately send another string to be evaluated.  */
365        work[stat.MPI_SOURCE] = k;
366        PGASendIndividual(ctx, k, pop, stat.MPI_SOURCE,
367                          PGA_COMM_STRINGTOEVAL, comm);
368       
369        /*  Find the next unevaluated individual  */
370        k++;
371        while ((k<ctx->ga.PopSize) && (ind+k)->evaluptodate)  k++;
372    }
373   
374    /*  All strings have been sent out.  Wait for them to be done.  */
375    while(sentout > 0) {
376        MPI_Recv(&e, 1, MPI_DOUBLE, MPI_ANY_SOURCE, PGA_COMM_EVALOFSTRING,
377                 comm, &stat);
378        p = work[stat.MPI_SOURCE];
379        PGASetEvaluation(ctx, p, pop, e);
380        sentout--;
381#if DEBUG_EVAL
382        printf("%4d: %10.8e Slave %d\n",
383               work[stat.MPI_SOURCE], e, stat.MPI_SOURCE); fflush(stdout);
384#endif
385    }
386    free(work);
387   
388    /*  Release the slaves.  */
389    for (i=1; i<size; i++)
390        MPI_Send(&i, 1, MPI_INT, i, PGA_COMM_DONEWITHEVALS, comm);
391
392    PGADebugExited("PGAEvaluateMS");
393}
394
395
396/*I****************************************************************************
397   PGAEvaluateSlave - Slave execution routine.  Sit around and wait for a
398   string to eval to show up, then evaluate it and return the evaluation.
399   Terminates when it receives PGA_COMM_DONEWITHEVALS.
400
401   Category: Fitness & Evaluation
402
403   Inputs:
404
405   Outputs:
406
407   Example:
408
409****************************************************************************I*/
410void PGAEvaluateSlave(PGAContext *ctx, int pop,
411                      double (*f)(PGAContext *, int, int), MPI_Comm comm)
412{
413    MPI_Status  stat;
414    int         k;
415    double      e;
416
417    PGADebugEntered("PGAEvaluateSlave");
418
419    k = PGA_TEMP1;
420    MPI_Probe(0, MPI_ANY_TAG, comm, &stat);
421    while (stat.MPI_TAG == PGA_COMM_STRINGTOEVAL) {
422        PGAReceiveIndividual(ctx, PGA_TEMP1, pop, 0, PGA_COMM_STRINGTOEVAL,
423                             comm, &stat);
424
425        if (ctx->sys.UserFortran == PGA_TRUE)
426            e = (*((double(*)(void *, void *, void *))f))(&ctx, &k, &pop);
427        else
428            e = (*f)(ctx, PGA_TEMP1, pop);
429
430        MPI_Send(&e, 1, MPI_DOUBLE, 0, PGA_COMM_EVALOFSTRING, comm);
431        MPI_Probe(0, MPI_ANY_TAG, comm, &stat);
432    }
433    MPI_Recv(&k, 1, MPI_INT, 0, PGA_COMM_DONEWITHEVALS, comm, &stat);
434
435    PGADebugExited("PGAEvaluateSlave");
436}
437
438
439/*U****************************************************************************
440   PGAEvaluate - Calls a user-specified function to return an evaluation of
441   each string in the population. The user-specified function is only called
442   if the string has been changed (e.g., by crossover or mutation) or the user
443   has explicitly signaled the string's evaluation is out-of-date by a call
444   to PGASetEvaluationUpToDateFlag().
445
446   Category: Fitness & Evaluation
447
448   Inputs:
449      ctx  - context variable
450      pop  - symbolic constant of the population to be evaluated
451      f    - a pointer to a function to evaluate a string.  This function will
452             be called once for each string in population pop that requires
453             evaluation.  This function must return a double (the evaluation
454             function value) and must fit the prototype
455                 double f(PGAContext *c, int p, int pop);
456      comm - an MPI communicator
457
458   Outputs:
459      Evaluates the population via side effect
460
461   Example:
462      Evaluate all strings in population PGA_NEWPOP using the user-defined
463      evaluation function Energy.
464
465      double Energy(PGAContext *ctx, int p, int pop) {
466        :
467      };
468
469      PGAContext *ctx;
470      :
471      PGAEvaluate(ctx, PGA_NEWPOP, Energy, MPI_COMM_WORLD);
472
473****************************************************************************U*/
474void PGAEvaluate(PGAContext *ctx, int pop,
475                 double (*f)(PGAContext *, int, int), MPI_Comm comm)
476{
477    int  rank, size;
478
479    PGADebugEntered("PGAEvaluate");
480
481    rank = PGAGetRank(ctx, comm);
482    size = PGAGetNumProcs(ctx, comm);
483
484    if (rank == 0) {
485        if (size == 1)
486            PGAEvaluateSeq(ctx, pop, f);
487        if (size == 2)
488            PGAEvaluateCoop(ctx, pop, f, comm);
489        if (size > 2)
490            PGAEvaluateMS(ctx, pop, f, comm);
491    } else {
492        PGAEvaluateSlave(ctx, pop, f, comm);
493    }
494    PGADebugExited("PGAEvaluate");
495}
496
497
498/*U****************************************************************************
499  PGABuildDatatype - Build an MPI datatype for string p in population pop.
500
501  Category: Parallel
502
503  Inputs:
504    ctx     - context variable
505    p       - index of an individual
506    pop     - symbolic constant of the population
507
508  Outputs:
509    An MPI datatype for member p of population pop.
510
511  Example:
512    PGAContext *ctx;
513    int p;
514    MPI_Datatype dt;
515    :
516    dt = PGABuildDatatype(ctx, p, PGA_NEWPOP);
517
518****************************************************************************U*/
519MPI_Datatype PGABuildDatatype(PGAContext *ctx, int p, int pop)
520{
521    PGADebugEntered("PGABuildDatatype");
522   
523    PGADebugExited("PGABuildDatatype");
524
525    return((*ctx->cops.BuildDatatype)(ctx, p, pop));
526}
527
528
529/*U****************************************************************************
530  PGASendIndividual - transmit an individual to another process
531
532  Category: Parallel
533
534  Inputs:
535    ctx  - context variable
536    p    - index of an individual
537    pop  - symbolic constant of the population
538    dest - ID of the process where this is going
539    tag  - MPI tag to send with the individual
540    comm - MPI communicator
541
542  Outputs:
543
544  Example:
545    PGAContext *ctx;
546    int p, dest;
547    :
548    dest = SelectAFreeProcessor();
549    PGASendIndividual(ctx, p, PGA_NEWPOP, dest, PGA_SR_STRINGTOEVAL, comm);
550
551****************************************************************************U*/
552void PGASendIndividual(PGAContext *ctx, int p, int pop, int dest, int tag,
553                       MPI_Comm comm)
554{
555    MPI_Datatype individualtype;
556
557    PGADebugEntered("PGASendIndividual");
558
559    individualtype = PGABuildDatatype(ctx, p, pop);
560    MPI_Send(MPI_BOTTOM, 1, individualtype, dest, tag, comm);
561    MPI_Type_free(&individualtype);
562   
563    PGADebugExited("PGASendIndividual");
564}
565
566/*U****************************************************************************
567  PGAReceiveIndividual - receive an individual from another process
568
569  Category: Parallel
570
571  Inputs:
572    ctx    - contex variable
573    p      - index of an individual
574    pop    - symbolic constant of the population
575    source - ID of the process from which to receive
576    tag    - MPI tag to look for
577    status - pointer to an MPI status structure
578
579  Outputs:
580    status and string p in population pop are changed by side-effect.
581
582  Example:
583    Receive a string from the master process (rank == 0) with tag
584    PGA_SR_STRINGTOEVAL, and place it into the first temporary location
585    in PGA_NEWPOP.
586
587    PGAContext *ctx;
588    MPI_Comm    comm;
589    MPI_Status  status;
590    :
591    PGAReceiveIndividual(ctx, PGA_TEMP1, PGA_NEWPOP, 0, PGA_SR_STRINGTOEVAL,
592                         comm, &status);
593
594****************************************************************************U*/
595void PGAReceiveIndividual(PGAContext *ctx, int p, int pop, int source, int tag,
596                          MPI_Comm comm, MPI_Status *status)
597{
598     MPI_Datatype individualtype;
599
600    PGADebugEntered("PGAReceiveIndividual");
601
602     individualtype = PGABuildDatatype(ctx, p, pop);
603     MPI_Recv(MPI_BOTTOM, 1, individualtype, source, tag, comm, status);
604     MPI_Type_free(&individualtype);
605
606    PGADebugExited("PGAReceiveIndividual");
607}
608
609/*U****************************************************************************
610  PGASendReceiveIndividual - Send an individual to a process, while receiving
611  a different individual from a different process.
612
613  Category: Parallel
614
615  Inputs:
616    ctx       - context variable
617    send_p    - index of string to send
618    send_pop  - symbolic constant of population to send from
619    dest      - destination process
620    send_tag  - tag to send with
621    recv_p    - index of string to receive
622    recv_pop  - symbolic constant of population to receive from
623    source    - process to receive from
624    recv_tag  - tag to receive with
625    comm      - an MPI communicator
626    status    - pointer to the MPI status structure
627
628  Outputs:
629    status and string recv_p in population recv_pop are modified by
630    side-effect.
631
632  Example:
633    A dedicated process is being used to perform an optimization algorithm
634    on the strings.  Send a new string, s, to the process, while receiving an
635    optimized string, r, from it.
636
637    PGAContext *ctx;
638    MPI_Comm    comm;
639    MPI_Status  status;
640    int  s, r;
641    :
642    PGASendReceiveIndividual(ctx, s, PGA_NEWPOP, 1, PGA_SR_STRINGTOMODIFY,
643                                  r, PGA_NEWPOP, 1, PGA_SR_MODIFIEDSTRING,
644                                  comm, &status);
645
646****************************************************************************U*/
647void PGASendReceiveIndividual(PGAContext *ctx, int send_p, int send_pop,
648                              int dest, int send_tag, int recv_p, int recv_pop,
649                              int source, int recv_tag, MPI_Comm comm,
650                              MPI_Status *status)
651{
652     MPI_Datatype individualsendtype;
653     MPI_Datatype individualrecvtype;
654
655    PGADebugEntered("PGASendReceiveIndividual");
656
657     individualsendtype = PGABuildDatatype(ctx, send_p, send_pop);
658     individualrecvtype = PGABuildDatatype(ctx, recv_p, recv_pop);
659
660     MPI_Sendrecv(MPI_BOTTOM, 1, individualsendtype, dest,   send_tag,
661                  MPI_BOTTOM, 1, individualrecvtype, source, recv_tag,
662                  comm, status);
663
664     MPI_Type_free(&individualsendtype);
665     MPI_Type_free(&individualrecvtype);
666
667    PGADebugExited("PGASendReceiveIndividual");
668}
669
670
671/*I****************************************************************************
672  PGARunIM - Execute the island model genetic algorithm
673
674  Category: Parallel
675
676  Inputs:
677    ctx      - context variable
678    evaluate - a pointer to the user's evaluation function, which must
679               have the calling sequence shown in the example.
680    comm     - the MPI communicator to use
681
682  Outputs:
683    none
684
685  Example:
686    PGAContext *ctx,
687    double f(PGAContext *ctx, int p, int pop);
688    MPI_Comm comm;
689    :
690    PGARunIM(ctx, f, comm);
691
692****************************************************************************I*/
693void PGARunIM(PGAContext *ctx, double (*f)(PGAContext *c, int p, int pop),
694              MPI_Comm tcomm)
695{
696    /* Based on ctx->par.topology this routine will need to create the
697       appropriate communicator out of tcomm
698    */
699   
700     PGADebugEntered("PGARunIM");
701     PGAError (ctx, "PGARunIM: Island model not implemented",
702               PGA_FATAL, PGA_VOID, NULL);
703     PGADebugExited("PGARunIM");
704}
705
706
707/*I****************************************************************************
708  PGARunNM - Execute a neighborhood model genetic algorithm
709
710  Category: Parallel
711
712  Inputs:
713    ctx      - context variable
714    evaluate - a pointer to the user's evaluation function, which must
715               have the calling sequence shown in the example.
716    comm     - the MPI communicator to use
717
718  Outputs:
719    none
720
721  Example:
722    PGAContext *ctx,
723    MPI_Comm comm;
724    double f(PGAContext *ctx, int p, int pop);
725    :
726    PGARunNM(ctx, f, comm);
727
728****************************************************************************I*/
729void PGARunNM(PGAContext *ctx, double (*f)(PGAContext *c, int p, int pop),
730              MPI_Comm tcomm)
731{
732    /* Based on ctx->par.topology this routine will need to create the
733       appropriate communicator out of tcomm
734    */
735     PGADebugEntered("PGARunNM");
736     PGAError (ctx, "PGARunNM: Island model not implemented",
737               PGA_FATAL, PGA_VOID, NULL);
738     PGADebugExited("PGARunNM");
739}
740
741
742
743/*U****************************************************************************
744  PGAGetRank - Returns the rank of the processor in communicator comm.  If
745  comm is NULL or a sequential version of PGAPack is used, PGAGetRank()
746  returns 0.
747
748  Category: Parallel
749
750  Inputs:
751      ctx  - context variable structure pointer
752      comm - an MPI communicator
753
754  Outputs:
755      The rank of this processor
756
757  Example:
758      PGAContext  *ctx;
759      int          rank;
760      :
761      rank = PGAGetRank(ctx, MPI_COMM_WORLD);
762      if (rank == 0) {
763          LetTheMasterDoSomething();
764      }
765
766****************************************************************************U*/
767int PGAGetRank (PGAContext *ctx, MPI_Comm comm)
768{
769    int rank;
770   
771    PGADebugEntered("PGAGetRank");
772
773    if (comm == NULL)
774        rank = 0;
775    else
776        MPI_Comm_rank(comm, &rank);
777   
778    PGADebugExited("PGAGetRank");
779   
780    return(rank);
781}
782
783
784/*U****************************************************************************
785  PGAGetNumProcs - Returns the size of communicator comm in processes.  If
786  comm is NULL or a sequential version of PGAPack is used, PGAGetNumProcs()
787  returns 1.
788
789  Category: Parallel
790
791  Inputs:
792      ctx  - context variable structure pointer
793      comm - an MPI communicator
794
795  Outputs:
796      The numbers of processors in communicator comm.
797
798  Example:
799      PGAContext  *ctx;
800      :
801      if (PGAGetNumProcs(ctx, MPI_COMM_WORLD) < 4) {
802          printf("Too few processors for decent performance!\n");
803          exit(-1);
804      }
805
806****************************************************************************U*/
807int PGAGetNumProcs (PGAContext *ctx, MPI_Comm comm)
808{
809    int size;
810
811    PGADebugEntered("PGAGetNumProcs");
812
813    if (comm == NULL)
814        size = 1;
815    else
816        MPI_Comm_size(comm, &size);
817
818    PGADebugExited("PGAGetNumProcs");
819
820    return(size);
821}
822
823
824/*I****************************************************************************
825   PGASetNumIslands - Set the number of islands to use in an island model
826   GA. The default is one.  Currently must be the same as the number of
827   processes in the default communicator. 
828
829   Category: Parallel
830
831   Inputs:
832      ctx - context variable
833      n   - number of islands
834
835   Outputs:
836      None
837
838   Example:
839      PGAContext *ctx,
840      double f(PGAContext *ctx, int p, int pop);
841      :
842      ctx = PGACreate(&argc, argv, PGA_DATATYPE_BINARY, 100, PGA_MAXIMIZE);
843      PGASetNumIslands(ctx, 10);
844      PGASetUp(ctx);
845      PGARun(ctx, f);
846      PGADestroy(ctx);
847
848****************************************************************************I*/
849void PGASetNumIslands( PGAContext *ctx, int n)
850{
851
852    PGADebugEntered("PGASetNumIslands");
853
854    if ( n < 1 )
855        PGAError(ctx, "PGASetNumIslands: Invalid value of n:",
856                 PGA_FATAL, PGA_INT, (void *) &n);
857
858    ctx->par.NumIslands = n;
859
860    PGADebugExited("PGASetNumIslands");
861}
862
863
864/*I***************************************************************************
865   PGAGetNumIslands - Returns the number of islands to use in an island model
866
867   Category: Parallel
868
869   Inputs:
870      ctx - context variable
871
872   Outputs:
873       the number of islands to use in an island model
874
875   Example:
876      PGAContext *ctx;
877      int npop;
878      :
879      npop = PGAGetNumIslands(ctx);
880
881***************************************************************************I*/
882int PGAGetNumIslands (PGAContext *ctx)
883{
884    PGADebugEntered("PGAGetNumIslands");
885    PGAFailIfNotSetUp("PGAGetNumIslands");
886
887    PGADebugExited("PGAGetNumIslands");
888
889    return(ctx->par.NumIslands);
890}
891
892/*I****************************************************************************
893   PGASetNumDemes - Set the number of demes to use in a neighborhood model
894   GA. Currently must be the same as the number of processes in the default
895   communicator.  The default is one.
896
897   Category: Parallel
898
899   Inputs:
900      ctx          - context variable
901      numdemes     - number of demes
902
903   Outputs:
904      None
905
906   Example:
907      PGAContext *ctx,
908      double f(PGAContext *ctx, int p, int pop);
909      :
910      ctx = PGACreate(&argc, argv, PGA_DATATYPE_BINARY, 100, PGA_MAXIMIZE);
911      PGASetNumDemes(ctx, 4);
912      PGASetUp(ctx);
913      PGARun(ctx, f);
914      PGADestroy(ctx);
915
916****************************************************************************I*/
917void PGASetNumDemes( PGAContext *ctx, int numdemes)
918{
919    PGADebugEntered("PGASetNumDemes");
920
921    if ( numdemes < 1 )
922        PGAError(ctx, "PGASetNumDemes: Invalid value of numdemes:",
923                 PGA_FATAL, PGA_INT, (void *) &numdemes);
924
925    ctx->par.NumDemes = numdemes;
926
927    PGADebugExited("PGASetNumDemes");
928}
929
930
931/*I***************************************************************************
932   PGAGetNumDemes - Returns the number of demes to use in a neighborhood model
933
934   Category: Parallel
935
936   Inputs:
937      ctx - context variable
938
939   Outputs:
940       the number of demes to use in a neighborhood model
941
942   Example:
943      PGAContext *ctx;
944      int npop;
945      :
946      npop = PGAGetNumDemes(ctx);
947
948***************************************************************************I*/
949int PGAGetNumDemes (PGAContext *ctx)
950{
951    PGADebugEntered("PGAGetNumDemes");
952    PGAFailIfNotSetUp("PGAGetNumDemes");
953
954    PGADebugExited("PGAGetNumDemes");
955
956    return(ctx->par.NumDemes);
957}
958
959
960/*U****************************************************************************
961   PGASetCommunicator - Set the default communicator to use when PGARun is
962   called.  Does not necessarily need to be the same as the number of
963   processes in MPI_COMM_WORLD (which is the default).
964
965   Category: Parallel
966
967   Inputs:
968      ctx    - context variable
969      comm   - communicator to use
970
971   Outputs:
972      None
973
974   Example:
975      MPI_Comm mycomm;
976      PGAContext *ctx,
977      double f(PGAContext *ctx, int p, int pop);
978      :
979      ctx = PGACreate(&argc, argv, PGA_DATATYPE_BINARY, 100, PGA_MAXIMIZE);
980      PGASetCommunicator(ctx, mycomm);
981      PGASetUp(ctx);
982      PGARun(ctx, f);
983      PGADestroy(ctx);
984
985****************************************************************************U*/
986void PGASetCommunicator( PGAContext *ctx, MPI_Comm comm)
987{
988
989    PGADebugEntered("PGASetCommunicator");
990
991    ctx->par.DefaultComm = comm;
992
993    PGADebugExited("PGASetCommunicator");
994}
995
996
997/*U****************************************************************************
998   PGAGetCommunicator - Returns the default communicator used when PGARun is
999   called.
1000   
1001   Category: Parallel
1002
1003   Inputs:
1004      ctx    - context variable
1005
1006   Outputs:
1007      The default communicator
1008
1009   Example:
1010      MPI_Comm comm;
1011      PGAContext *ctx,
1012      double f(PGAContext *ctx, int p, int pop);
1013      :
1014      ctx = PGACreate(&argc, argv, PGA_DATATYPE_BINARY, 100, PGA_MAXIMIZE);
1015      PGASetUp(ctx);
1016      comm = PGAGetCommunicator(ctx);
1017
1018
1019****************************************************************************U*/
1020MPI_Comm PGAGetCommunicator( PGAContext *ctx)
1021{
1022
1023    PGADebugEntered("PGAGetCommunicator");
1024
1025    PGADebugExited("PGAGetCommunicator");
1026
1027    return(ctx->par.DefaultComm);
1028}
Note: See TracBrowser for help on using the repository browser.