From c2feb229d28c6ef63e5e83f1c423c5476bbc12fb Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Fri, 2 Aug 2024 18:42:24 +0200 Subject: [PATCH] Use immutable data structures to calculate variations --- app/services/tables/distribution.rb | 19 +++++++++++++++++++ app/services/tables/swap.rb | 26 ++++++++++++-------------- app/services/tables/table.rb | 6 ++++++ app/services/vns/engine.rb | 2 +- db/seeds.rb | 3 +-- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/app/services/tables/distribution.rb b/app/services/tables/distribution.rb index 5fe0911..9b5f4ba 100644 --- a/app/services/tables/distribution.rb +++ b/app/services/tables/distribution.rb @@ -12,6 +12,22 @@ module Tables @tables.values.freeze end + def deep_freeze + @tables.each_value(&:freeze) + @tables.freeze + freeze + end + + def replace(table) + @tables[table.id] = table + end + + def dup + super.tap do |new_distribution| + new_distribution.instance_variable_set(:@tables, @tables.dup) + end + end + def <<(array) Table.new(array).tap do |table| @tables[table.id] = table @@ -22,6 +38,9 @@ module Tables @tables = {} self << people.slice!(0..rand(@min_per_table..@max_per_table)) while people.any? + + @tables.freeze + freeze end def discomfort diff --git a/app/services/tables/swap.rb b/app/services/tables/swap.rb index 631b49b..d77e2a4 100644 --- a/app/services/tables/swap.rb +++ b/app/services/tables/swap.rb @@ -8,25 +8,23 @@ module Tables def each @initial_solution.tables.combination(2) do |table_a, table_b| table_a.product(table_b).each do |(person_a, person_b)| - original_discomfort_a = table_a.reset - original_discomfort_b = table_b.reset + new_solution = @initial_solution.dup - table_a.delete(person_a) - table_b.delete(person_b) + new_table_a = table_a.dup + new_table_b = table_b.dup - table_a << person_b - table_b << person_a + new_solution.replace(new_table_a) + new_solution.replace(new_table_b) - yield(@initial_solution) - ensure - table_a.delete(person_b) - table_b.delete(person_a) + new_table_a.delete(person_a) + new_table_b.delete(person_b) - table_a << person_a - table_b << person_b + new_table_a << person_b + new_table_b << person_a - table_a.discomfort = original_discomfort_a - table_b.discomfort = original_discomfort_b + new_solution.freeze + + yield(new_solution) end end end diff --git a/app/services/tables/table.rb b/app/services/tables/table.rb index 0c9dc2b..54fd8cc 100644 --- a/app/services/tables/table.rb +++ b/app/services/tables/table.rb @@ -18,5 +18,11 @@ module Tables def discomfort @discomfort ||= DiscomfortCalculator.new(self).calculate end + + def dup + super.tap do |new_table| + new_table.discomfort = nil + end + end end end diff --git a/app/services/vns/engine.rb b/app/services/vns/engine.rb index 5c260aa..d5474b9 100644 --- a/app/services/vns/engine.rb +++ b/app/services/vns/engine.rb @@ -26,7 +26,7 @@ module VNS optimize(perturbation.new(@best_solution)) end - @best_solution + @best_solution end private diff --git a/db/seeds.rb b/db/seeds.rb index 162a80f..eb08d7a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,4 +1,4 @@ -NUMBER_OF_GUESTS = 50 +NUMBER_OF_GUESTS = ENV['SEED_GUEST_COUNT'].presence.to_i || 50 TablesArrangement.delete_all Expense.delete_all @@ -21,7 +21,6 @@ Expense.create!(name: 'Transportation', amount: 3000, pricing_type: 'fixed') Expense.create!(name: 'Invitations', amount: 200, pricing_type: 'fixed') Expense.create!(name: 'Cake', amount: 500, pricing_type: 'fixed') - samples = { close_family_a: 10, close_family_b: 10,