Eric
5/16/2006 5:16:00 AM
Thanks all for the advice. This post will be shorter. :)
One thing I noticed when making these changes was that every time I
made the code more compact, it seemed to run slower. Is this normal
for ruby? (I doubt this would be nearly as much of an issue if I
weren't number crunching.)
# From Java program
# x= 8.48550
# y=-4.42140
# z=-2.90655
# From Ruby program
# x= 8.485481
# y=-4.421231
# z=-2.906773
class Eq3Var
def initialize( *args )
@xCo, @xPow, @yCo, @yPow, @zCo, @zPow, @const = args.map{ |x|
x.to_f }
end
def eval (x, y, z)
@xCo * x**@xPow + @yCo * y**@yPow + @zCo * z**@zPow + @const
end
end
class Solver
attr_reader :range, :step, :bestSol
def initialize()
*@eqs = Eq3Var.new(1, 1, -1, 1, 1, 1, -10), Eq3Var.new(1, 2, 1, 2,
1, 2, -100), Eq3Var.new(1, 3, 1, 3, 1, 3, -500)
@range, @step, @factor, *@bestSol = 10.0, 0.5, 5.0, 0.0, 0.0, 0.0
end
def sumSquare( *args )
s = 0
args.each do |x|
s += x**2.0
end
return s
end
def force()
puts "Starting best solution: #{@bestSol.join(', ')}"
min = sumSquare(@eqs[0].eval(*@bestSol), @eqs[1].eval(*@bestSol),
@eqs[2].eval(*@bestSol))
*init = *@bestSol
i, j, k = init[0] - @range, init[1] - @range, init[2] - @range
while i < init[0] + @range
while j < init[1] + @range
while k < init[2] + @range
t = sumSquare(@eqs[0].eval(i, j, k), @eqs[1].eval(i, j, k),
@eqs[2].eval(i, j, k))
if (t < min)
min = t
@bestSol = i, j, k
#puts "new min #{t}"
end
k = k + @step
end
j, k = j + @step, init[2] - @range
end
i, j, k = i + @step, init[1] - @range, init[2] - @range
#puts "#{@bestSol[0]} #{@bestSol[1]} #{@bestSol[2]} a is
#{@eqs[0].eval(@bestSol[0], @bestSol[1], @bestSol[2])} - b is
#{@eqs[1].eval(@bestSol[0], @bestSol[1], @bestSol[2])} - c is
#{@eqs[2].eval(@bestSol[0], @bestSol[1], @bestSol[2])}"
end
@range, @step = @range / @factor, @step / @factor
puts "a is #{@eqs[0].eval(@bestSol[0], @bestSol[1], @bestSol[2])} - b
is #{@eqs[1].eval(@bestSol[0], @bestSol[1], @bestSol[2])} - c is
#{@eqs[2].eval(@bestSol[0], @bestSol[1], @bestSol[2])}"
end
end
mySolver = Solver.new()
n = ' '
itr = 0
10.times do
mySolver.force()
itr = itr + 1
puts "In #{itr} itterations, the best solution so far:
#{mySolver.bestSol.join(', ')}. Refine with range of #{mySolver.range}
and step of #{ mySolver.step}"
end
# The code looks prettier, but it runs slower :(