private void RunAsync(long maxEvaluations, TerminateFunction terminateFunction) { var token = _tokenSource.Token; ((ManualResetEvent)token.WaitHandle).Set(); _task = Task.Factory.StartNew(() => MainTask(maxEvaluations, terminateFunction, token), token, TaskCreationOptions.LongRunning, TaskScheduler.Default); _task.ContinueWith(t => { /* error handling */ var exception = t.Exception; IsRunning = false; if (this.OnRunException != null && t.Exception != null) { var message = new StringBuilder(); foreach (var ex in t.Exception.InnerExceptions) { message.Append(ex.Message); message.Append("\r\n"); } var eventArgs = new ExceptionEventArgs("RunAsync", message.ToString()); this.OnRunException(this, eventArgs); } }, TaskContinuationOptions.OnlyOnFaulted); }
/// <summary> /// Main run routine of genetic algorithm. /// </summary> private void MainTask(long maxEvaluations, TerminateFunction terminateFunction, CancellationToken token) { try { IsRunning = true; TerminateFunction = terminateFunction; //validate the population if (this.Population == null || this.Population.Solutions.Count == 0) { throw new NullReferenceException( "Either the Population is null, or there are no solutions within the population."); } //perform the initial evaluation Evaluations += _population.Evaluate(FitnessFunction); //raise the Initial Evaluation Complete event if (this.OnInitialEvaluationComplete != null) { var eventArgs = new GaEventArgs(_population, 0, Evaluations); this.OnInitialEvaluationComplete(this, eventArgs); } //main run loop for GA for (int generation = 0; Evaluations < maxEvaluations; generation++) { //Note: Selection handled by the operator(s) _currentGeneration = generation; var newPopulation = RunGeneration(_currentGeneration, _population, FitnessFunction); _population.Solutions.Clear(); _population.Solutions.AddRange(newPopulation.Solutions); //raise the Generation Complete event if (this.OnGenerationComplete != null) { var eventArgs = new GaEventArgs(_population, generation + 1, Evaluations); this.OnGenerationComplete(this, eventArgs); } if (TerminateFunction != null) { if (TerminateFunction.Invoke(_population, generation + 1, Evaluations)) { break; } } //if running synchronously, this never gets set if (token.CanBeCanceled) { //running asynchronously so check for a 'Pause' by monitoring the wait handle. token.WaitHandle.WaitOne(); } if (token.IsCancellationRequested) { break; } } IsRunning = false; IsPaused = false; //raise the Run Complete event if (this.OnRunComplete != null) { var eventArgs = new GaEventArgs(_population, _currentGeneration + 1, Evaluations); this.OnRunComplete(this, eventArgs); } } catch (Exception ex) { // re-throw for now throw ex; } }
/// <summary> /// Runs the algorithm the specified number of times. Each run executes until the specified delegate function returns true. /// </summary> /// <param name="terminateFunction"></param> public void RunAsync(TerminateFunction terminateFunction) { RunAsync(long.MaxValue, terminateFunction); }
/// <summary> /// Main method for executing the GA. The GA runs until the /// Terminate function returns true. /// This method runs syncronously. /// </summary> /// <param name="terminateFunction">Terminate function.</param> public void Run(TerminateFunction terminateFunction) { MainTask(long.MaxValue, terminateFunction, CancellationToken.None); }