Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions examples/tsp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,40 @@
require 'alns/select/roulette_wheel'
require 'alns/stop/max_iterations'
require 'alns/stop/max_runtime'
require 'alns/random/random'

module TSP
def self.solve
write_dot = false
seed = 1234
secure_random = false

OptionParser.new do |parser|
parser.banner = 'Usage: tsp.rb [options]'

parser.on('-d', '--dot', 'write a dot file with result') do |v|
parser.on('-d', '--dot', 'write a dot file with the result') do
write_dot = true
end

parser.on('-sSEED', '--seed=SEED', Integer, 'specify seed') do |v|
seed = v
end

parser.on('-r', '--secure-random', 'use secure random') do
secure_random = true
end
end.parse!

nodes = make_nodes(COORDS)
dists = make_dists(COORDS)

solver = ALNS::Solver.new(Random.new(1234))
rnd = if secure_random
ALNS::Random::Random.new
else
Random.new(seed)
end

solver = ALNS::Solver.new(rnd)

init_sol = TspState.new(nodes, {}, dists)
init_sol = greedy_repair(init_sol, solver.rnd)
Expand Down Expand Up @@ -256,17 +273,21 @@ def initialize(nodes, edges, dists)

def initialize_copy(original)
super
@nodes = original.nodes
# @nodes is frozen
@edges = original.edges.dup
@dists = original.dists
# @dists is frozen
@objective = nil
end

def objective
total_dist = 0.0
@edges.each do |from, to|
total_dist += @dists[from][to]
if @objective.nil?
total_dist = 0.0
@edges.each do |from, to|
total_dist += @dists[from][to]
end
@objective = total_dist
end
total_dist
@objective
end
end

Expand Down
11 changes: 3 additions & 8 deletions lib/alns/math.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
# frozen_string_literal: true

module ALNS
EPSILON = 1e-9

def self.close?(a, b, epsilon = EPSILON) # rubocop:disable Naming/MethodParameterName
(a - b).abs <= epsilon
end

def self.weighted_random_index(rnd, weights)
raise 'Invalid weights: Array is empty' if weights.empty?
return 0 if weights.size == 1
Expand All @@ -17,9 +11,10 @@ def self.weighted_random_index(rnd, weights)
weights.each_with_index do |weight, index|
adjusted_value -= weight

return index if adjusted_value <= 0 || close?(adjusted_value, 0)
return index if adjusted_value <= 0
end

raise "Arithmetic error: sum=#{total_sum}, adjusted_value=#{adjusted_value}, weights=#{weights.inspect}"
# we will only be here when errors accumulate
weights.length - 1
end
end
17 changes: 17 additions & 0 deletions lib/alns/random/random.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require 'securerandom'

module ALNS
module Random
class Random
def rand(max = nil)
if max.nil?
SecureRandom.random_number
else
SecureRandom.random_number(max)
end
end
end
end
end
5 changes: 0 additions & 5 deletions test/math_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ def setup
@rnd = Random.new(123)
end

def test_close
assert ALNS.close?(1, 1.0000000001)
assert !ALNS.close?(1, 1.0000001)
end

def test_weighted_random_index
tests = [
{ weights: [1.0], want: 0 }, # one element
Expand Down