~ubuntu-branches/ubuntu/feisty/libctl/feisty

« back to all changes in this revision

Viewing changes to base/simplex.scm

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2002-04-17 10:36:45 UTC
  • Revision ID: james.westby@ubuntu.com-20020417103645-29vomjspk4yf4olw
Tags: upstream-2.1
ImportĀ upstreamĀ versionĀ 2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
; libctl: flexible Guile-based control files for scientific software
 
2
; Copyright (C) 1998, 1999, 2000, 2001, 2002, Steven G. Johnson
 
3
;
 
4
; This library is free software; you can redistribute it and/or
 
5
; modify it under the terms of the GNU Lesser General Public
 
6
; License as published by the Free Software Foundation; either
 
7
; version 2 of the License, or (at your option) any later version.
 
8
;
 
9
; This library is distributed in the hope that it will be useful,
 
10
; but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
; Lesser General Public License for more details.
 
13
;
 
14
; You should have received a copy of the GNU Lesser General Public
 
15
; License along with this library; if not, write to the
 
16
; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
; Boston, MA  02111-1307, USA.
 
18
;
 
19
; Steven G. Johnson can be contacted at stevenj@alum.mit.edu.
 
20
 
 
21
; ****************************************************************
 
22
; The Nelder-Mead simplex algorithm for multidimensional minimization.
 
23
; See the simplex-minimize function, below.
 
24
 
 
25
(define (ax+by a x b y)
 
26
  (define (cdr-null x) (if (null? x) '() (cdr x)))
 
27
  (if (and (null? x) (null? y))
 
28
      '()
 
29
      (let ((ax (if (null? x) 0 (* a (car x))))
 
30
            (by (if (null? y) 0 (* b (car y)))))
 
31
        (cons (+ ax by) (ax+by a (cdr-null x) b (cdr-null y))))))
 
32
 
 
33
(define (simplex-point x val) (cons x val))
 
34
(define simplex-point-x car)
 
35
(define simplex-point-val cdr)
 
36
 
 
37
(define (simplex-high s)
 
38
  (car (sort s (lambda (s1 s2) (> (simplex-point-val s1)
 
39
                                  (simplex-point-val s2))))))
 
40
(define (simplex-high2 s)
 
41
  (cadr (sort s (lambda (s1 s2) (> (simplex-point-val s1)
 
42
                                   (simplex-point-val s2))))))
 
43
(define (simplex-low s)
 
44
  (car (sort s (lambda (s1 s2) (< (simplex-point-val s1)
 
45
                                  (simplex-point-val s2))))))
 
46
 
 
47
(define (simplex-replace s s-old s-new)
 
48
  (if (null? s)
 
49
      '()
 
50
      (if (eq? (car s) s-old)
 
51
          (cons s-new (cdr s))
 
52
          (cons (car s) (simplex-replace (cdr s) s-old s-new)))))
 
53
 
 
54
(define (simplex-sum-x s)
 
55
  (if (null? s)
 
56
      '()
 
57
      (ax+by 1 (simplex-point-x (car s)) 1 (simplex-sum-x (cdr s)))))
 
58
 
 
59
(define (simplex-centroid-x s)
 
60
  (let ((sum (ax+by 1 (simplex-sum-x s) 
 
61
                    -1 (simplex-point-x (simplex-high s)))))
 
62
    (ax+by (/ (- (length s) 1)) sum 0.0 '())))
 
63
 
 
64
(define (simplex-shrink s-min f s)
 
65
  (if (null? s)
 
66
      '()
 
67
      (if (eq? s-min (car s))
 
68
          (cons (car s) (simplex-shrink s-min f (cdr s)))
 
69
          (let ((x (ax+by 0.5 (simplex-point-x s-min)
 
70
                          0.5 (simplex-point-x (car s)))))
 
71
            (cons (simplex-point x (apply f x))
 
72
                  (simplex-shrink s-min f (cdr s)))))))
 
73
 
 
74
(define simplex-reflect-ratio 1.0)
 
75
(define simplex-expand-ratio 2.0)
 
76
(define simplex-contract-ratio 0.5)
 
77
 
 
78
(define (simplex-contract f s)
 
79
  (let ((s-h (simplex-high s))
 
80
        (s-l (simplex-low s))
 
81
        (x0 (simplex-centroid-x s)))
 
82
    (let ((xc (ax+by (- 1 simplex-contract-ratio) x0
 
83
                     simplex-contract-ratio (simplex-point-x s-h))))
 
84
      (let ((vc (apply f xc)))
 
85
        (if (< vc (simplex-point-val s-h))
 
86
            (simplex-replace s s-h (simplex-point xc vc))
 
87
            (simplex-shrink s-l f s))))))
 
88
 
 
89
(define (simplex-iter f s)
 
90
  (let ((s-h (simplex-high s))
 
91
        (s-h2 (simplex-high2 s))
 
92
        (s-l (simplex-low s))
 
93
        (x0 (simplex-centroid-x s)))
 
94
    (let ((xr (ax+by (+ 1 simplex-reflect-ratio) x0
 
95
                     (- simplex-reflect-ratio) (simplex-point-x s-h))))
 
96
      (let ((vr (apply f xr)))
 
97
        (if (and (<= vr (simplex-point-val s-h2))
 
98
                 (>= vr (simplex-point-val s-l)))
 
99
            
 
100
            (simplex-replace s s-h (simplex-point xr vr))
 
101
            (if (< vr (simplex-point-val s-l))
 
102
                (let ((xe (ax+by (- 1 simplex-expand-ratio) x0
 
103
                                 simplex-expand-ratio xr)))
 
104
                  (let ((ve (apply f xe)))
 
105
                    (if (>= ve vr)
 
106
                        (simplex-replace s s-h (simplex-point xr vr))
 
107
                        (simplex-replace s s-h (simplex-point xe ve)))))
 
108
                (if (and (< vr  (simplex-point-val s-h))
 
109
                         (> vr  (simplex-point-val s-h2)))
 
110
                    (simplex-contract f (simplex-replace 
 
111
                                         s s-h (simplex-point xr vr)))
 
112
                    (simplex-contract f s))))))))
 
113
 
 
114
(define (simplex-iterate f s tol)
 
115
  (let ((s-h (simplex-high s))
 
116
        (s-l (simplex-low s)))
 
117
    (if (<= (magnitude (- (simplex-point-val s-h) (simplex-point-val s-l)))
 
118
            (* 0.5 tol (+ tol (magnitude (simplex-point-val s-h)) 
 
119
                          (magnitude (simplex-point-val s-l)))))
 
120
        s-l
 
121
        (begin
 
122
          (print "extremization: best so far is " s-l "\n")
 
123
          (simplex-iterate f (simplex-iter f s) tol)))))
 
124
 
 
125
(define (simplex-shift-x x i)
 
126
  (let ((xv (list->vector x)))
 
127
    (let ((xv-i (vector-ref xv i)))
 
128
      (if (< (magnitude xv-i) 1e-6)
 
129
          (vector-set! xv i 0.1)
 
130
          (vector-set! xv i (* 0.9 xv-i)))
 
131
      (vector->list xv))))
 
132
 
 
133
(define (simplex-shift-list x)
 
134
  (define (ssl-aux i)
 
135
    (if (< i 0)
 
136
        '()
 
137
        (cons (simplex-shift-x x i) (ssl-aux (- i 1)))))
 
138
  (cons x (ssl-aux (- (length x) 1))))
 
139
 
 
140
; Use the Simplex method to minimize the function (f . x), where
 
141
; the initial guess is x0 and the fractional tolerance on the value
 
142
; of the solution is tol.
 
143
(define (simplex-minimize f x0 tol)
 
144
  (let ((s0 (map (lambda (x) (simplex-point x (apply f x)))
 
145
                 (simplex-shift-list x0))))
 
146
    (simplex-iterate f s0 tol)))