The problem is not so easy o resolve
Here a solution, with Simulated annealing algorithm.
############# Simulated annealing definitions
l=(1..20).to_a # list of value
$size=l.size
#--------- make initial solution
aa=[[],[],[]] # decompose l in 3 lists
aa[rand(0...aa.size)] << l.delete_at(rand(l.size)) while l.size>0
#-- add empty value (lists can have different size...)
aa.each {|a| a.concat([0]*(1+a.size/4))}
#--------- function to optimize : sum of each listes should be near equals
def performence(aa)
res=aa.map {|l| l.reduce(0,:+) }
-1.0*res.combination(2).map { |a,b| (a-b)**2 }.reduce(0,:+)
end
#------- Acceptance probabilities
# could be best :)
def opt(delta,temp)
rand(100)<temp/2
end
############################################################
# Simulated annealing Algorithm
############################################################
##################
def choose(n,diff)
i=diff
i=rand(0...n) while i==diff
i
end
def permute(array,from,to)
array[from.first][from.last],array[to.first][to.last]=
array[to.first][to.last],array[from.first][from.last]
end
last_perf=0
puts "initale perf=%f" % performence(aa)
100.downto(0) { |temp|
(400*$size).times { |r|
i1=choose(aa.size,-1)
i2=choose(aa.size,i1)
ii1=choose(aa[i1].size,-1)
ii2=choose(aa[i2].size,-1)
permute(aa,[i1,ii1],[i2,ii2])
perf=performence(aa)
delta=perf-last_perf
if delta<0
if opt(delta,temp)
#puts("xxtemp=%4d => perf=%6f" % [temp,perf]) if r%300>=0
last_perf=perf
else
permute(aa,[i1,ii1],[i2,ii2]) # undo
end
else
if delta>0
#puts("**temp=%4d => perf=%6f/%6f" % [temp,perf,last_perf]) if r%300>=0
last_perf=perf
else
permute(aa,[i1,ii1],[i2,ii2]) # undo
end
end
}
}
puts "\n\nperf=%d" % performence(aa)
aa.each {|a| puts "(%4d) <= %s" % [a.reduce(0,:+),a.select {|x|x>0}.sort.inspect] }
Example of execution:
initale perf=-12462.000000
perf=0
( 70) <= [10, 11, 14, 15, 20]
( 70) <= [1, 3, 4, 5, 6, 8, 12, 13, 18]
( 70) <= [2, 7, 9, 16, 17, 19]
Please, use triple-backcote (
``` ) for writing code n this forum