#!/usr/bin/env ruby # Ruby/GSL implementation of GSL "multiroot/test.c" require("gsl") require("./gsl_test2.rb") include GSL::Test include Math GC.disable def test_fdf(desc, fdf, initpt, factor, type) n = fdf.n x = eval("#{initpt}") if factor != 1.0 x = x.scale(factor) end s = GSL::MultiRoot::FdfSolver.alloc(type, n) s.set(fdf, x) iter = 0 begin iter += 1 status = s.iterate status = GSL::MultiRoot.test_residual(s.f, 0.0000001) end while status == GSL::CONTINUE and iter < 1000 jac, stat = GSL::MultiRoot.fdjacobian(fdf, s.x, s.f, GSL::SQRT_DBL_EPSILON) r = 0.0 sum = 0.0 for i in 0...n for j in 0...n u = jac[i,j] su = s.jac[i,j] r = (u - su).abs/(1e-6 + 1e-6 * u.abs) sum += r if (u - su).abs > (1e-6 + 1e-6 * u.abs) printf("broken jacobian %g\n", r) end end printf("avg r = %g\n", sum/(n*n)) end residual = 0.0 for i in 0...n residual += s.f[i].abs end GSL::Test::test(status, "#{type} on #{desc} (#{factor}), #{iter} iterations, residual = #{residual}") end def test_f(desc, fdf, initpt, factor, type) n = fdf.n x = eval("#{initpt}") x = x.scale(factor) function = GSL::MultiRoot::Function.alloc(fdf.f, fdf.n) s = GSL::MultiRoot::FSolver.alloc(type, n) s.set(function, x) iter = 0 begin iter += 1 status = s.iterate status = GSL::MultiRoot.test_residual(s.f, 0.0000001) end while status == GSL::CONTINUE and iter < 1000 residual = 0.0 for i in 0...n residual += s.f[i].abs end GSL::Test::test(status, "#{type} on #{desc} (#{factor}), #{iter} iterations, residual = #{residual}") end def roth_initpt return GSL::Vector.alloc(4.5, 3.5) end def wood_initpt return GSL::Vector.alloc(-3.0, -1.0, -3.0, -1.0) end def rosenbrock_initpt GSL::Vector.alloc(-1.2, 1.0) end roth_f = Proc.new { |x, f| u = x[0] v = x[1] f[0] = -13.0 + u + ((5.0 - v)*v - 2.0)*v; f[1] = -29.0 + u + ((v + 1.0)*v - 14.0)*v; } roth_df = Proc.new { |x, df| x1 = x[1] df.set(0, 0, 1.0) df.set(0, 1, -3 * x1 * x1 + 10 * x1 - 2) df.set(1, 0, 1.0) df.set(1, 1, 3 * x1 * x1 + 2 * x1 - 14) } rosenbrock_f = Proc.new { |x, f| x0 = x[0]; x1 = x[1] y0 = 1.0 - x0 y1 = 10*(x1 - x0*x0) f[0] = y0 f[1] = y1 GSL::SUCCESS } rosenbrock_df = Proc.new { |x, df| x0 = x[0] df00 = -1.0 df01 = 0.0 df10 = -20*x0 df11 = 10 df.set(0, 0, df00) df.set(0, 1, df01) df.set(1, 0, df10) df.set(1, 1, df11) GSL::SUCCESS } roth = GSL::MultiRoot::Function_fdf.alloc(roth_f, roth_df, 2) rosenbrock = GSL::MultiRoot::Function_fdf.alloc(rosenbrock_f, rosenbrock_df, 2) fsolvers = ["dnewton", "broyden", "hybrid", "hybrids"] fsolvers.each do |type| test_f("Roth", roth, "roth_initpt", 1.0, type) test_f("Rosenbrock", rosenbrock, "rosenbrock_initpt", 1.0, type) end exit f = 1.0 fdfsolvers = ["newton", "gnewton", "hybridj", "hybridsj"] fdfsolvers.each do |type| test_fdf("Roth", roth, "roth_initpt", f, type) end