[Scipy-svn] r2535 - trunk/Lib/sandbox/newoptimize

scipy-svn at scipy.org scipy-svn at scipy.org
Thu Jan 11 03:43:20 CST 2007


Author: jarrod.millman
Date: 2007-01-11 03:43:18 -0600 (Thu, 11 Jan 2007)
New Revision: 2535

Modified:
   trunk/Lib/sandbox/newoptimize/tnc.py
Log:
1st attempt to replicate the changes to interface made by Travis Oliphant for inclusion in scipy


Modified: trunk/Lib/sandbox/newoptimize/tnc.py
===================================================================
--- trunk/Lib/sandbox/newoptimize/tnc.py	2007-01-11 07:48:11 UTC (rev 2534)
+++ trunk/Lib/sandbox/newoptimize/tnc.py	2007-01-11 09:43:18 UTC (rev 2535)
@@ -33,6 +33,7 @@
 """
 
 import moduleTNC
+from numpy import asarray
 
 MSG_NONE = 0 # No messages
 MSG_ITER = 1 # One line per iteration
@@ -51,6 +52,7 @@
 }
 
 HUGE_VAL=1e200*1e200 # No standard representation of Infinity in Python 2.3.3
+               # FIXME: can we use inf now that we have numpy and IEEE floats?
 
 INFEASIBLE   = -1 # Infeasible (low > up)
 LOCALMINIMUM =  0 # Local minima reach (|pg| ~= 0)
@@ -74,26 +76,34 @@
         USERABORT    : "User requested end of minimization"
 }
 
-def minimize(function, x, low = None, up = None, scale = None, offset = None,
-        messages = MSG_ALL, maxCGit = -1, maxnfeval = None, eta = -1, stepmx = 0,
-        accuracy = 0, fmin = 0, ftol = -1, xtol = -1, pgtol = -1, rescale = -1):
+# Changes to interface made by Travis Oliphant, Apr. 2004 for inclusion in
+#  SciPy
+
+import optimize
+approx_fprime = optimize.approx_fprime
+
+def fmin_tnc(func, x0, fprime=None, args=(), approx_grad=0, bounds=None, epsilon=1e-8,
+        scale=None, offset=None, messages=MSG_ALL, maxCGit=-1, maxfun=None, eta=-1,
+        stepmx=0, accuracy=0, fmin=0, ftol=-1, xtol=-1, pgtol=-1, rescale=-1):
     """Minimize a function with variables subject to bounds, using gradient
     information.
 
     returns (rc, nfeval, x).
 
     Inputs:
-    x         : initial estimate (a list of floats)
-    function  : the function to minimize. Must take one argument, x and return
+    func      : the function to minimize. Must take one argument, x and return
                 f and g, where f is the value of the function and g its
                 gradient (a list of floats).
                 if the function returns None, the minimization is aborted.
-    low, up   : the bounds (lists of floats)
-                set low[i] to -HUGE_VAL to remove the lower bound
-                set up[i] to HUGE_VAL to remove the upper bound
-                if low == None, the lower bounds are removed.
-                if up == None, the upper bounds are removed.
-                low and up defaults to None
+    x0        : initial estimate (a list of floats)
+    fprime    : gradient of func. If None, then func returns the function
+                value and the gradient ( f, g = func(x, *args) ).
+                Called as fprime(x, *args)
+    args      : arguments to pass to function
+    approx_grad : if true, approximate the gradient numerically
+    bounds    : a list of (min, max) pairs for each element in x, defining
+                the bounds on that parameter. Use None for one of min or max
+                when there is no bound in that direction
     scale     : scaling factors to apply to each variable (a list of floats)
                 if None, the factors are up-low for interval bounded variables
                 and 1+|x] fo the others.
@@ -108,8 +118,8 @@
                 if maxCGit == 0, the direction chosen is -gradient
                 if maxCGit < 0, maxCGit is set to max(1,min(50,n/2))
                 defaults to -1
-    maxnfeval : max. number of function evaluation
-                if None, maxnfeval is set to max(100, 10*len(x0))
+    maxfun    : max. number of function evaluation
+                if None, maxfun is set to max(100, 10*len(x0))
                 defaults to None
     eta       : severity of the line search. if < 0 or > 1, set to 0.25
                 defaults to -1
@@ -141,25 +151,85 @@
     Outputs:
     x         : the solution (a list of floats)
     nfeval    : the number of function evaluations
-    rc        : return code as defined in the RCSTRINGS dict"""
+    rc        : return code as defined in the RCSTRINGS dict
 
-    if low == None:
-        low = [-HUGE_VAL]*len(x)
+See also:
 
-    if up == None:
-        up = [HUGE_VAL]*len(x)
+  fmin, fmin_powell, fmin_cg,
+         fmin_bfgs, fmin_ncg -- multivariate local optimizers
+  leastsq -- nonlinear least squares minimizer
 
+  fmin_l_bfgs_b, fmin_tnc,
+         fmin_cobyla -- constrained multivariate optimizers
+
+  anneal, brute -- global optimizers
+
+  fminbound, brent, golden, bracket -- local scalar minimizers
+
+  fsolve -- n-dimenstional root-finding
+
+  brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
+
+  fixed_point -- scalar fixed-point finder
+"""
+
+    n = len(x0)
+
+    if bounds is None:
+        bounds = [(None,None)] * n
+    if len(bounds) != n:
+        raise ValueError('length of x0 != length of bounds')
+
+    if approx_grad:
+        def func_and_grad(x):
+            x = asarray(x)
+            f = func(x, *args)
+            g = approx_fprime(x, func, epsilon, *args)
+            return f, list(g)
+    elif fprime is None:
+        def func_and_grad(x):
+            x = asarray(x)
+            f, g = func(x, *args)
+            return f, list(g)
+    else:
+        def func_and_grad(x):
+            x = asarray(x)
+            f = func(x, *args)
+            g = fprime(x, *args)
+            return f, list(g)
+
+    """
+    low, up   : the bounds (lists of floats)
+                set low[i] to -HUGE_VAL to remove the lower bound
+                set up[i] to HUGE_VAL to remove the upper bound
+                if low == None, the lower bounds are removed.
+                if up == None, the upper bounds are removed.
+                low and up defaults to None
+    """
+    low = [0]*n
+    up = [0]*n
+    for i in range(n):
+        l,u = bounds[i]
+        if l is None:
+            low[i] = -HUGE_VAL
+        else:
+            low[i] = l
+        if u is None:
+            up[i] = HUGE_VAL
+        else:
+            up[i] = u
+
     if scale == None:
         scale = []
 
     if offset == None:
         offset = []
 
-    if maxnfeval == None:
-        maxnfeval = max(100, 10*len(x))
+    if maxfun == None:
+        maxfun = max(100, 10*len(x0))
 
-    return moduleTNC.minimize(function, x, low, up, scale, offset,
-            messages, maxCGit, maxnfeval, eta, stepmx, accuracy,
+    return moduleTNC.minimize(func_and_grad, x0, low, up, scale, offset,
+            messages, maxCGit, maxfun, eta, stepmx, accuracy,
             fmin, ftol, xtol, pgtol, rescale)
 
 if __name__ == '__main__':
@@ -178,7 +248,7 @@
             return f, g
 
         # Optimizer call
-        rc, nf, x = minimize(function, [-7, 3], [-10, 1], [10, 10])
+        rc, nf, x = fmin_tnc(function, [-7, 3], bounds=([-10, 1], [10, 10]))
 
         print "After", nf, "function evaluations, TNC returned:", RCSTRINGS[rc]
         print "x =", x
@@ -260,9 +330,9 @@
         return f, dif
     tests.append ((test45fg, [2]*5, [0]*5, [1,2,3,4,5], [1,2,3,4,5]))
 
-    def test(fg, x, low, up, xopt):
+    def test(fg, x, bounds, xopt):
         print "** Test", fg.__name__
-        rc, nf, x = minimize(fg, x, low, up, messages = MSG_NONE, maxnfeval = 200)
+        rc, nf, x = fmin_tnc(fg, x, bounds=bounds, messages = MSG_NONE, maxnfeval = 200)
         print "After", nf, "function evaluations, TNC returned:", RCSTRINGS[rc]
         print "x =", x
         print "exact value =", xopt
@@ -278,8 +348,8 @@
         if ef > 1e-8:
             raise "Test "+fg.__name__+" failed"
 
-    for fg, x, low, up, xopt in tests:
-        test(fg, x, low, up, xopt)
+    for fg, x, bounds, xopt in tests:
+        test(fg, x, bounds, xopt)
 
     print
     print "** All TNC tests passed."



More information about the Scipy-svn mailing list