Skip to content

Commit

Permalink
export nomdomSelector
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobbossek committed May 4, 2016
1 parent 84eb583 commit 36e7580
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 48 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export(setupMaximumEvaluationsTerminator)
export(setupMaximumIterationsTerminator)
export(setupMaximumTimeTerminator)
export(setupMutator)
export(setupNondomSelector)
export(setupNullRecombinator)
export(setupOXRecombinator)
export(setupOptPathLoggingMonitor)
Expand Down
48 changes: 1 addition & 47 deletions R/emoa.nsga2.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,52 +48,6 @@ nsga2 = function(
max.time = NULL,
...) {

# set up the core of NSGA-II, namely the survival selection
nsga2SurvivalSelector = makeSelector(
selector = function(fitness, n.select, task, control, opt.state) {
nondom.layers = doNondominatedSorting(fitness)

# storage for indizes of selected individuals
new.pop.idxs = integer()

# get maximum rank, i.e., the number of domination layers
max.rank = max(nondom.layers$ranks)

# get the indizes of points for each domination layer
idxs.by.rank = lapply(seq(max.rank), function(r) which(nondom.layers$ranks == r))

# get the number of points in each domination layer ...
front.len = sapply(idxs.by.rank, length)

# ... cumulate the number of points of the domination layers ...
cum.front.len = cumsum(front.len)

# ... and determine the first domination layer, which does not fit as a whole
front.first.nonfit = which.first(cum.front.len > n.select)

if (front.first.nonfit > 1L) {
# in this case at least one nondominated front can be added
new.pop.idxs = unlist(idxs.by.rank[1:(front.first.nonfit - 1L)])
}

# how many points to select by second criterion, i.e., crowding distance?
n.diff = n.select - length(new.pop.idxs)

if (n.diff > 0L) {
idxs.first.nonfit = idxs.by.rank[[front.first.nonfit]]
cds = computeCrowdingDistance(fitness[, idxs.first.nonfit, drop = FALSE])
idxs2 = order(cds, decreasing = TRUE)[1:n.diff]
new.pop.idxs = c(new.pop.idxs, idxs.first.nonfit[idxs2])
}

# merge the stuff and return
return(new.pop.idxs)
},
supported.objectives = "multi-objective",
name = "NSGA-II survival selector",
description = "nondominated sorting with potential crowding distance"
)

if (isSmoofFunction(task)) {
task = makeOptimizationTask(task)
}
Expand All @@ -116,7 +70,7 @@ nsga2 = function(
parent.selector = parent.selector,
recombinator = recombinator,
mutator = mutator,
survival.selector = nsga2SurvivalSelector
survival.selector = setupNondomSelector()
)

return(doTheEvolution(task, ctrl))
Expand Down
59 changes: 59 additions & 0 deletions R/operator.selector.nondom.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#' @title
#' Non-dominated sorting selector.
#'
#' @description
#' Applies nondominated sorting of the objective and subsequent crowding distance
#' criterion to select a subset of individuals. This is the selector used by the
#' NSGA-II EMOA (see \code{\link{nsga2}}).
#'
#' @return [\code{setOfIndividuals}]
#' @family selectors
#' @export
setupNondomSelector = function() {
selector = function(fitness, n.select, task, control, opt.state) {
nondom.layers = doNondominatedSorting(fitness)

# storage for indizes of selected individuals
new.pop.idxs = integer()

# get maximum rank, i.e., the number of domination layers
max.rank = max(nondom.layers$ranks)

# get the indizes of points for each domination layer
idxs.by.rank = lapply(seq(max.rank), function(r) which(nondom.layers$ranks == r))

# get the number of points in each domination layer ...
front.len = sapply(idxs.by.rank, length)

# ... cumulate the number of points of the domination layers ...
cum.front.len = cumsum(front.len)

# ... and determine the first domination layer, which does not fit as a whole
front.first.nonfit = which.first(cum.front.len > n.select)

if (front.first.nonfit > 1L) {
# in this case at least one nondominated front can be added
new.pop.idxs = unlist(idxs.by.rank[1:(front.first.nonfit - 1L)])
}

# how many points to select by second criterion, i.e., crowding distance?
n.diff = n.select - length(new.pop.idxs)

if (n.diff > 0L) {
idxs.first.nonfit = idxs.by.rank[[front.first.nonfit]]
cds = computeCrowdingDistance(fitness[, idxs.first.nonfit, drop = FALSE])
idxs2 = order(cds, decreasing = TRUE)[1:n.diff]
new.pop.idxs = c(new.pop.idxs, idxs.first.nonfit[idxs2])
}

# merge the stuff and return
return(new.pop.idxs)
}

makeSelector(
selector = selector,
name = "NSGA-II survival selector",
description = "nondominated sorting with potential crowding distance.",
supported.objectives = "multi-objective"
)
}
3 changes: 2 additions & 1 deletion man/setupGreedySelector.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions man/setupNondomSelector.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/setupRouletteWheelSelector.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/setupSimpleSelector.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/setupTournamentSelector.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 36e7580

Please sign in to comment.