Skip to content

Commit

Permalink
Refactor crossover operators
Browse files Browse the repository at this point in the history
  • Loading branch information
ajnebro committed Jun 25, 2024
1 parent c410616 commit 110de54
Show file tree
Hide file tree
Showing 17 changed files with 1,994 additions and 2,253 deletions.
2 changes: 1 addition & 1 deletion examples/MIC2024Example.NSGAIISolvingIntegerProblem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ solver::NSGAII = NSGAII(
termination = TerminationByEvaluations(2500))

solver.mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)
solver.crossover = SBXCrossover(1.0, 20.0, problem.bounds)
solver.crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds)

# Step 3: optimize
optimize(solver)
Expand Down
4 changes: 2 additions & 2 deletions examples/NSGAIIAsAnEvolutionaryAlgorithm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ function main()
solver.termination = TerminationByEvaluations(25000)

mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)
crossover = SBXCrossover(0.9, 20.0, problem.bounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 20.0, bounds = problem.bounds)

"""
mutation = UniformMutation(1.0/numberOfVariables(problem), 20.0, problem.bounds)
crossover = BLXAlphaCrossover(1.0, 0.5, problem.bounds)
crossover = BLXAlphaCrossover(probability = 1.0, alpha = 0.5, bounds = problem.bounds)
"""

solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)
Expand Down
2 changes: 1 addition & 1 deletion examples/NSGAIIBinaryProblemExplicitSettings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function main()
populationSize = 50,
termination = TerminationByEvaluations(2000),
mutation = BitFlipMutation(1.0 / problem.numberOfBits),
crossover = SinglePointCrossover(1.0)
crossover = SinglePointCrossover(probability = 1.0)
)

optimize(solver)
Expand Down
2 changes: 1 addition & 1 deletion examples/NSGAIIFloatProblemExplicitSettings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function main()
problem,
populationSize = 50,
termination = TerminationByComputingTime(Dates.Second(2)),
crossover = SBXCrossover(1.0, 20.0, problem.bounds),
crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds),
mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds))

optimize(solver)
Expand Down
2 changes: 1 addition & 1 deletion examples/NSGAIISolvingAConstrainedProblem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function main()
solver.termination = TerminationByEvaluations(25000)

solver.mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)
solver.crossover = SBXCrossover(1.0, 20.0, problem.bounds)
solver.crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds)

solver.dominanceComparator = ConstraintsAndDominanceComparator()

Expand Down
2 changes: 1 addition & 1 deletion examples/NSGAIIWithExternalCrowdingDistanceArchive.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function main()

mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)

crossover = SBXCrossover(0.9, 20.0, problem.bounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 20.0, bounds = problem.bounds)

solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand Down
2 changes: 1 addition & 1 deletion examples/NSGAIIWithExternalUnboundedArchive.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function main()

mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)

crossover = SBXCrossover(0.9, 20.0, problem.bounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 20.0, bounds = problem.bounds)

solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand Down
2 changes: 1 addition & 1 deletion examples/singleObjectiveGeneticAlgorithmOneMax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function main()
solver.termination = TerminationByEvaluations(40000)

mutation = BitFlipMutation(1.0 / numberOfVariables(problem))
crossover = SinglePointCrossover(1.0)
crossover = SinglePointCrossover(probability = 1.0)
solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

solver.selection = BinaryTournamentSelection(solver.variation.matingPoolSize, IthObjectiveComparator(1))
Expand Down
6 changes: 2 additions & 4 deletions examples/singleObjectiveGeneticAlgorithmSphere.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ function main()
solver.termination = TerminationByEvaluations(700000)

mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)
"""
solver.crossover = BLXAlphaCrossover((probability=1.0, alpha=0.5, bounds=problem.bounds))
"""
crossover = SBXCrossover(1.0, 20.0, problem.bounds)

crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds)
solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

solver.selection = BinaryTournamentSelection(solver.variation.matingPoolSize, IthObjectiveComparator(1))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ function main()

mutation = PolynomialMutation(1.0 / numberOfVariables(problem), 20.0, problem.bounds)
"""
solver.crossover = BLXAlphaCrossover((probability=1.0, alpha=0.5, bounds=problem.bounds))
solver.crossover = BLXAlphaCrossover(probability=1.0, alpha=0.5, bounds=problem.bounds)
"""
crossover = SBXCrossover(1.0, 20.0, problem.bounds)
crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds)
solver.variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

solver.selection = BinaryTournamentSelection(solver.variation.matingPoolSize, IthObjectiveComparator(1))
Expand Down
566 changes: 292 additions & 274 deletions notebooks/Dealing with constrained problems.ipynb

Large diffs are not rendered by default.

2,720 changes: 1,359 additions & 1,361 deletions notebooks/NSGA-II notebook.ipynb

Large diffs are not rendered by default.

898 changes: 307 additions & 591 deletions notebooks/NSGA-II with external archive.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/algorithm/NSGAII.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mutable struct NSGAII <: Algorithm
problem :: ContinuousProblem;
populationSize = 100,
termination = TerminationByEvaluations(25000), dominanceComparator = numberOfConstraints(problem) == 0 ? DefaultDominanceComparator() : ConstraintsAndDominanceComparator(),
crossover = SBXCrossover(1.0, 20.0, problem.bounds),
crossover = SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = problem.bounds),
mutation = PolynomialMutation(1.0/numberOfVariables(problem), 20.0, problem.bounds))
algorithm = new()
algorithm.solver = EvolutionaryAlgorithm()
Expand All @@ -35,7 +35,7 @@ mutable struct NSGAII <: Algorithm
problem :: BinaryProblem;
populationSize = 100,
termination = TerminationByEvaluations(25000), dominanceComparator = numberOfConstraints(problem) == 0 ? DefaultDominanceComparator() : ConstraintsAndDominanceComparator(),
crossover = SinglePointCrossover(1.0),
crossover = SinglePointCrossover(probability = 1.0),
mutation = BitFlipMutation(1.0/problem.numberOfBits))
algorithm = new()
algorithm.solver = EvolutionaryAlgorithm()
Expand Down
11 changes: 11 additions & 0 deletions src/operator/crossover.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ struct BLXAlphaCrossover <: CrossoverOperator

function BLXAlphaCrossover(;probability = 0.9, alpha = 0.5, bounds = [])
@assert bounds != [] "The bounds list is empty"
@assert probability >= 0.0 string("The probability ", probability, " must be equal or greater than zero")
@assert alpha >= 0 string("The alpha value ", alpha, " cannot be negative")

return new(probability, alpha, bounds)
end
Expand Down Expand Up @@ -58,6 +60,8 @@ struct SBXCrossover <: CrossoverOperator

function SBXCrossover(;probability = 0.9, distributionIndex = 20.0, bounds = [])
@assert bounds != [] "The bounds list is empty"
@assert probability >= 0.0 string("The probability ", probability, " must be equal or greater than zero")
@assert distributionIndex >= 0 string("The distributionIndex value ", alpha, " cannot be negative")

return new(probability, distributionIndex, bounds)
end
Expand Down Expand Up @@ -220,6 +224,13 @@ end
# Single point crossover
struct SinglePointCrossover <: CrossoverOperator
probability::Real

function SinglePointCrossover(;probability = 0.9)
@assert probability >= 0.0 string("The probability ", probability, " must be equal or greater than zero")

return new(probability)
end

end

function numberOfRequiredParents(crossover::SinglePointCrossover)
Expand Down
8 changes: 4 additions & 4 deletions test/component/evolutionaryAlgorithm/variationTest.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function crossoverAndMutationVariationIsCorrectlyInitialized()
solutionBounds = [Bounds{Float64}(1.0, 10.0), Bounds{Float64}(1.0, 10.0)]

mutation = PolynomialMutation(0.01, 20.0, solutionBounds)
crossover = SBXCrossover(0.9, 30.0, solutionBounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 30.0, bounds = solutionBounds)

variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand All @@ -22,7 +22,7 @@ function theMatingPoolSizeWhenTheOffspringPopulationSizeIsOneMustBeTwo()
solutionBounds = [Bounds{Float64}(1.0, 10.0), Bounds{Float64}(1.0, 10.0)]

mutation = PolynomialMutation(0.01, 20.0, solutionBounds)
crossover = SBXCrossover(0.9, 30.0, solutionBounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 30.0, bounds = solutionBounds)

variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand All @@ -39,7 +39,7 @@ function crossoverAndMutationVariationReturnTheCorrectNumberOfSolutionsCaseA()
solutionBounds = matingPool[1].bounds

mutation = PolynomialMutation(0.01, 20.0, solutionBounds)
crossover = SBXCrossover(0.9, 30.0, solutionBounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 30.0, bounds = solutionBounds)

variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand All @@ -56,7 +56,7 @@ function crossoverAndMutationVariationReturnTheCorrectNumberOfSolutionsCaseB()
solutionBounds = matingPool[1].bounds

mutation = PolynomialMutation(0.01, 20.0, solutionBounds)
crossover = SBXCrossover(0.9, 30.0, solutionBounds)
crossover = SBXCrossover(probability = 0.9, distributionIndex = 30.0, bounds = solutionBounds)

variation = CrossoverAndMutationVariation(offspringPopulationSize, crossover, mutation)

Expand Down
12 changes: 6 additions & 6 deletions test/operator/crossoverTest.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function singlePointCrossoverWithProbabilityZeroReturnTwoSolutionsEqualToThePare
parent1 = BinarySolution(initBitVector("101000"), [], [], Dict())
parent2 = BinarySolution(initBitVector("010011"), [], [], Dict())

crossover = SinglePointCrossover(0.0)
crossover = SinglePointCrossover(probability = 0.0)
children = recombine(parent1, parent2, crossover)

return isequal(parent1, children[1]) && isequal(parent2, children[2])
Expand All @@ -16,16 +16,16 @@ function singlePointCrossoverWithWithProbabilityOneChangesAllTheVariableValuesIn
parent1 = BinarySolution(initBitVector("101000"), [], [], Dict())
parent2 = BinarySolution(initBitVector("010011"), [], [], Dict())

crossover = SinglePointCrossover(1.0)
crossover = SinglePointCrossover(probability = 1.0)
children = recombine(parent1, parent2, crossover)

return !isequal(parent1, children[1]) && !isequal(parent2, children[2])
end

@testset "Single point crossover tests" begin
@test SinglePointCrossover(0.1).probability == 0.1
@test numberOfRequiredParents(SinglePointCrossover(0.1)) == 2
@test numberOfDescendants(SinglePointCrossover(0.1)) == 2
@test SinglePointCrossover(probability = 0.1).probability == 0.1
@test numberOfRequiredParents(SinglePointCrossover(probability = 0.1)) == 2
@test numberOfDescendants(SinglePointCrossover(probability = 0.1)) == 2

@test singlePointCrossoverWithProbabilityZeroReturnTwoSolutionsEqualToTheParentSolutions()
@test singlePointCrossoverWithWithProbabilityOneChangesAllTheVariableValuesIntheReturnedSolutions()
Expand Down Expand Up @@ -61,7 +61,7 @@ function SBXCrossoverWithAEmptyListOfBoundsRaiseAnException()
return SBXCrossover(probability = 1.0, distributionIndex = 20.0, bounds = [])
end

sbxCrossover = SBXCrossover(probability = 0.054, probability = 20.0, probability = [Bounds{Float64}(3.0, 5.0)])
sbxCrossover = SBXCrossover(probability = 0.054, distributionIndex = 20.0, bounds = [Bounds{Float64}(3.0, 5.0)])
@testset "SBX crossover tests" begin
@test sbxCrossover.probability == 0.054
@test sbxCrossover.distributionIndex == 20.0
Expand Down

0 comments on commit 110de54

Please sign in to comment.