Initial version of VNS algorithm #8

Merged
bustikiller merged 20 commits from vns into main 2024-08-01 18:27:42 +00:00
2 changed files with 44 additions and 34 deletions
Showing only changes of commit 8c6974a1e5 - Show all commits

View File

@ -6,17 +6,19 @@ module Tables
end end
def calculate def calculate
group_merging cohesion_penalty
end end
private private
def group_merging def cohesion_penalty
10 * (number_of_groups - 1) table.map { |guest| guest.affinity_group_list.first }.combination(2).sum do |a, b|
end distance = AffinityGroupsHierarchy.instance.distance(a, b)
next 1 if distance.nil?
next 0 if distance.zero?
def number_of_groups Rational(distance, distance + 1)
table.map(&:affinity_groups).flatten.uniq.count end
end end
end end
end end

View File

@ -1,42 +1,50 @@
require 'rails_helper' require 'rails_helper'
module Tables module Tables
RSpec.describe DiscomfortCalculator do RSpec.describe DiscomfortCalculator do
describe '#group_merging' do let(:calculator) { described_class.new(table) }
let(:calculator) { described_class.new(table) }
describe '#cohesion_penalty' do
context 'when there is just one group in the table' do context 'when the table contains just two guests' do
let(:table) do let(:table) do
create_list(:guest, 3).each do |guest| [
guest.affinity_group_list.add('family') create(:guest, affinity_group_list: ['family']),
guest.save! create(:guest, affinity_group_list: ['friends'])
end ]
end end
it { expect(calculator.send(:group_merging)).to eq(0) } before do
end allow(AffinityGroupsHierarchy.instance).to receive(:distance).and_return(distance)
context 'when the table contains two groups' do
let(:table) do
guests = create_list(:guest, 3)
guests[0].affinity_group_list.add('family')
guests[1].affinity_group_list.add('friends')
guests[2].affinity_group_list.add('family')
guests.each(&:save!)
end end
it { expect(calculator.send(:group_merging)).to eq(10) } context 'when they belong to the same group' do
end let(:distance) { 0 }
context 'when the table contains three groups' do it { expect(calculator.send(:cohesion_penalty)).to eq(0) }
let(:table) do
guests = create_list(:guest, 3)
guests[0].affinity_group_list.add('family')
guests[1].affinity_group_list.add('friends')
guests[2].affinity_group_list.add('work')
guests.each(&:save!)
end end
it { expect(calculator.send(:group_merging)).to eq(20) } context 'when they belong to completely unrelated groups' do
let(:distance) { nil }
it { expect(calculator.send(:cohesion_penalty)).to eq(1) }
end
context 'when they belong to groups at a distance of 1' do
let(:distance) { 1 }
it { expect(calculator.send(:cohesion_penalty)).to eq(0.5) }
end
context 'when they belong to groups at a distance of 2' do
let(:distance) { 2 }
it { expect(calculator.send(:cohesion_penalty)).to eq(Rational(2, 3)) }
end
context 'when they belong to groups at a distance of 3' do
let(:distance) { 3 }
it { expect(calculator.send(:cohesion_penalty)).to eq(Rational(3, 4)) }
end
end end
end end
end end