Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/GeneticSharp.Domain/Fitnesses/FuncFitness.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;

namespace GeneticSharp
{
Expand Down Expand Up @@ -30,4 +31,29 @@ public double Evaluate (IChromosome chromosome)
}
#endregion
}
}

public class VectorFuncFitness : VectorFitness
{
private readonly Func<IList<IChromosome>, double[]> m_func;

/// <summary>
/// Initializes a new instance of the <see cref="T:GeneticSharp.Domain.Fitnesses.VectorFuncFitness"/> class.
/// </summary>
/// <param name="func">The fitness evaluation Func.</param>
public VectorFuncFitness(Func<IList<IChromosome>, double[]> func)
{
ExceptionHelper.ThrowIfNull("func", func);
m_func = func;
}

/// <summary>
/// Evaluates the specified chromosomes and returns their fitness values as a vector.
/// </summary>
/// <param name="chromosomes">The chromosomes to be evaluated.</param>
/// <returns>A vector of fitness values corresponding to the input chromosomes.</returns>
public override double[] Evaluate(IList<IChromosome> chromosomes)
{
return m_func(chromosomes);
}
}
}
32 changes: 32 additions & 0 deletions src/GeneticSharp.Domain/Fitnesses/VectorFitness.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;

namespace GeneticSharp
{
/// <summary>
/// Defines an interface for a vector fitness function. <see cref="GeneticSharp.Domain.Fitnesses.IFitness"/>, for discussion of a scalar fitness function.
/// <remarks>
/// 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 <see cref="GeneticSharp.Infrastructure.Framework.Threading.ParallelTaskExecutor"/>,
/// 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 <em>must</em> use instances of this class with <see cref="GeneticSharp.Infrastructure.Framework.Threading.LinearTaskExecutor"/>.
/// <see href="http://en.wikipedia.org/wiki/Fitness_function">Wikipedia</see>
/// </remarks>
/// </summary>
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<IChromosome>) or IFitness.Evaluate(IChromosome) instead.");
}

/// <summary>
/// Evaluates the specified chromosomes and returns their fitness values as a vector.
/// </summary>
/// <param name="chromosomes">The chromosomes to be evaluated.</param>
/// <returns>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.</returns>
public abstract double[] Evaluate(IList<IChromosome> chromosomes);
}
}
89 changes: 69 additions & 20 deletions src/GeneticSharp.Domain/GeneticAlgorithm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,40 +390,89 @@ private bool EndCurrentGeneration()
/// Evaluates the fitness.
/// </summary>
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<IChromosome> 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
{
TaskExecutor.Stop();
TaskExecutor.Clear();
}

Population.CurrentGeneration.Chromosomes = Population.CurrentGeneration.Chromosomes.OrderByDescending(c => c.Fitness.Value).ToList();
}

/// <summary>
/// Runs the evaluate fitness.
/// </summary>
/// <param name="chromosome">The chromosome.</param>
private void RunEvaluateFitness(object chromosome)
}

private void EvaluateScalarFitness(IList<IChromosome> 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();
}
}

/// <summary>
/// Runs the evaluate fitness.
/// </summary>
/// <param name="chromosome">The chromosome.</param>
private void RunEvaluateFitness(object chromosome)
{
var c = chromosome as IChromosome;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@
<Import Project="..\msbuilds\GeneticSharp.dotnet-core.targets" />
<Import Project="..\msbuilds\GeneticSharp.common.targets" />
<Import Project="..\msbuilds\GeneticSharp.app.targets" />

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Exe</OutputType>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win7-x86;osx-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="NCalc.NetCore" Version="1.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta2" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="12.1.0" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="14.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\GeneticSharp.Domain\GeneticSharp.Domain.csproj" />
<ProjectReference Include="..\GeneticSharp.Extensions\GeneticSharp.Extensions.csproj" />
<ProjectReference Include="..\GeneticSharp.Infrastructure.Framework\GeneticSharp.Infrastructure.Framework.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="Resources\GhostwriterQuotex.json.txt" />
</ItemGroup>
</Project>
</Project>