int RemoteSubtreeWorker(Population& pop, const GeneralGamlConfig& conf){ int *which, size, rank, tag; char *tree_strings, *buf; double score, *models; bool perturb; which=new int[5]; MPI_Comm_rank(MPI_COMM_WORLD, &rank); pop.CalcAverageFitness(); int lastSend=g_sw->SplitTime(); cout << "Remote number " << rank << " running..." << endl; for (pop.gen = 1; pop.gen < conf.stopgen;){ pop.keepTrack(); pop.OutputFate(); if (pop.gen % conf.logevery == 0) pop.OutputLog(); ++pop.gen; pop.NextGeneration(); if(g_sw->SplitTime() - lastSend > conf.sendInterval){ debug_mpi("SYNCH COMM (node 0)"); //send our best individual to the master RemoteSendBestTree(pop); lastSend=g_sw->SplitTime(); if(pop.params->stoptime - g_sw->SplitTime() < 0){ debug_mpi("time limit of %d seconds reached...", pop.params->stoptime); break; } } //Check for a new tree from the master bool firstmessage=true; bool gotmessage=false; int subtreeNode; while(RecvMPIMessage(&tree_strings, &size, 0, &tag, false)==true){ //check for a quit message if(tag == TAG_QUIT) { debug_mpi("\trecv: quit message"); delete [] which; debug_mpi("quitting"); return 0; } // bool gotNewIndiv=false; int recievedDefNumber; debug_mpi("SYNCH COMM (node 0)"); gotmessage=true; assert(tag == TAG_TREE_STRINGS || tag==TAG_PERTURB); if(firstmessage==false) debug_mpi("\tfound a newer message..."); if(tag != TAG_PERTURB){ gotNewIndiv=true; RecvMPIMessage(&buf, &size, 0, &tag, true); assert(tag == TAG_MODEL); models=(double*) buf; debug_mpi("\tgot new ind" ); RecvMPIMessage(&buf, &size, 0, &tag, true); // if(tag != TAG_PERTURB){ perturb=false; assert(tag == TAG_SUBTREE_DEFINE); subtreeNode=atoi(buf); if(subtreeNode!=0){ delete []buf; RecvMPIMessage(&buf, &size, 0, &tag, true); assert(tag == TAG_SUBTREE_ITERATION); recievedDefNumber=atoi(buf); debug_mpi("\tworking on subtree def %d, node %d", recievedDefNumber, subtreeNode); } else recievedDefNumber=0; } else{ pop.pertMan->pertType=atoi(tree_strings); perturb=true; } //if the current best and the new tree are either both accurate for the same subtree def or both //inaccurate for subtrees, just replace the worst individual, rather than the // whole pop, that way if the tree is old and worse that what the remote // already has it won't matter if(gotNewIndiv){ *which=(int)pop.cumfit[0][0]; debug_mpi("\treplacing indiv %d", *which); pop.ReplaceSpecifiedIndividuals(1, which, tree_strings, models); if(recievedDefNumber!=pop.subtreeDefNumber || (pop.subtreeNode!=0 && subtreeNode!=0)){ pop.AssignSubtree(subtreeNode, *which); pop.CalcAverageFitness(); debug_mpi("\tfilling pop with clones of %d", *which); pop.SetNewBestIndiv(*which); pop.FillPopWithClonesOfBest(); pop.subtreeDefNumber=recievedDefNumber; } delete [] models; delete [] buf; } #ifdef INCLUDE_PERTURBATION if(perturb==true){ pop.CalcAverageFitness(); if(pop.pertMan->pertType==1){ debug_mpi("peforming NNI perturbation..."); int toReplace=(pop.bestIndiv == 0 ? 1 : 0); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); pop.NNIPerturbation(pop.bestIndiv, toReplace); pop.SetNewBestIndiv(toReplace); pop.FillPopWithClonesOfBest(); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); } else if(pop.pertMan->pertType==2){ debug_mpi("peforming SPR perturbation..."); int toReplace=(pop.bestIndiv == 0 ? 1 : 0); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); pop.SPRPerturbation(pop.bestIndiv, toReplace); pop.SetNewBestIndiv(toReplace); pop.FillPopWithClonesOfBest(); pop.AppendTreeToTreeLog(-1, pop.bestIndiv); } else assert(0); } #endif delete [] tree_strings; tag=0; firstmessage=false; } if(gotmessage==true){ // if(pop.subtreeNode != subtreeNode) pop.AssignSubtree(subtreeNode); pop.CalcAverageFitness(); debug_mpi("\tbest score= %f", pop.indiv[*which].Fitness()); //DEBUG //pop.AppendTreeToTreeLog(rank, -1, *which); } } SendMPIMessage(NULL, 0, 0, TAG_QUIT); debug_mpi("\tsent: quit message"); delete [] which; debug_mpi("quitting"); return 0; }