Files
simpeg/SimPEG/Parameters.py
T
2014-04-15 09:51:29 -07:00

178 lines
5.1 KiB
Python

import Utils, numpy as np
class Parameter(object):
"""Parameter"""
debug = False #: Print debugging information
current = None #: This hold
currentIter = 0
def __init__(self, **kwargs):
Utils.setKwargs(self, **kwargs)
@property
def parent(self):
"""This is the parent of the Parameter instance."""
return getattr(self,'_parent',None)
@parent.setter
def parent(self, p):
startupName = '_startup_paramProperty_'+self._propertyName
if getattr(self,'_parent',None) is not None:
delattr(self._parent,startupName)
print 'Warning: Parameter %s has switched to a new parent.' % self._propertyName
if self.debug: print '%s function has been deleted' % startupName
self._parent = p
prop = self
def _startup_paramProperty(self, *args):
if prop.debug: print 'initializing %s' % prop._propertyName
prop.initialize()
Utils.hook(self._parent, _startup_paramProperty, name=startupName, overwrite=True)
@property
def inv(self): return self.parent.inv
@property
def objFunc(self): return self.parent.objFunc
@property
def opt(self): return self.parent.opt
@property
def reg(self): return self.parent.reg
@property
def survey(self): return self.parent.survey
@property
def prob(self): return self.parent.prob
@property
def mapping(self): return self.parent.mapping
@property
def mesh(self): return self.parent.mesh
def initialize(self):
pass
def get(self):
if (self.current is None or
not self.opt.iter == self.currentIter):
self.current = self.nextIter()
self.currentIter = getattr(self.opt, 'iter', 0)
return self.current
def nextIter(self):
raise NotImplementedError('Getting the Parameter is not yet implemented.')
def ParameterProperty(name, default=None, doc=""):
def getter(self):
out = getattr(self,'_'+name,default)
if isinstance(out, Parameter):
out = out.get()
return out
def setter(self, value):
if isinstance(value, Parameter):
value._propertyName = name
value.parent = self
setattr(self, '_'+name, value)
return property(fget=getter, fset=setter, doc=doc)
class BetaEstimate(Parameter):
"""BetaEstimate"""
beta0 = 'guess' #: The initial Beta (regularization parameter)
beta0_ratio = 0.1 #: When beta0 is set to 'guess', estimateBeta0 is used with this ratio
beta = None #: Beta parameter
def __init__(self, **kwargs):
Parameter.__init__(self, **kwargs)
def initialize(self):
self.beta = self.beta0
@Utils.requires('parent')
def nextIter(self):
if self.beta is 'guess':
if self.debug: print 'BetaSchedule is estimating Beta0.'
self.beta = self.estimateBeta0()
return self.beta
@Utils.requires('parent')
def estimateBeta0(self):
"""estimateBeta0(u=None)
The initial beta is calculated by comparing the estimated
eigenvalues of JtJ and WtW.
To estimate the eigenvector of **A**, we will use one iteration
of the *Power Method*:
.. math::
\mathbf{x_1 = A x_0}
Given this (very course) approximation of the eigenvector,
we can use the *Rayleigh quotient* to approximate the largest eigenvalue.
.. math::
\lambda_0 = \\frac{\mathbf{x^\\top A x}}{\mathbf{x^\\top x}}
We will approximate the largest eigenvalue for both JtJ and WtW, and
use some ratio of the quotient to estimate beta0.
.. math::
\\beta_0 = \gamma \\frac{\mathbf{x^\\top J^\\top J x}}{\mathbf{x^\\top W^\\top W x}}
:rtype: float
:return: beta0
"""
objFunc = self.parent
survey = objFunc.survey
m = objFunc.m_current
u = objFunc.u_current
if u is None:
u = survey.prob.fields(m)
x0 = np.random.rand(*m.shape)
t = x0.dot(objFunc.dataObj2Deriv(m,x0,u=u))
b = x0.dot(objFunc.reg.modelObj2Deriv(m, v=x0))
return self.beta0_ratio*(t/b)
class BetaSchedule(BetaEstimate):
"""BetaSchedule"""
coolingFactor = 2.
coolingRate = 3
@Utils.requires('parent')
def nextIter(self):
if self.beta is 'guess':
if self.debug: print 'BetaSchedule is estimating Beta0.'
self.beta = self.estimateBeta0()
if self.opt.iter > 0 and self.opt.iter % self.coolingRate == 0:
if self.debug: print 'BetaSchedule is cooling Beta. Iteration: %d' % self.opt.iter
self.beta /= self.coolingFactor
return self.beta
class UpdateReferenceModel(Parameter):
mref0 = None
def nextIter(self):
mref = getattr(self, 'm_prev', None)
if mref is None:
if self.debug: print 'UpdateReferenceModel is using mref0'
mref = self.mref0
self.m_prev = self.objFunc.m_current
return mref