source: trunk/optimizer/src/pgapack/pgapack/source/parallel.c @ 986

Last change on this file since 986 was 986, checked in by gah, 15 years ago

added global pgapack_abort flag to plugin and abort operation to optimizer

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