File: multimin.ml

package info (click to toggle)
ocamlgsl 0.3.5-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,444 kB
  • ctags: 2,901
  • sloc: ml: 7,956; ansic: 6,796; makefile: 303; sh: 87; awk: 13
file content (107 lines) | stat: -rw-r--r-- 2,837 bytes parent folder | download | duplicates (4)
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
open Gsl_fun

let _ = 
  Gsl_error.init () 

let parab a b = 
  let f ~x =
    let xa = x.{0} -. a in
    let yb = x.{1} -. b in
    10. *. xa *. xa +. 20. *. yb *. yb +. 30.
  in
  let df ~x ~g =
    g.{0} <- 20. *. (x.{0} -. a) ;
    g.{1} <- 40. *. (x.{1} -. b)
  in
  let fdf ~x ~g = 
    let xa = x.{0} -. a in
    let yb = x.{1} -. b in
    g.{0} <- 20. *. xa ;
    g.{1} <- 40. *. yb ;
    10. *. xa *. xa +. 20. *. yb *. yb +. 30.
  in
  { multim_f   = f;
    multim_df  = df ;
    multim_fdf = fdf ; 
  } 


let epsabs = 1e-3
let maxiter = 50

let print_state n =
  let x = Gsl_vector.create n in
  let g = Gsl_vector.create n in
  fun mini iter ->
    let f = Gsl_multimin.Deriv.minimum ~x ~g mini in
    Printf.printf "%5d x=%.5f y=%.5f f=%10.5f g0=%.5g g1=%.5g\n"
      iter x.{0} x.{1} f g.{0} g.{1}

let mini kind gf start ~step ~tol=
  let minim = Gsl_multimin.Deriv.make kind 2 gf 
      ~x:(Gsl_vector.of_array start) ~step ~tol in
  let print_state = print_state 2 in
  let rec proc iter = 
    Gsl_multimin.Deriv.iterate minim ;
    let status = Gsl_multimin.Deriv.test_gradient minim epsabs in
    match status with
    | true -> 
	Printf.printf "Minimum found at:\n" ;
	print_state minim iter
    | false when iter >= maxiter -> 
	print_state minim iter ;
	Printf.printf "Too many iterations\n" ;
    | false ->
	print_state minim iter ;
	proc (succ iter)
  in
  Printf.printf "minimizer: %s\n" (Gsl_multimin.Deriv.name minim) ;
  proc 1

let print_state_simplex n =
  let x = Gsl_vector.create n in
  fun mini iter ->
    let f = Gsl_multimin.NoDeriv.minimum ~x mini in
    let ssval = Gsl_multimin.NoDeriv.size mini in
    Printf.printf "%5d x=%10.3f y=%10.3f f()=%-10.3f ssize=%.3f\n"
      iter x.{0} x.{1} f ssval
      
let mini_simplex kind gf ~start ~step_size =
  let minim = Gsl_multimin.NoDeriv.make kind 2 gf 
      ~x:(Gsl_vector.of_array start)
      ~step_size:(Gsl_vector.of_array step_size) in
  let print_state = print_state_simplex 2 in
  let rec proc iter = 
    Gsl_multimin.NoDeriv.iterate minim ;
    let status = Gsl_multimin.NoDeriv.test_size minim epsabs in
    match status with
    | true -> 
	Printf.printf "Minimum found at:\n" ;
	print_state minim iter
    | false when iter >= maxiter -> 
	print_state minim iter ;
	Printf.printf "Too many iterations\n" ;
    | false ->
	print_state minim iter ;
	proc (succ iter)
  in
  Printf.printf "minimizer: %s\n" (Gsl_multimin.NoDeriv.name minim) ;
  proc 1


open Gsl_multimin.Deriv
let _ = 
  List.iter
    (fun kind ->
      mini kind (parab 1. 2.) [| 5. ; 7. |] 0.01 1e-4 ;
      print_newline () ;
      flush stdout)
    [ CONJUGATE_FR ;
      CONJUGATE_PR ;
      VECTOR_BFGS ;
      STEEPEST_DESCENT ; ] ;

  mini_simplex Gsl_multimin.NoDeriv.NM_SIMPLEX
    (parab 1. 2.).multim_f
    ~start:[| 5. ; 7. |]
    ~step_size:[| 1. ; 1. |]