Module: Moea::Pareto

Included in:
WeakPareto
Defined in:
../lib/pareto.rb

Overview

The infrastructure for the multiobjective optimisation. See dces.essex.ac.uk/staff/rpoli/gp-field-guide/92KeepingtheObjectivesSeparate.html

The user-defined class can include Pareto module which

  1. brings the dominates? method and <=> operator,

  2. offers the supporting methods for the Crowding distance computation,

Class methods Pareto.nondominated and Pareto.dominated implement selections from the array of Pareto-aware instances.

Defined Under Namespace

Classes: Objective

Constant Summary

@@objectives =
{}

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) clear_objectives(user)

Clear all objectives for a given user class



91
92
93
# File '../lib/pareto.rb', line 91

def Pareto.clear_objectives user
  user.objectives.clear if defined? user.objectives
end

+ (Object) dominated(population)

Return the dominated subset of the population, ie. the population with Pareto.nondominated members excluded.



167
168
169
170
171
172
173
174
175
176
177
178
179
# File '../lib/pareto.rb', line 167

def Pareto.dominated population
  dominated = []
  population.each_with_index do |individual1, index1|
    population.each_with_index do |individual2, index2|
      next if index1==index2
      if individual2.dominates? individual1
        dominated.push individual1
        break
      end
    end
  end
  dominated
end

+ (Object) maximize(user, symb)

Shorthand for


  Pareto.objective( user, symb, :maximize )


121
122
123
# File '../lib/pareto.rb', line 121

def Pareto.maximize( user, symb ) 
  Pareto.objective( user, symb, :maximize )   
end

+ (Object) minimize(user, symb)

Shorthand for


  Pareto.objective( user, symb, :minimize )


115
116
117
# File '../lib/pareto.rb', line 115

def Pareto.minimize( user, symb ) 
  Pareto.objective( user, symb, :minimize )   
end

+ (Object) nondominated(population)

Return the nondominated subset of the population. For each member M of the nondominated subset holds that there is no other member of the population dominating M.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File '../lib/pareto.rb', line 150

def Pareto.nondominated population
  front = []
  population.each_with_index do |individual1, index1|
    nondominated = true
    population.each_with_index do |individual2, index2|
      next if index1==index2
      if individual2.dominates? individual1
        nondominated = false
        break
      end
    end
    front.push individual1 if nondominated
  end
  front
end

+ (Object) objective(user, symb, dir)

Declare the objective in the user-defined class.


  user .. the name of the user-defined class
  symb .. symbol (an accessor) of the single objective
  dir .. direction of the optimisation. 
  

The possible values of dir are:


  :maximize .. the objective should be maximized (the individual with a greater symb value is better),
  :minimize .. the objective should be minimized (the individual with a smaller symb value is better), 
  proc { |a,b| ... } .. (a procedure returns -1 if a is better than b, returns 1 if b is better than a, returns 0 if a and b have equal qualities)
  

For instance:


  class BasicPair < Struct.new( :up, :down )
    include Pareto
    Pareto.objective BasicPair, :down, :minimize
    Pareto.objective BasicPair, :up, :maximize 
  end
  

declares the user-defined BasicPair structure with two objectives (:up, :down). BasicPair#up is maximized and BasicPair#down is minimized. The BasicPair#dominates? and BasicPair#<=> methods are now defined for the use within the library, as well as BasicPair.objective_symbols.

Short versions of Pareto.objective can also be used:


  class BasicPair < Struct.new( :up, :down )
    include Pareto
    minimize :down
    maximize :up
  end


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File '../lib/pareto.rb', line 64

def Pareto.objective( user, symb, dir )
  
  how = case dir
  when :maximize
    eval "proc { |a,b| a.#{symb}<=>b.#{symb} }"
  when :minimize
    eval "proc { |a,b| b.#{symb}<=>a.#{symb} }"   
  else
    dir
  end

  user.class_eval %Q{

                      @objectives = []

                      class << self
                        attr_accessor :objectives 
                      end

                    } unless defined? user.objectives


  user.objectives << Objective.new( symb, how )
 
end

+ (Object) objective_best(population, user, symb)

Return the best member of the population (by the means of symb objective of the user class).



143
144
145
146
# File '../lib/pareto.rb', line 143

def Pareto.objective_best( population, user, symb )
  objective = user.objectives.find { |obj| obj.symb == symb }
  population.min { |a,b| objective.how.call( b, a ) }    
end

+ (Object) objective_sort(population, user, symb)

Return the population sorted by the symb objective of the user class.



137
138
139
140
# File '../lib/pareto.rb', line 137

def Pareto.objective_sort( population, user, symb )
  objective = user.objectives.find { |obj| obj.symb == symb } 
  population.sort { |a,b| objective.how.call( b, a ) }   
end

+ (Object) objective_symbols(user)

Return the array of all objective symbols declared by the Pareto.objective for the class user.



126
127
128
# File '../lib/pareto.rb', line 126

def Pareto.objective_symbols user
  user.objectives.map { |obj| obj.symb }
end

Instance Method Details

- (Object) <=>(other)

a<=>b returns:


  -1 if a.dominates? b,
  1 if b.dominates? a,
  0 otherwise.

Note: Assuming that if x dominates y then y does not dominate x (see WeakPareto module).



107
108
109
110
111
# File '../lib/pareto.rb', line 107

def <=>(other)
  return -1 if dominates? other
  return 1 if other.dominates? self
  return 0
end

- (Boolean) dominates?(other)

Given that a and b are individuals of the same class, a.dominates?(b) returns true if:

  1. there is no such objective in which the b is better than a, and

  2. there is at least one objective in which the a is better than b.

Returns:

  • (Boolean)


98
99
100
# File '../lib/pareto.rb', line 98

def dominates? other
  dominates_core( other, false )
end

- (Object) objective_symbols

Shorthand for


  Pareto.objective_symbols( self.class )


132
133
134
# File '../lib/pareto.rb', line 132

def objective_symbols
  Pareto.objective_symbols self.class
end