diff --git a/app/services/vns/engine.rb b/app/services/vns/engine.rb index dc0feff..a5f680c 100644 --- a/app/services/vns/engine.rb +++ b/app/services/vns/engine.rb @@ -5,6 +5,7 @@ module VNS class Engine PERTURBATION_SIZES = [1, 1, 1, 2, 2, 3].freeze + ITERATIONS = 50 class << self def sequence(elements) elements = elements.to_a @@ -26,6 +27,14 @@ module VNS @perturbations << klass end + def notify_progress(&block) + @progress_notifier = block + end + + def on_better_solution(&block) + @better_solution_notifier = block + end + attr_writer :initial_solution def run @@ -40,18 +49,24 @@ module VNS run_all_optimizations + @progress_notifier&.call(Rational(1, ITERATIONS + 1)) + best_solution = @current_solution - 50.times do + ITERATIONS.times do |iteration| @current_solution = Tables::WheelSwap.new(best_solution).call(PERTURBATION_SIZES.sample) @best_score = @target_function.call(@current_solution) Rails.logger.debug { "After perturbation: #{@best_score}" } run_all_optimizations + @progress_notifier&.call(Rational(iteration + 1, ITERATIONS + 1)) + next unless best_solution.discomfort > @current_solution.discomfort best_solution = @current_solution + @better_solution_notifier&.call(best_solution) + Rails.logger.debug do "Found better solution after perturbation optimization: #{@current_solution.discomfort}" end diff --git a/lib/tasks/vns.rake b/lib/tasks/vns.rake index 9554a76..b7c38ac 100644 --- a/lib/tasks/vns.rake +++ b/lib/tasks/vns.rake @@ -21,6 +21,14 @@ namespace :vns do engine.target_function(&:discomfort) + engine.notify_progress do |current_progress| + Rails.logger.info "Progress: #{(current_progress * 100.0).round(2)}%" + end + + engine.on_better_solution do |better_solution| + Rails.logger.info "New best solution found with discomfort: #{better_solution.discomfort}" + end + solution = Rails.benchmark('VNS Benchmarking') { engine.run } Rails.logger.info "Best solution found with discomfort: #{solution.discomfort}"