|
|
begin
require 'lib/charlie'
rescue LoadError
require 'rubygems'
require 'charlie'
end
class Symbol
# This one works with ALL the RVMs. Charlie's default or the Rubinius' one doesn't work with Rubinius!
def to_proc
Proc.new { |*args|
obj = args.shift
args.empty? ? obj.__send__(self) : obj.__send__(self, *args)
}
end if RUBY_VERSION < '1.9'
end
def TSPGenotype(costs)
n = costs.size
elements = (0...n).to_a
Class.new(Genotype) {
define_method(:size){ n }
define_method(:elements){ elements }
define_method(:fitness){
d=0
(genes + [genes[0]]).each_cons(2) do |a,b|
d += costs[a][b]
end
-d
}
def initialize
@genes = elements.dup.shuffle
end
def to_s
@genes.inspect
end
use TournamentSelection,
PCrossN(EdgeRecombinationCrossover=>0.02, PermutationCrossover=>0.75),
PMutateN(InversionMutator=>0.4,InsertionMutator=>0.4)
cache_fitness
}
end
class TSPSolver
def initialize(costs = {})
@costs = costs
@genotype = TSPGenotype(costs)
end
def solve!
population = Population.new(@genotype,100).evolve_silent(1000)
fittest = population[0]
solution = @costs.sort_by{ |point| fittest.genes.index(point[0]) }
# p solution
puts fittest.fitness
puts fittest
end
# The coords hash must be in the following form:
# {
# 0 => [x1, y1],
# 1 => [x2, y2],
# etc...
# }
# where x1,y1 are Integers and represent the cartesian coordinates of the "city" of the associated key (number).
def self.from_cartesian_coords(coords = {}, real_distance = false)
costs = {}
coords.each do |point, v|
costs[point] = {}
end
if real_distance
raise "Real distance not implemented"
else
coords.each do |a_key, a_values|
coords.each do |b_key, b_values|
if a_key != b_key and costs[a_key][b_key] == nil
d = Math.sqrt( (a_values[0]-b_values[0])**2 + (a_values[1]-b_values[1])**2 )
costs[a_key][b_key],costs[b_key][a_key] = d,d
end
end
end
end
solver = self.new(costs)
end
def self.example(n = 100)
grid = (0...n).map{|i| (0...n).map{|j| [i,j] } }.inject{|a,b|a+b}
tmp_grid = Array.new(grid)
coords = {}
n.times do |city_num|
coords[city_num] = tmp_grid.delete_at((rand(10000) - coords.size).to_i)
end
example = self.from_cartesian_coords(coords)
end
end
TSPSolver.example.solve!
|