From 20d6a5a7138d520c38c0d59020c142e0d74232ce Mon Sep 17 00:00:00 2001 From: ajnebro Date: Thu, 23 May 2024 16:08:49 +0200 Subject: [PATCH] Minor refactoring --- src/algorithm/evolutionaryAlgorithm.jl | 2 +- .../evolutionaryAlgorithm/replacement.jl | 2 +- src/core/solution.jl | 4 +- src/util/comparator.jl | 4 - src/util/ranking.jl | 84 +++++++++++++++++-- test/util/rankingTest.jl | 36 ++++---- 6 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/algorithm/evolutionaryAlgorithm.jl b/src/algorithm/evolutionaryAlgorithm.jl index 30435fb..f80e08f 100644 --- a/src/algorithm/evolutionaryAlgorithm.jl +++ b/src/algorithm/evolutionaryAlgorithm.jl @@ -45,7 +45,7 @@ function evolutionaryAlgorithm(ea::EvolutionaryAlgorithm) offspringPopulation = variate(ea.variation, population, matingPool) offspringPopulation = evaluate(ea.evaluation, offspringPopulation) - @time population = replace_(ea.replacement, population, offspringPopulation) + population = replace_(ea.replacement, population, offspringPopulation) evaluations += length(offspringPopulation) ea.status["EVALUATIONS"] = evaluations diff --git a/src/component/evolutionaryAlgorithm/replacement.jl b/src/component/evolutionaryAlgorithm/replacement.jl index 5c4d09e..c390582 100644 --- a/src/component/evolutionaryAlgorithm/replacement.jl +++ b/src/component/evolutionaryAlgorithm/replacement.jl @@ -35,7 +35,7 @@ function replace_(replacement::RankingAndDensityEstimatorReplacement, x::Vector{ compute!(replacement.ranking, jointVector) - for rank in replacement.ranking.rank + for rank in replacement.ranking.ranks compute!(replacement.densityEstimator, rank) end diff --git a/src/core/solution.jl b/src/core/solution.jl index 084ee7c..0d4f9f8 100644 --- a/src/core/solution.jl +++ b/src/core/solution.jl @@ -4,8 +4,8 @@ mutable struct ContinuousSolution{T<:Number} <: Solution variables::Array{T} - objectives::Array{AbstractFloat} - constraints::Array{AbstractFloat} + objectives::Array{Real} + constraints::Array{Real} attributes::Dict bounds::Array{Bounds{T}} end diff --git a/src/util/comparator.jl b/src/util/comparator.jl index c471c2b..a552416 100644 --- a/src/util/comparator.jl +++ b/src/util/comparator.jl @@ -80,10 +80,6 @@ function compare(comparator::DefaultDominanceComparator, x::Vector{T}, y::Vector return result end -#function compareForDominance(solution1::Solution, solution2::Solution)::Int -# return compareForDominance(solution1.objectives, solution2.objectives) -#end - mutable struct IthObjectiveComparator <: Comparator index::Int elementAtComparator::ElementAtComparator diff --git a/src/util/ranking.jl b/src/util/ranking.jl index 8e70cad..295199d 100644 --- a/src/util/ranking.jl +++ b/src/util/ranking.jl @@ -1,7 +1,7 @@ # Struct and methods to implement the non-dominated ranking sorting method mutable struct DominanceRanking <: Ranking - rank::Vector + ranks::Vector dominanceComparator::Comparator end @@ -14,17 +14,17 @@ function DominanceRanking() end function getSubFront(ranking::DominanceRanking, rankId::Integer) - message = string("The subfront id ", rankId, " is not in the range 1:", length(ranking.rank)) - @assert length(ranking.rank) >= rankId message - return ranking.rank[rankId] + message = string("The subfront id ", rankId, " is not in the range 1:", length(ranking.ranks)) + @assert length(ranking.ranks) >= rankId message + return ranking.ranks[rankId] end function numberOfRanks(ranking::DominanceRanking)::Int - return length(ranking.rank) + return length(ranking.ranks) end function appendRank!(ranking::DominanceRanking, newRank::Vector{T}) where {T<:Solution} - push!(ranking.rank, newRank) + push!(ranking.ranks, newRank) return Nothing end @@ -50,7 +50,7 @@ function compare(comparator::DominanceRankingComparator, solution1::Solution, so end function compute!(ranking::DominanceRanking, solutions::Array{T}) where {T<:Solution} - ranking.rank = [] + ranking.ranks = [] solutionsToRank = [solution for solution in solutions] rankCounter = 1 @@ -74,6 +74,76 @@ function compute!(ranking::DominanceRanking, solutions::Array{T}) where {T<:Solu end end + + +function dominates(a::Solution, b::Solution) + all(a.objectives .<= b.objectives) && any(a.objectives .< b.objectives) +end + +function compute2!(ranking::DominanceRanking, solutions::Array{T}) where {T<:Solution} + ranking.ranks = [] + + num_solutions = length(solutions) + domination_counts = zeros(Int, num_solutions) + dominated_solutions = [Int[] for _ in 1:num_solutions] + ranks = zeros(Int, num_solutions) + + # Step 1: Determine dominance relationships + for i in 1:num_solutions + for j in 1:num_solutions + if i != j + if dominates(solutions[i], solutions[j]) + push!(dominated_solutions[i], j) + elseif dominates(solutions[j], solutions[i]) + domination_counts[i] += 1 + end + end + end + end + + # Step 2: Assign initial ranks + front = Int[] + currentSolutionsRank = [] + for i in 1:num_solutions + if domination_counts[i] == 0 + ranks[i] = 1 + push!(front, i) + push!(currentSolutionsRank, solutions[i]) + end + end + + println("RANK: ", typeof(currentSolutionsRank)) + + appendRank!(ranking, currentSolutionsRank) + + # Step 3: Assign ranks iteratively + current_rank = 1 + while !isempty(front) + next_front = Int[] + nextSolutionsRank = T[] + for i in front + for j in dominated_solutions[i] + domination_counts[j] -= 1 + if domination_counts[j] == 0 + ranks[j] = current_rank + 1 + push!(next_front, j) + push!(nextSolutionsRank, solutions[j]) + end + end + end + appendRank!(ranking, nextSolutionsRank) + front = next_front + current_rank += 1 + end + + # Set ranks in the attributes of solutions + for i in 1:num_solutions + setRank(solutions[i], ranks[i]) + end +end + + + """ function compute2!(ranking::DominanceRanking, solutions::Array{T}) where {T<:Solution} ranking.rank = [] diff --git a/test/util/rankingTest.jl b/test/util/rankingTest.jl index 0f917cc..1cc16e3 100644 --- a/test/util/rankingTest.jl +++ b/test/util/rankingTest.jl @@ -22,7 +22,7 @@ end @testset "Emtpy ranking tests" begin @test createADominanceRankingWithADominanceComparatorWorksProperly() - @test length(DominanceRanking().rank) == 0 + @test length(DominanceRanking().ranks) == 0 @test numberOfRanks(DominanceRanking()) == 0 @test_throws "The subfront id 1 is not in the range 1:0" getSubFront(DominanceRanking(), 1) @@ -44,7 +44,7 @@ function computeRankingOfASolutionListWithASolutionReturnsARankingContainingThat ranking = DominanceRanking() compute!(ranking, solutions) - return numberOfRanks(ranking) == 1 && isequal(solutions[1].objectives, ranking.rank[1][1].objectives) + return numberOfRanks(ranking) == 1 && isequal(solutions[1].objectives, ranking.ranks[1][1].objectives) end function computeRankingOfASolutionListWithTwoNonDominatedSolutionsReturnsASingleRank() @@ -72,7 +72,7 @@ function computeRankingOfASolutionListWithTwoNonDominatedSolutionsReturnsASingle ranking = DominanceRanking() compute!(ranking, solutions) - return (getRank(solution1) == getRank(solution2) == 1) && (length(ranking.rank[1]) == 2) + return (getRank(solution1) == getRank(solution2) == 1) && (length(ranking.ranks[1]) == 2) end function computeRankingOfASolutionListWithTwoDominatedSolutionsReturnsTwoRankings() @@ -88,8 +88,8 @@ function computeRankingOfASolutionListWithTwoDominatedSolutionsReturnsTwoRanking compute!(ranking, solutions) return (numberOfRanks(ranking) == 2) && - (length(ranking.rank[1]) == 1) && - (length(ranking.rank[2]) == 1) && + (length(ranking.ranks[1]) == 1) && + (length(ranking.ranks[2]) == 1) && (getRank(solution2) == 1) && (getRank(solution1) == 2) end @@ -110,9 +110,9 @@ function computeRankingOfASolutionListWithThreeDominatedSolutionsReturnsThreeRan compute!(ranking, solutions) return (numberOfRanks(ranking) == 3) && - (length(ranking.rank[1]) == 1) && - (length(ranking.rank[2]) == 1) && - (length(ranking.rank[3]) == 1) && + (length(ranking.ranks[1]) == 1) && + (length(ranking.ranks[2]) == 1) && + (length(ranking.ranks[3]) == 1) && (getRank(solution3) == 1) && (getRank(solution2) == 2) && (getRank(solution1) == 3) @@ -138,7 +138,7 @@ function computeRankingOfASolutionListWithFourNonDominatedSolutionsReturnsOneRan compute!(ranking, solutions) return (numberOfRanks(ranking) == 1) && - (length(ranking.rank[1]) == 4) && + (length(ranking.ranks[1]) == 4) && (getRank(solution4) == 1) && (getRank(solution3) == 1) && (getRank(solution2) == 1) && @@ -158,8 +158,8 @@ function computeRankingOfASolutionListWithTwoNonDominatedFrontsReturnsTwoRanking compute!(ranking, solutions) return (numberOfRanks(ranking) == 2) && - (length(ranking.rank[1]) == 2) && - (length(ranking.rank[2]) == 3) && + (length(ranking.ranks[1]) == 2) && + (length(ranking.ranks[2]) == 3) && (getRank(solution1Front1) == 1) && (getRank(solution2Front2) == 2) end @@ -188,8 +188,8 @@ function computeRankingOfASolutionListWithWeakDominatedSolutionsWorkProperly() compute!(ranking, solutions) return (numberOfRanks(ranking) == 2) && - (length(ranking.rank[1]) == 4) && - (length(ranking.rank[2]) == 2) && + (length(ranking.ranks[1]) == 4) && + (length(ranking.ranks[2]) == 2) && (getRank(solution1) == 1) && (getRank(solution6) == 1) end @@ -217,9 +217,9 @@ function computeRankingMustWorkProperlyWithTheExampleOfTheMNDSPaper() compute!(ranking, solutions) return numberOfRanks(ranking) == 3 && - length(ranking.rank[1]) == 4 && - length(ranking.rank[2]) == 4 && - length(ranking.rank[3]) == 3 + length(ranking.ranks[1]) == 4 && + length(ranking.ranks[2]) == 4 && + length(ranking.ranks[3]) == 3 end function computeRankingMustWorkProperlyWithAnExampleOfNineSolutions() @@ -241,8 +241,8 @@ function computeRankingMustWorkProperlyWithAnExampleOfNineSolutions() compute!(ranking, solutions) return numberOfRanks(ranking) == 2 && - length(ranking.rank[1]) == 4 && - length(ranking.rank[2]) == 5 + length(ranking.ranks[1]) == 4 && + length(ranking.ranks[2]) == 5 end @testset "Compute ranking tests" begin