# Feedback on differential evolution algorithm

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``````

Hi @peheje,
you can do something like this for the first function:

``````def calculate_score(xs : Array(Float64))
xs.sum { |i| i**2}
end
``````

This should be faster, and is clean enough to not require a new definition if you want Regarding the rest, your code looks good 1 Like

In the vein of using existing `Enumerable` methods:

``````scores = pop.map { |arr| calculate_score(arr) }
``````

So succinct and pretty, thanks! Had a feeling it could be easier. 1 Like

Really cool, thanks mate. 1 Like