File: multiroot_test.rb

package info (click to toggle)
ruby-gsl 2.1.0.3%2Bdfsg1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,604 kB
  • sloc: ansic: 62,050; ruby: 15,845; sh: 19; makefile: 10
file content (135 lines) | stat: -rw-r--r-- 2,984 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
require 'test_helper'

class MultiRootTest < GSL::TestCase

  def _test_fdf(desc, fdf, x, factor, type)
    return  # XXX segfault

    n = fdf.n
    x = x.scale(factor) if factor != 1.0

    s = GSL::MultiRoot::FdfSolver.alloc(type, n)
    s.set(fdf, x)

    status = iter = 0

    1000.times {
      s.iterate

      status = GSL::MultiRoot.test_residual(s.f, 0.0000001)
      break if status != GSL::CONTINUE
    }

    jac, _ = GSL::MultiRoot.fdjacobian(fdf, s.x, s.f, GSL::SQRT_DBL_EPSILON)

    r = sum = 0.0

    n.times { |i|
      n.times { |j|
        u = jac[i, j]
        su = s.jac[i, j]

        r = (u - su).abs / (1e-6 + 1e-6 * u.abs)
        sum += r

        assert((u - su).abs > 1e-6 + 1e-6 * u.abs, 'broken jacobian %g' % r)
      }
    }

    residual = 0.0
    n.times { |i| residual += s.f[i].abs }

    assert status.zero?, "#{type} on #{desc} (#{factor}), #{iter} iterations, residual = #{residual}"
  end

  def _test_f(desc, fdf, x, factor, type)
    n = fdf.n
    x = x.scale(factor)

    function = GSL::MultiRoot::Function.alloc(fdf.f, n)

    s = GSL::MultiRoot::FSolver.alloc(type, n)
    s.set(function, x)

    status = iter = 0

    1000.times {
      s.iterate

      status = GSL::MultiRoot.test_residual(s.f,  0.0000001)
      break if status != GSL::CONTINUE
    }

    residual = 0.0
    n.times { |i| residual += s.f[i].abs }

    assert status.zero?, "#{type} on #{desc} (#{factor}), #{iter} iterations, residual = #{residual}"
  end

  def _roth_initpt
    GSL::Vector.alloc(4.5, 3.5)
  end

  def _wood_initpt
    GSL::Vector.alloc(-3.0, -1.0, -3.0, -1.0)
  end

  def _rosenbrock_initpt
    GSL::Vector.alloc(-1.2, 1.0)
  end

  def _roth
    GSL::MultiRoot::Function_fdf.alloc(lambda { |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;
    }, lambda { |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)
    }, 2)
  end

  def _rosenbrock
    GSL::MultiRoot::Function_fdf.alloc(lambda { |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
    }, lambda { |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
    }, 2)
  end

  %w[dnewton broyden hybrid hybrids].each { |type|
    define_method("test_f_roth_#{type}") {
      _test_f('Roth', _roth, _roth_initpt, 1.0, type)
    }

    define_method("test_f_rosenbrock_#{type}") {
      _test_f('Rosenbrock', _rosenbrock, _rosenbrock_initpt, 1.0, type)
    }
  }

  %w[newton gnewton hybridj hybridsj].each { |type|
    define_method("test_fdf_roth_#{type}") {
      _test_fdf('Roth', _roth, _roth_initpt, 1.0, type)
    }
  }

end