Changes to evalFunction. and more extensible calls in startup and endIteration

This commit is contained in:
Rowan Cockett
2013-11-07 12:27:07 -08:00
parent 318ca555c8
commit ded738b077
3 changed files with 39 additions and 25 deletions
+5 -5
View File
@@ -23,13 +23,13 @@ class Inversion(object):
if not haveInserted:
self.opt.printers.insert(1,{"title": "beta",
"value": lambda M: M.parent._beta,
"width": 13, "format": "%1.2e"})
"width": 10, "format": "%1.2e"})
self.opt.printers.insert(2,{"title": "phi_d",
"value": lambda M: M.parent._phi_d_last,
"width": 13, "format": "%1.2e"})
"width": 10, "format": "%1.2e"})
self.opt.printers.insert(3,{"title": "phi_m",
"value": lambda M: M.parent._phi_m_last,
"width": 13, "format": "%1.2e"})
"width": 10, "format": "%1.2e"})
def setKwargs(self, **kwargs):
"""Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist."""
@@ -80,8 +80,8 @@ class Inversion(object):
while True:
self._beta = self.getBeta()
m = self.opt.minimize(self.evalFunction,m)
if self.stoppingCriteria(): break
self._iter += 1
if self.stoppingCriteria(): break
return m
beta0 = 1.e2
@@ -127,7 +127,7 @@ class Inversion(object):
operator = sp.linalg.LinearOperator( (m.size, m.size), H_fun, dtype=float )
out += (operator,)
return out
return out if len(out) > 1 else out[0]
def dataObj(self, m, u=None):
+31 -18
View File
@@ -33,7 +33,9 @@ class Minimize(object):
tolX = 1e-1
tolG = 1e-1
eps = 1e-5
debug = True
debug = False
debugLS = False
def __init__(self, **kwargs):
self._id = int(np.random.rand()*1e6) # create a unique identifier to this program to be used in pubsub
@@ -79,17 +81,17 @@ class Minimize(object):
self.printers = [{
"title": "#",
"value": lambda M: M._iter,
"width": 10,
"width": 5,
"format": "%3d"
},{
"title": "f",
"value": lambda M: self.f,
"width": 14,
"width": 10,
"format": "%1.2e"
},{
"title": "|g|",
"value": lambda M: norm(M.g),
"width": 14,
"width": 10,
"format": "%1.2e"
},{
"title": "LS",
@@ -101,17 +103,17 @@ class Minimize(object):
self.printersLS = [{
"title": "#",
"value": lambda M: (M._iter, M._iterLS),
"width": 10,
"width": 5,
"format": "%3d.%d"
},{
"title": "t",
"value": lambda M: M._LS_t,
"width": 14,
"width": 10,
"format": "%0.5f"
},{
"title": "ft",
"value": lambda M: M._LS_ft,
"width": 14,
"width": 10,
"format": "%1.2e"
},{
"title": "f + alp*g.T*p",
@@ -143,6 +145,14 @@ class Minimize(object):
(f[, g][, H]) = evalFunction(x, return_g=False, return_H=False )
def evalFunction(x, return_g=False, return_H=False):
out = (f,)
if return_g:
out += (g,)
if return_H:
out += (H,)
return out if len(out) > 1 else out[0]
Events are fired with the following inputs via pypubsub::
@@ -192,6 +202,7 @@ class Minimize(object):
while True:
self.f, self.g, self.H = evalFunction(self.xc, return_g=True, return_H=True)
if doPub: pub.sendMessage('Minimize.evalFunction', minimize=self, f=self.f, g=self.g, H=self.H)
self.printIter()
if self.stoppingCriteria(): break
p = self.findSearchDirection()
if doPub: pub.sendMessage('Minimize.searchDirection', minimize=self, p=p)
@@ -204,7 +215,6 @@ class Minimize(object):
if not caught: return self.xc
self.doEndIteration(xt)
if doPub: pub.sendMessage('Minimize.endIteration', minimize=self, xt=xt)
self.printIter()
self.printDone()
@@ -232,17 +242,19 @@ class Minimize(object):
If you have things that also need to run on startup, you can create a method::
def _startup(self, x0):
def _startup*(self, x0):
pass
If present, _startup will be called at the start of the default startup call.
Where the * can be any string. If present, _startup* will be called at the start of the default startup call.
You may also completely overwrite this function.
:param numpy.ndarray x0: initial x
:rtype: None
:return: None
"""
if hasattr(self,'_startup'): self._startup(x0)
if method in [posible for posible in dir(self) if '_startup' in posible]:
if self.debug: print 'startup is calling self.'+method
getattr(self,method)(xt)
self._iter = 0
self._iterLS = 0
@@ -417,16 +429,16 @@ class Minimize(object):
self._iterLS = 0
while self._iterLS < self.maxIterLS:
self._LS_xt = self.projection(self.xc + self._LS_t*p)
self._LS_ft = self.evalFunction(self._LS_xt, return_g=False, return_H=False)[0]
self._LS_ft = self.evalFunction(self._LS_xt, return_g=False, return_H=False)
self._LS_descent = np.inner(self.g, self._LS_xt - self.xc) # this takes into account multiplying by t, but is important for projection.
if self.stoppingCriteria(inLS=True): break
self._iterLS += 1
self._LS_t = self.LSshorten*self._LS_t
if self.debug:
if self.debugLS:
if self._iterLS == 1: self.printInit(inLS=True)
self.printIter(inLS=True)
if self.debug and self._iterLS > 0: self.printDone(inLS=True)
if self.debugLS and self._iterLS > 0: self.printDone(inLS=True)
return self._LS_xt, self._iterLS < self.maxIterLS
@@ -460,18 +472,19 @@ class Minimize(object):
If you have things that also need to run at the end of every iteration, you can create a method::
def _doEndIteration(self, xt):
def _doEndIteration*(self, xt):
pass
If present, _doEndIteration will be called at the start of the default doEndIteration call.
Where the * can be any string. If present, _doEndIteration* will be called at the start of the default doEndIteration call.
You may also completely overwrite this function.
:param numpy.ndarray xt: tested new iterate that ensures a descent direction.
:rtype: None
:return: None
"""
if hasattr(self,'_doEndIteration'): self._doEndIteration(xt)
if method in [posible for posible in dir(self) if '_doEndIteration' in posible]:
if self.debug: print 'doEndIteration is calling self.'+method
getattr(self,method)(xt)
# store old values
+3 -2
View File
@@ -5,6 +5,7 @@ from SimPEG.utils import mkvc, sdiag
from SimPEG import utils
from SimPEG.mesh import TensorMesh, LogicallyOrthogonalMesh
import numpy as np
import scipy.sparse as sp
import unittest
import inspect
@@ -179,14 +180,14 @@ def Rosenbrock(x, return_g=True, return_H=True):
f = 100*(x[1]-x[0]**2)**2+(1-x[0])**2
g = np.array([2*(200*x[0]**3-200*x[0]*x[1]+x[0]-1), 200*(x[1]-x[0]**2)])
H = np.array([[-400*x[1]+1200*x[0]**2+2, -400*x[0]], [-400*x[0], 200]])
H = sp.csr_matrix(np.array([[-400*x[1]+1200*x[0]**2+2, -400*x[0]], [-400*x[0], 200]]))
out = (f,)
if return_g:
out += (g,)
if return_H:
out += (H,)
return out
return out if len(out) > 1 else out[0]
def checkDerivative(fctn, x0, num=7, plotIt=True, dx=None):
"""