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

Last change on this file since 1271 was 1271, checked in by liveletlive, 15 years ago

Changes made to API and pgapack for addition of new stoppage criteria. TIMEElapsed criteria is not yet added.

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