New crystaller here.
Requesting code review to make this more Crystally without classes, and faster.
Can I enable something like --fast-math? Disable index checking?
Does anyone have some nice guides on how to profile Crystal?
def calculate_score(xs : Array(Float64))
s = 0.0
xs.size.times { |i| s += xs[i] * xs[i] } # f(0) = 0, n params
s
end
start_dt = Time.utc
params = 100
bounds = -10.0..10.0
generations = 1000
print_each = 100
pop_size = 100
mutate_range = 0.2..0.95
crossover_range = 0.1..1.0
crossover = 0.9
mutate = 0.4
trial = Array.new(params, 0.0)
pop = Array.new(pop_size) { Array.new(params) { rand(bounds) } }
scores = Array.new(pop_size) { |i| calculate_score(pop[i]) }
generations.times do |g|
crossover, mutate = rand(crossover_range), rand(mutate_range)
pop_size.times do |i|
x0, x1, x2, xt = pop.sample, pop.sample, pop.sample, pop[i]
params.times { |j| trial[j] = rand < crossover ? (x0[j] + (x1[j] - x2[j]) * mutate).clamp(bounds) : xt[j] }
trial_score = calculate_score(trial)
pop[i], scores[i] = trial.dup, trial_score if trial_score < scores[i]
end
if g.remainder(print_each) == 0
mean = scores.sum / pop_size
puts "GEN #{g}"
puts "MEAN #{mean}"
#best = scores.min
#puts "BEST #{best.xs}"
end
end
end_dt = Time.utc
puts end_dt - start_dt