Initial version of VNS algorithm #8
@ -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
|
||||||
|
@ -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) }
|
||||||
|
|
||||||
context 'when there is just one group in the table' do
|
describe '#cohesion_penalty' 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
|
||||||
|
allow(AffinityGroupsHierarchy.instance).to receive(:distance).and_return(distance)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the table contains two groups' do
|
context 'when they belong to the same group' do
|
||||||
let(:table) do
|
let(:distance) { 0 }
|
||||||
guests = create_list(:guest, 3)
|
|
||||||
guests[0].affinity_group_list.add('family')
|
it { expect(calculator.send(:cohesion_penalty)).to eq(0) }
|
||||||
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 completely unrelated groups' do
|
||||||
|
let(:distance) { nil }
|
||||||
|
|
||||||
|
it { expect(calculator.send(:cohesion_penalty)).to eq(1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the table contains three groups' do
|
context 'when they belong to groups at a distance of 1' do
|
||||||
let(:table) do
|
let(:distance) { 1 }
|
||||||
guests = create_list(:guest, 3)
|
|
||||||
guests[0].affinity_group_list.add('family')
|
it { expect(calculator.send(:cohesion_penalty)).to eq(0.5) }
|
||||||
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 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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user