From d8c56e58e29cf1d1820e80c3a70345d147cbb42b Mon Sep 17 00:00:00 2001 From: Tim Wood Date: Mon, 16 Jun 2025 13:35:46 -0700 Subject: [PATCH 1/2] Issue #135: Remediate CVE-2023-4863. --- .../GeneticSharp.Runner.ConsoleApp.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/GeneticSharp.Runner.ConsoleApp/GeneticSharp.Runner.ConsoleApp.csproj b/src/GeneticSharp.Runner.ConsoleApp/GeneticSharp.Runner.ConsoleApp.csproj index 0924fc4b..84e10b1f 100644 --- a/src/GeneticSharp.Runner.ConsoleApp/GeneticSharp.Runner.ConsoleApp.csproj +++ b/src/GeneticSharp.Runner.ConsoleApp/GeneticSharp.Runner.ConsoleApp.csproj @@ -2,10 +2,10 @@ - + net6.0 - Exe + Exe win7-x86;osx-x64;linux-x64 @@ -13,7 +13,7 @@ - + @@ -21,8 +21,8 @@ - + - \ No newline at end of file + From b97ef42276101ec3dbb4e519a9fe3cade58215b5 Mon Sep 17 00:00:00 2001 From: Tim Wood Date: Mon, 23 Jun 2025 13:05:01 -0700 Subject: [PATCH 2/2] Checkpoint: Add vector fitness class and processing for use with GPUs. Extend vector pattern to FuncFitness. TODO: Build out tests. --- .../Fitnesses/FuncFitness.cs | 28 +++++- .../Fitnesses/VectorFitness.cs | 32 +++++++ src/GeneticSharp.Domain/GeneticAlgorithm.cs | 89 ++++++++++++++----- 3 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 src/GeneticSharp.Domain/Fitnesses/VectorFitness.cs diff --git a/src/GeneticSharp.Domain/Fitnesses/FuncFitness.cs b/src/GeneticSharp.Domain/Fitnesses/FuncFitness.cs index fc89fb33..3a46c012 100644 --- a/src/GeneticSharp.Domain/Fitnesses/FuncFitness.cs +++ b/src/GeneticSharp.Domain/Fitnesses/FuncFitness.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace GeneticSharp { @@ -30,4 +31,29 @@ public double Evaluate (IChromosome chromosome) } #endregion } -} \ No newline at end of file + + public class VectorFuncFitness : VectorFitness + { + private readonly Func, double[]> m_func; + + /// + /// Initializes a new instance of the class. + /// + /// The fitness evaluation Func. + public VectorFuncFitness(Func, double[]> func) + { + ExceptionHelper.ThrowIfNull("func", func); + m_func = func; + } + + /// + /// Evaluates the specified chromosomes and returns their fitness values as a vector. + /// + /// The chromosomes to be evaluated. + /// A vector of fitness values corresponding to the input chromosomes. + public override double[] Evaluate(IList chromosomes) + { + return m_func(chromosomes); + } + } +} diff --git a/src/GeneticSharp.Domain/Fitnesses/VectorFitness.cs b/src/GeneticSharp.Domain/Fitnesses/VectorFitness.cs new file mode 100644 index 00000000..00aa15cf --- /dev/null +++ b/src/GeneticSharp.Domain/Fitnesses/VectorFitness.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace GeneticSharp +{ + /// + /// Defines an interface for a vector fitness function. , for discussion of a scalar fitness function. + /// + /// A vector fitness function extends the notion of a scalar fitness function to express the vector result of a fitness function run in parallel on a vector-processor + /// device such as a GPU. Given a set of chromosomes, the vector fitness function evaluates the chromosomes in the set on a logical vector device, and returns a vector of fitness values. + /// This approach differs from and offers convenience relative to the scalar fitness function executed in parallel with , + /// as VectorFitness delegates the parallel scoring of the chromosomes to the vector device and its substantial parallelism, rather than using a CPU thread per chromosome. + /// Applications must use instances of this class with . + /// Wikipedia + /// + /// + public abstract class VectorFitness : IFitness + { + public double Evaluate(IChromosome chromosome) + { + // This method is not used in VectorFitness, but is required by the IFitness interface. + // It is provided here to satisfy the interface contract, but should not be called. + throw new System.NotSupportedException("IVectorFitness does not support single chromosome evaluation. Use Evaluate(IList) or IFitness.Evaluate(IChromosome) instead."); + } + + /// + /// Evaluates the specified chromosomes and returns their fitness values as a vector. + /// + /// The chromosomes to be evaluated. + /// A vector of fitness values corresponding to the input chromosomes. The indexes of the fitness values match the indexes of the chromosomes in the list. + public abstract double[] Evaluate(IList chromosomes); + } +} diff --git a/src/GeneticSharp.Domain/GeneticAlgorithm.cs b/src/GeneticSharp.Domain/GeneticAlgorithm.cs index 9c3ac3ed..132e6151 100644 --- a/src/GeneticSharp.Domain/GeneticAlgorithm.cs +++ b/src/GeneticSharp.Domain/GeneticAlgorithm.cs @@ -390,24 +390,49 @@ private bool EndCurrentGeneration() /// Evaluates the fitness. /// private void EvaluateFitness() - { - try - { - var chromosomesWithoutFitness = Population.CurrentGeneration.Chromosomes.Where(c => !c.Fitness.HasValue).ToList(); + { + var chromosomesWithoutFitness = Population.CurrentGeneration.Chromosomes.Where(c => !c.Fitness.HasValue).ToList(); - for (int i = 0; i < chromosomesWithoutFitness.Count; i++) + if (Fitness is VectorFitness vectorFitness) + { + if (TaskExecutor is not LinearTaskExecutor) { - var c = chromosomesWithoutFitness[i]; + throw new InvalidOperationException("The vector fitness evaluation requires a LinearTaskExecutor."); + } + + EvaluateVectorFitness(chromosomesWithoutFitness, vectorFitness); + } + else + { + EvaluateScalarFitness(chromosomesWithoutFitness); + } - TaskExecutor.Add(() => + Population.CurrentGeneration.Chromosomes = Population.CurrentGeneration.Chromosomes.OrderByDescending(c => c.Fitness.Value).ToList(); + } + + private void EvaluateVectorFitness(IList chromosomesWithoutFitness, VectorFitness vectorFitness) + { + try + { + TaskExecutor.Add(() => + { + try { - RunEvaluateFitness(c); - }); - } + var fitnessValues = vectorFitness.Evaluate(chromosomesWithoutFitness); + for (int i = 0; i < chromosomesWithoutFitness.Count; i++) + { + chromosomesWithoutFitness[i].Fitness = fitnessValues[i]; + } + } + catch (Exception ex) + { + throw new FitnessException(Fitness, "Error executing Fitness.Evaluate for chromosome vector: {0}".With(ex.Message), ex); + } + }); if (!TaskExecutor.Start()) { - throw new TimeoutException("The fitness evaluation reached the {0} timeout.".With(TaskExecutor.Timeout)); + throw new TimeoutException("The vector fitness evaluation reached the {0} timeout.".With(TaskExecutor.Timeout)); } } finally @@ -415,15 +440,39 @@ private void EvaluateFitness() TaskExecutor.Stop(); TaskExecutor.Clear(); } - - Population.CurrentGeneration.Chromosomes = Population.CurrentGeneration.Chromosomes.OrderByDescending(c => c.Fitness.Value).ToList(); - } - - /// - /// Runs the evaluate fitness. - /// - /// The chromosome. - private void RunEvaluateFitness(object chromosome) + } + + private void EvaluateScalarFitness(IList chromosomesWithoutFitness) + { + try + { + for (int i = 0; i < chromosomesWithoutFitness.Count; i++) + { + var c = chromosomesWithoutFitness[i]; + + TaskExecutor.Add(() => + { + RunEvaluateFitness(c); + }); + } + + if (!TaskExecutor.Start()) + { + throw new TimeoutException("The fitness evaluation reached the {0} timeout.".With(TaskExecutor.Timeout)); + } + } + finally + { + TaskExecutor.Stop(); + TaskExecutor.Clear(); + } + } + + /// + /// Runs the evaluate fitness. + /// + /// The chromosome. + private void RunEvaluateFitness(object chromosome) { var c = chromosome as IChromosome;