Class: DSPy::Teleprompt::GEPA::ParetoSelector

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dspy/teleprompt/gepa.rb

Overview

ParetoSelector: Multi-objective optimization using Pareto frontier analysis

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(evaluator:, config:) ⇒ ParetoSelector



2220
2221
2222
2223
# File 'lib/dspy/teleprompt/gepa.rb', line 2220

def initialize(evaluator:, config:)
  @evaluator = evaluator
  @config = config
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



2217
2218
2219
# File 'lib/dspy/teleprompt/gepa.rb', line 2217

def config
  @config
end

#evaluatorObject (readonly)

Returns the value of attribute evaluator.



2214
2215
2216
# File 'lib/dspy/teleprompt/gepa.rb', line 2214

def evaluator
  @evaluator
end

Instance Method Details

#select_parents(population_with_scores, count:) ⇒ Object



2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
# File 'lib/dspy/teleprompt/gepa.rb', line 2227

def select_parents(population_with_scores, count:)
  return [] if population_with_scores.empty?
  return population_with_scores.map(&:first) if count >= population_with_scores.size

  # Combine tournament and Pareto-based selection for parent selection
  selected = []

  count.times do
    parent = tournament_selection(population_with_scores)
    selected << parent
  end

  selected
end

#select_survivors(population_with_scores, count:) ⇒ Object



2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
# File 'lib/dspy/teleprompt/gepa.rb', line 2244

def select_survivors(population_with_scores, count:)
  return [] if population_with_scores.empty?
  return population_with_scores.map(&:first) if count >= population_with_scores.size

  scores = population_with_scores.map(&:last)

  # Find Pareto frontier first
  pareto_frontier = find_pareto_frontier(scores)
  frontier_indices = scores.each_index.select { |i| pareto_frontier.include?(scores[i]) }
  frontier_programs = frontier_indices.map { |i| population_with_scores[i].first }

  if frontier_programs.size >= count
    # Use diversity selection within frontier
    frontier_with_scores = frontier_indices.map { |i| population_with_scores[i] }
    return diversity_selection(frontier_with_scores, count: count)
  else
    # Include all frontier + fill remaining with elite selection
    remaining_count = count - frontier_programs.size
    remaining_population = population_with_scores.reject.with_index { |_, i| frontier_indices.include?(i) }

    additional = elite_selection(remaining_population, count: remaining_count)
    frontier_programs + additional
  end
end