Пример #1
0
 public virtual void EvalRoundRobin(
     IEvolutionState state,
     int[] origins,
     int[] numinds,
     IList <Individual> individuals,
     int subpop,
     IGroupedProblem prob)
 {
     if (state.EvalThreads == 1)
     {
         EvalRoundRobinPopChunk(
             state, origins[0], numinds[0], 0, individuals, subpop, prob);
     }
     else
     {
         ParallelEvaluation <RoundRobinCompetitiveEvaluatorThread>(
             state, origins, numinds, individuals, subpop, prob);
     }
 }
Пример #2
0
        void ParallelEvaluation <TEvalThread>(
            IEvolutionState state,
            int[] origins,
            int[] numinds,
            IList <Individual> individuals,
            int subpop,
            IGroupedProblem prob)
            where TEvalThread : CompetitiveEvaluatorThread, new()
        {
            // BRS: TPL DataFlow is cleaner and safer than using raw threads.

            // Limit the concurrency in case the user has gone overboard!
            var maxDegree = Math.Min(Environment.ProcessorCount, state.BreedThreads);
            var options   = new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = maxDegree
            };

            Action <CompetitiveEvaluatorThread> act = t => t.Run();
            var actionBlock = new ActionBlock <CompetitiveEvaluatorThread>(act, options);

            for (var i = 0; i < state.EvalThreads; i++)
            {
                var runnable = new TEvalThread
                {
                    ThreadNum = i,
                    State     = state,
                    Subpop    = subpop,
                    NumInds   = numinds[i],
                    From      = origins[i],
                    Problem   = prob,
                    Evaluator = this,
                    Inds      = individuals
                };
                actionBlock.Post(runnable);
            }
            actionBlock.Complete();
            actionBlock.Completion.Wait();
        }
Пример #3
0
        public virtual void EvalNRandomTwoWayPopChunk(IEvolutionState state, int origin, int numinds, int threadnum,
                                                      IList <Individual> individuals, int subpop, IGroupedProblem prob)
        {
            // the number of games played for each player
            var individualsOrdered = new EncapsulatedIndividual[individuals.Count];
            var queue = new EncapsulatedIndividual[individuals.Count];

            for (var i = 0; i < individuals.Count; i++)
            {
                individualsOrdered[i] = new EncapsulatedIndividual(individuals[i], 0);
            }

            var competition = new Individual[2];
            var subpops     = new[] { subpop, subpop };
            var updates     = new bool[2];

            updates[0] = true;
            var upperBound = origin + numinds;

            for (var x = origin; x < upperBound; x++)
            {
                Array.Copy(individualsOrdered, 0, queue, 0, queue.Length);
                competition[0] = queue[x].Ind;

                // if the rest of individuals is not enough to fill
                // all games remaining for the current individual
                // (meaning that the current individual has left a
                // lot of games to play versus players with index
                // greater than his own), then it should play with
                // all. In the end, we should check that he finished
                // all the games he needs. If he did, everything is
                // ok, otherwise he should play with some other players
                // with index smaller than his own, but all these games
                // will count only for his fitness evaluation, and
                // not for the opponents' (unless allowOverEvaluations is set to true)

                // if true, it means that he has to play against all opponents with greater index
                if (individuals.Count - x - 1 <= GroupSize - queue[x].NumOpponentsMet)
                {
                    for (var y = x + 1; y < queue.Length; y++)
                    {
                        competition[1] = queue[y].Ind;
                        updates[1]     = queue[y].NumOpponentsMet < GroupSize || AllowOverEvaluation;
                        prob.Evaluate(state, competition, updates, false, subpops, 0);
                        queue[x].NumOpponentsMet++;
                        if (updates[1])
                        {
                            queue[y].NumOpponentsMet++;
                        }
                    }
                }
                // here he has to play against a selection of the opponents with greater index
                else
                {
                    // we can use the queue structure because we'll just rearrange the indexes
                    // but we should make sure we also rearrange the other vectors referring to the individuals

                    for (var y = 0; GroupSize > queue[x].NumOpponentsMet; y++)
                    {
                        // swap to the end and remove from list
                        var index = state.Random[0].NextInt(queue.Length - x - 1 - y) + x + 1;
                        competition[1] = queue[index].Ind;

                        updates[1] = queue[index].NumOpponentsMet < GroupSize || AllowOverEvaluation;
                        prob.Evaluate(state, competition, updates, false, subpops, 0);
                        queue[x].NumOpponentsMet++;
                        if (updates[1])
                        {
                            queue[index].NumOpponentsMet++;
                        }

                        // swap the players (such that a player will not be considered twice)
                        var temp = queue[index];
                        queue[index] = queue[queue.Length - y - 1];
                        queue[queue.Length - y - 1] = temp;
                    }
                }

                // if true, it means that the current player needs to play some games with other players with lower indexes.
                // this is an unfortunate situation, since all those players have already had their groupSize games for the evaluation
                if (queue[x].NumOpponentsMet < GroupSize)
                {
                    for (var y = queue[x].NumOpponentsMet; y < GroupSize; y++)
                    {
                        // select a random opponent with smaller index (don't even care for duplicates)
                        int index;
                        if (x > 0)
                        {
                            // if x is 0, then there are no players with smaller index, therefore pick a random one
                            index = state.Random[0].NextInt(x);
                        }
                        else
                        {
                            index = state.Random[0].NextInt(queue.Length - 1) + 1;
                        }
                        // use the opponent for the evaluation
                        competition[1] = queue[index].Ind;
                        updates[1]     = (queue[index].NumOpponentsMet < GroupSize) || AllowOverEvaluation;
                        prob.Evaluate(state, competition, updates, false, subpops, 0);
                        queue[x].NumOpponentsMet++;
                        if (updates[1])
                        {
                            queue[index].NumOpponentsMet++;
                        }
                    }
                }
            }
        }
Пример #4
0
        public virtual void EvalNRandomOneWayPopChunk(IEvolutionState state, int origin, int numinds, int threadnum, IList <Individual> individuals, int subpop, IGroupedProblem prob)
        {
            var queue = individuals.ToArray();
            int len   = queue.Length;

            var competition = new Individual[2];
            var subpops     = new[] { subpop, subpop };
            var updates     = new bool[2];

            updates[0] = true;
            updates[1] = false;
            var upperBound = origin + numinds;

            for (var x = origin; x < upperBound; x++)
            {
                competition[0] = individuals[x];
                // fill up our tournament
                for (var y = 0; y < GroupSize;)
                {
                    // swap to end and remove
                    var index = state.Random[0].NextInt(len - y);
                    competition[1]     = queue[index];
                    queue[index]       = queue[len - y - 1];
                    queue[len - y - 1] = competition[1];
                    // if the opponent is not the actual individual, we can
                    // have a competition
                    if (!competition[1].Equals(individuals[x]))
                    {
                        prob.Evaluate(state, competition, updates, false, subpops, 0);
                        y++;
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// A private helper function for evalutatePopulation which evaluates a chunk
        /// of individuals in a subpop for a given thread.
        ///
        /// Although this method is declared public (for the benefit of a private
        /// helper class in this file), you should not call it.
        /// </summary>
        public virtual void EvalRoundRobinPopChunk(IEvolutionState state, int origin, int numinds, int threadnum, IList <Individual> individuals, int subpop, IGroupedProblem prob)
        {
            var competition = new Individual[2];
            var subpops     = new[] { subpop, subpop };
            var updates     = new bool[2];

            updates[0] = updates[1] = true;
            var upperBound = origin + numinds;

            // evaluate chunk of population against entire population
            // since an individual x will be evaluated against all
            // other individuals <x in other threads, only evaluate it against
            // individuals >x in this thread.
            for (var x = origin; x < upperBound; x++)
            {
                for (var y = x + 1; y < individuals.Count; y++)
                {
                    competition[0] = individuals[x];
                    competition[1] = individuals[y];
                    prob.Evaluate(state, competition, updates, false, subpops, 0);
                }
            }
        }
Пример #6
0
        public virtual void EvalSingleElimination(IEvolutionState state, IList <Individual> individuals, int subpop, IGroupedProblem prob)
        {
            // for a single-elimination tournament, the subpop[0] size must be 2^n for
            // some value n.  We don't check that here!  Check it in Setup.

            // create the tournament array
            var tourn = individuals.ToArray();

            var len         = tourn.Length;
            var competition = new Individual[2];
            var subpops     = new[] { subpop, subpop };
            var updates     = new bool[2];

            updates[0] = updates[1] = true;

            // the "top half" of our array will be losers.
            // the bottom half will be winners.  Then we cut our array in half and repeat.
            while (len > 1)
            {
                for (var x = 0; x < len / 2; x++)
                {
                    competition[0] = tourn[x];
                    competition[1] = tourn[len - x - 1];

                    prob.Evaluate(state, competition, updates, true, subpops, 0);
                }

                for (var x = 0; x < len / 2; x++)
                {
                    // if the second individual is better, or coin flip if equal, than we switch them around
                    if (tourn[len - x - 1].Fitness.BetterThan(tourn[x].Fitness) ||
                        tourn[len - x - 1].Fitness.EquivalentTo(tourn[x].Fitness) && state.Random[0].NextBoolean())
                    {
                        Individual temp = tourn[x];
                        tourn[x]           = tourn[len - x - 1];
                        tourn[len - x - 1] = temp;
                    }
                }

                // last part of the tournament: deal with odd values of len!
                if (len % 2 != 0)
                {
                    len = 1 + len / 2;
                }
                else
                {
                    len /= 2;
                }
            }
        }
        public virtual void AfterCoevolutionaryEvaluation(IEvolutionState state, Population pop, IGroupedProblem prob)
        {
            if (NumElite > 0)
            {
                for (var i = 0; i < state.Population.Subpops.Count; i++)
                {
                    if (ShouldEvaluateSubpop(state, i, 0))              // only load elites for subpopulations which are actually changing
                    {
                        LoadElites(state, i);
                    }
                }
            }

            // copy over the previous population
            if (NumPrev > 0)
            {
                _previousPopulation = (Population)(state.Population.EmptyClone());
                for (var i = 0; i < _previousPopulation.Subpops.Count; i++)
                {
                    for (var j = 0; j < _previousPopulation.Subpops[i].Individuals.Count; j++)
                    {
                        _previousPopulation.Subpops[i].Individuals[j] = (Individual)(state.Population.Subpops[i].Individuals[j].Clone());
                    }
                }
            }
        }
        public virtual void PerformCoevolutionaryEvaluation(IEvolutionState state, Population pop, IGroupedProblem prob)
        {
            var evaluations = 0;

            _inds    = new Individual[pop.Subpops.Count];
            _updates = new bool[pop.Subpops.Count];

            // we start by warming up the selection methods
            if (NumCurrent > 0)
            {
                for (var i = 0; i < _selectionMethodCurrent.Length; i++)
                {
                    _selectionMethodCurrent[i].PrepareToProduce(state, i, 0);
                }
            }

            if (NumPrev > 0)
            {
                for (var i = 0; i < _selectionMethodPrev.Length; i++)
                {
                    // do a hack here
                    var currentPopulation = state.Population;
                    state.Population = _previousPopulation;
                    _selectionMethodPrev[i].PrepareToProduce(state, i, 0);
                    state.Population = currentPopulation;
                }
            }

            // build subpopulation array to pass in each time
            var subpops = new int[state.Population.Subpops.Count];

            for (var j = 0; j < subpops.Length; j++)
            {
                subpops[j] = j;
            }

            // handle shuffled always

            if (NumShuffled > 0)
            {
                int[] /*numShuffled*/ [] /*subpop*/ [] /*shuffledIndividualIndexes*/ ordering = null;
                // build shuffled orderings
                ordering = TensorFactory.Create <Int32>(NumShuffled, state.Population.Subpops.Count,
                                                        state.Population.Subpops[0].Individuals.Count);
                for (var c = 0; c < NumShuffled; c++)
                {
                    for (var m = 0; m < state.Population.Subpops.Count; m++)
                    {
                        for (var i = 0; i < state.Population.Subpops[0].Individuals.Count; i++)
                        {
                            ordering[c][m][i] = i;
                        }
                        if (m != 0)
                        {
                            Shuffle(state, ordering[c][m]);
                        }
                    }
                }

                // for each individual
                for (var i = 0; i < state.Population.Subpops[0].Individuals.Count; i++)
                {
                    for (var k = 0; k < NumShuffled; k++)
                    {
                        for (var ind = 0; ind < _inds.Length; ind++)
                        {
                            _inds[ind]    = state.Population.Subpops[ind].Individuals[ordering[k][ind][i]];
                            _updates[ind] = true;
                        }
                        prob.Evaluate(state, _inds, _updates, false, subpops, 0);
                        evaluations++;
                    }
                }
            }

            // for each subpopulation
            for (var j = 0; j < state.Population.Subpops.Count; j++)
            {
                // now do elites and randoms

                if (!ShouldEvaluateSubpop(state, j, 0))
                {
                    continue;                                      // don't evaluate this subpopulation
                }
                // for each individual
                for (var i = 0; i < state.Population.Subpops[j].Individuals.Count; i++)
                {
                    var individual = state.Population.Subpops[j].Individuals[i];

                    // Test against all the elites
                    for (var k = 0; k < _eliteIndividuals[j].Length; k++)
                    {
                        for (var ind = 0; ind < _inds.Length; ind++)
                        {
                            if (ind == j)
                            {
                                _inds[ind]    = individual;
                                _updates[ind] = true;
                            }
                            else
                            {
                                _inds[ind]    = _eliteIndividuals[ind][k];
                                _updates[ind] = false;
                            }
                        }
                        prob.Evaluate(state, _inds, _updates, false, subpops, 0);
                        evaluations++;
                    }

                    // test against random selected individuals of the current population
                    for (var k = 0; k < NumCurrent; k++)
                    {
                        for (var ind = 0; ind < _inds.Length; ind++)
                        {
                            if (ind == j)
                            {
                                _inds[ind]    = individual;
                                _updates[ind] = true;
                            }
                            else
                            {
                                _inds[ind]    = ProduceCurrent(ind, state, 0);
                                _updates[ind] = true;
                            }
                        }
                        prob.Evaluate(state, _inds, _updates, false, subpops, 0);
                        evaluations++;
                    }

                    // Test against random selected individuals of previous population
                    for (int k = 0; k < NumPrev; k++)
                    {
                        for (int ind = 0; ind < _inds.Length; ind++)
                        {
                            if (ind == j)
                            {
                                _inds[ind]    = individual;
                                _updates[ind] = true;
                            }
                            else
                            {
                                _inds[ind]    = ProducePrevious(ind, state, 0);
                                _updates[ind] = false;
                            }
                        }
                        prob.Evaluate(state, _inds, _updates, false, subpops, 0);
                        evaluations++;
                    }
                }
            }

            // now shut down the selection methods
            if (NumCurrent > 0)
            {
                for (var i = 0; i < _selectionMethodCurrent.Length; i++)
                {
                    _selectionMethodCurrent[i].FinishProducing(state, i, 0);
                }
            }

            if (NumPrev > 0)
            {
                for (var i = 0; i < _selectionMethodPrev.Length; i++)
                {
                    // do a hack here
                    var currentPopulation = state.Population;
                    state.Population = _previousPopulation;
                    _selectionMethodPrev[i].FinishProducing(state, i, 0);
                    state.Population = currentPopulation;
                }
            }

            state.Output.Message("Evaluations: " + evaluations);
        }
        public virtual void  BeforeCoevolutionaryEvaluation(IEvolutionState state, Population pop, IGroupedProblem prob)
        {
            if (state.Generation == 0)
            {
                // create arrays for the elite individuals in the population at the previous generation.
                // deep clone the elite individuals as random individuals (in the initial generation, nobody has been evaluated yet).

                // deal with the elites
                _eliteIndividuals = TensorFactory.Create <Individual>(state.Population.Subpops.Count, NumElite);

                // copy the first individuals in each subpop (they are already randomly generated)
                for (var i = 0; i < _eliteIndividuals.Length; i++)
                {
                    if (NumElite > state.Population.Subpops[i].Individuals.Count)
                    {
                        state.Output.Fatal("Number of elite partners is greater than the size of the subpop.");
                    }
                    for (var j = 0; j < NumElite; j++)
                    {
                        _eliteIndividuals[i][j] = (Individual)(state.Population.Subpops[i].Individuals[j].Clone());  // just take the first N individuals of each subpopulation
                    }
                }

                // test for shuffled
                if (NumShuffled > 0)
                {
                    var size = state.Population.Subpops[0].Individuals.Count;
                    for (var i = 0; i < state.Population.Subpops.Count; i++)
                    {
                        if (state.Population.Subpops[i].Individuals.Count != size)
                        {
                            state.Output.Fatal("Shuffling was requested in MultiPopCoevolutionaryEvaluator, but the subpopulation sizes are not the same.  " +
                                               "Specifically, subpopulation 0 has size " + size + " but subpopulation " + i + " has size " + state.Population.Subpops[i].Individuals.Count);
                        }
                    }
                }
            }
        }