From fbb8cf2731e10000f71e2056215a363ffc0d4023 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Wed, 4 May 2016 23:17:01 -0700 Subject: [PATCH] modularizing regularization --- SimPEG/Regularization.py | 404 ++++++++++++++++++++++++++------------- 1 file changed, 269 insertions(+), 135 deletions(-) diff --git a/SimPEG/Regularization.py b/SimPEG/Regularization.py index fc101a61..fd974130 100644 --- a/SimPEG/Regularization.py +++ b/SimPEG/Regularization.py @@ -403,7 +403,203 @@ class BaseRegularization(object): return mD.T * ( self.W.T * ( self.W * ( mD * v) ) ) -class Tikhonov(BaseRegularization): +class Simple(BaseRegularization): + """ + Simple regularization that does not include length scales in the derivatives. + """ + + mrefInSmooth = False #: SMOOTH and SMOOTH_MOD_DIF options + alpha_s = Utils.dependentProperty('_alpha_s', 1e-6, ['_W', '_Wsmall'], "Smallness weight") + alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction") + alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction") + alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction") + wght = 1. + + def __init__(self, mesh, mapping=None, indActive=None, **kwargs): + BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs) + + if isinstance(self.wght,float): + self.wght = np.ones(self.regmesh.nC) * self.wght + + @property + def Wsmall(self): + """Regularization matrix Wsmall""" + if getattr(self,'_Wsmall', None) is None: + self._Wsmall = Utils.sdiag((self.regmesh.vol*self.alpha_s*self.wght)**0.5) + return self._Wsmall + + @property + def Wx(self): + """Regularization matrix Wx""" + if getattr(self, '_Wx', None) is None: + self._Wx = Utils.sdiag((self.regmesh.aveCC2Fx * self.regmesh.vol*self.alpha_x*(self.regmesh.aveCC2Fx*self.wght))**0.5)*self.regmesh.cellDiffxStencil + return self._Wx + + @property + def Wy(self): + """Regularization matrix Wy""" + if getattr(self, '_Wy', None) is None: + self._Wy = Utils.sdiag((self.regmesh.aveCC2Fy * self.regmesh.vol * self.alpha_y*(self.regmesh.aveCC2Fy*self.wght))**0.5)*self.regmesh.cellDiffyStencil + return self._Wy + + @property + def Wz(self): + """Regularization matrix Wz""" + if getattr(self, '_Wz', None) is None: + self._Wz = Utils.sdiag((self.regmesh.aveCC2Fz * self.regmesh.vol*self.alpha_z*(self.regmesh.aveCC2Fz*self.wght))**0.5)*self.regmesh.cellDiffzStencil + return self._Wz + + @property + def Wsmooth(self): + """Full smoothness regularization matrix W""" + if getattr(self, '_Wsmooth', None) is None: + wlist = (self.Wx,) + if self.regmesh.dim > 1: + wlist += (self.Wy,) + if self.regmesh.dim > 2: + wlist += (self.Wz,) + self._Wsmooth = sp.vstack(wlist) + return self._Wsmooth + + @property + def W(self): + """Full regularization matrix W""" + if getattr(self, '_W', None) is None: + wlist = (self.Wsmall, self.Wsmooth) + self._W = sp.vstack(wlist) + return self._W + + @Utils.timeIt + def _evalSmall(self, m): + r = self.Wsmall * ( self.mapping * (m - self.mref) ) + return 0.5 * r.dot(r) + + @property + def W(self): + """Full regularization matrix W""" + if getattr(self, '_W', None) is None: + wlist = (self.Wsmall, self.Wsmooth) + self._W = sp.vstack(wlist) + return self._W + + @property + def Wsmooth(self): + """Full smoothness regularization matrix W""" + if getattr(self, '_Wsmooth', None) is None: + wlist = (self.Wx,) + if self.regmesh.dim > 1: + wlist += (self.Wy,) + if self.regmesh.dim > 2: + wlist += (self.Wz,) + self._Wsmooth = sp.vstack(wlist) + return self._Wsmooth + + + @Utils.timeIt + def _evalSmall(self, m): + r = self.Wsmall * ( self.mapping * (m - self.mref) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmallDeriv(self,m): + r = self.Wsmall * ( self.mapping * (m - self.mref) ) + return r.T * ( self.Wsmall * self.mapping.deriv(m - self.mref) ) + + @Utils.timeIt + def _evalSmoothx(self, m): + if self.mrefInSmooth == True: + r = self.Wx * ( self.mapping * (m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wx * ( self.mapping * (m) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmoothy(self, m): + if self.mrefInSmooth == True: + r = self.Wy * ( self.mapping * (m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wy * ( self.mapping * (m) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmoothz(self, m): + if self.mrefInSmooth == True: + r = self.Wz * ( self.mapping * (m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wz * ( self.mapping * (m) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmooth(self, m): + phiSmooth = self._evalSmoothx(m) + if self.regmesh.dim > 1: + phiSmooth += self._evalSmoothy(m) + if self.regmesh.dim > 2: + phiSmooth += self._evalSmoothz(m) + return phiSmooth + + @Utils.timeIt + def _evalSmoothxDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wx * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wx * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wx * ( self.mapping * m ) + return r.T * ( self.Wx * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmoothyDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wy * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wy * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wy * ( self.mapping * m ) + return r.T * ( self.Wy * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmoothzDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wz * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wz * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wz * ( self.mapping * m ) + return r.T * ( self.Wz * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmoothDeriv(self,m): + deriv = self._evalSmoothxDeriv(m) + if self.regmesh.dim > 1: + deriv += self._evalSmoothyDeriv(m) + if self.regmesh.dim > 2: + deriv += self._evalSmoothzDeriv(m) + return deriv + + + @Utils.timeIt + def eval(self, m): + return self._evalSmall(m) + self._evalSmooth(m) + + @Utils.timeIt + def evalDeriv(self, m): + """ + The regularization is: + + .. math:: + + R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})} + + So the derivative is straight forward: + + .. math:: + + R(m) = \mathbf{W^\\top W (m-m_\\text{ref})} + + """ + return self._evalSmallDeriv(m) + self._evalSmoothDeriv(m) + + + +class Tikhonov(Simple): """ L2 Tikhonov regularization with both smallness and smoothness (first order derivative) contributions. @@ -493,56 +689,92 @@ class Tikhonov(BaseRegularization): self._Wzz = Utils.sdiag((self.regmesh.vol*self.alpha_zz)**0.5)*self.regmesh.faceDiffz*self.regmesh.cellDiffz return self._Wzz + @property - def Wsmooth(self): + def Wsmooth2(self): """Full smoothness regularization matrix W""" if getattr(self, '_Wsmooth', None) is None: - wlist = (self.Wx, self.Wxx) + wlist = (self.Wxx) if self.regmesh.dim > 1: - wlist += (self.Wy, self.Wyy) + wlist += (self.Wyy) if self.regmesh.dim > 2: - wlist += (self.Wz, self.Wzz) + wlist += (self.Wzz) self._Wsmooth = sp.vstack(wlist) return self._Wsmooth - @property - def W(self): - """Full regularization matrix W""" - if getattr(self, '_W', None) is None: - wlist = (self.Wsmall, self.Wsmooth) - self._W = sp.vstack(wlist) - return self._W - @Utils.timeIt - def _evalSmall(self, m): - r = self.Wsmall * ( self.mapping * (m - self.mref) ) - return 0.5 * r.dot(r) - - @Utils.timeIt - def _evalSmooth(self, m): + def _evalSmoothxx(self, m): if self.mrefInSmooth == True: - r = self.Wsmooth * ( self.mapping * (m - self.mref) ) + r = self.Wxx * ( self.mapping * (m - self.mref) ) elif self.mrefInSmooth == False: - r = self.Wsmooth * ( self.mapping * (m) ) + r = self.Wxx * ( self.mapping * (m) ) return 0.5 * r.dot(r) + @Utils.timeIt + def _evalSmoothyy(self, m): + if self.mrefInSmooth == True: + r = self.Wyy * ( self.mapping * (m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wyy * ( self.mapping * (m) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmoothzz(self, m): + if self.mrefInSmooth == True: + r = self.Wzz * ( self.mapping * (m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wzz * ( self.mapping * (m) ) + return 0.5 * r.dot(r) + + @Utils.timeIt + def _evalSmooth2(self, m): + phiSmooth2 = self._evalSmoothxx(m) + if self.regmesh.dim > 1: + phiSmooth2 += self._evalSmoothyy(m) + if self.regmesh.dim > 2: + phiSmooth2 += self._evalSmoothzz(m) + return phiSmooth2 + + @Utils.timeIt + def _evalSmoothxxDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wxx * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wxx * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wxx * ( self.mapping * m ) + return r.T * ( self.Wxx * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmoothyyDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wyy * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wyy * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wyy * ( self.mapping * m ) + return r.T * ( self.Wyy * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmoothzzDeriv(self,m): + if self.mrefInSmooth == True: + r = self.Wzz * ( self.mapping * ( m - self.mref ) ) + return r.T * ( self.Wzz * self.mapping.deriv(m - self.mref) ) + elif self.mrefInSmooth == False: + r = self.Wzz * ( self.mapping * m ) + return r.T * ( self.Wzz * self.mapping.deriv(m) ) + + @Utils.timeIt + def _evalSmooth2Deriv(self,m): + deriv = self._evalSmoothxxDeriv(m) + if self.regmesh.dim > 1: + deriv += self._evalSmoothyyDeriv(m) + if self.regmesh.dim > 2: + deriv += self._evalSmoothzzDeriv(m) + return deriv + + @Utils.timeIt def eval(self, m): - return self._evalSmall(m) + self._evalSmooth(m) - - @Utils.timeIt - def _evalSmallDeriv(self,m): - r = self.Wsmall * ( self.mapping * (m - self.mref) ) - return r.T * ( self.Wsmall * self.mapping.deriv(m - self.mref) ) - - @Utils.timeIt - def _evalSmoothDeriv(self,m): - if self.mrefInSmooth == True: - r = self.Wsmooth * ( self.mapping * ( m - self.mref ) ) - return r.T * ( self.Wsmooth * self.mapping.deriv(m - self.mref) ) - elif self.mrefInSmooth == False: - r = self.Wsmooth * ( self.mapping * m ) - return r.T * ( self.Wsmooth * self.mapping.deriv(m) ) + return self._evalSmall(m) + self._evalSmooth(m) + self._evalSmooth2(m) @Utils.timeIt def evalDeriv(self, m): @@ -560,88 +792,9 @@ class Tikhonov(BaseRegularization): R(m) = \mathbf{W^\\top W (m-m_\\text{ref})} """ - return self._evalSmallDeriv(m) + self._evalSmoothDeriv(m) + return self._evalSmallDeriv(m) + self._evalSmoothDeriv(m) + self._evalSmooth2Deriv(m) -class Simple(Tikhonov): - """ - Simple regularization that does not include length scales in the derivatives. - """ - - mrefInSmooth = False #: SMOOTH and SMOOTH_MOD_DIF options - alpha_s = Utils.dependentProperty('_alpha_s', 1.0, ['_W', '_Wsmall'], "Smallness weight") - alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction") - alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction") - alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction") - wght = 1. - - def __init__(self, mesh, mapping=None, indActive=None, **kwargs): - BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs) - - if isinstance(self.wght,float): - self.wght = np.ones(self.regmesh.nC) * self.wght - - @property - def Wsmall(self): - """Regularization matrix Wsmall""" - if getattr(self,'_Wsmall', None) is None: - self._Wsmall = Utils.sdiag((self.regmesh.vol*self.alpha_s*self.wght)**0.5) - return self._Wsmall - - @property - def Wx(self): - """Regularization matrix Wx""" - if getattr(self, '_Wx', None) is None: - self._Wx = Utils.sdiag((self.regmesh.aveCC2Fx * self.regmesh.vol*self.alpha_x*(self.regmesh.aveCC2Fx*self.wght))**0.5)*self.regmesh.cellDiffxStencil - return self._Wx - - @property - def Wy(self): - """Regularization matrix Wy""" - if getattr(self, '_Wy', None) is None: - self._Wy = Utils.sdiag((self.regmesh.aveCC2Fy * self.regmesh.vol * self.alpha_y*(self.regmesh.aveCC2Fy*self.wght))**0.5)*self.regmesh.cellDiffyStencil - return self._Wy - - @property - def Wz(self): - """Regularization matrix Wz""" - if getattr(self, '_Wz', None) is None: - self._Wz = Utils.sdiag((self.regmesh.aveCC2Fz * self.regmesh.vol*self.alpha_z*(self.regmesh.aveCC2Fz*self.wght))**0.5)*self.regmesh.cellDiffzStencil - return self._Wz - - @property - def Wsmooth(self): - """Full smoothness regularization matrix W""" - if getattr(self, '_Wsmooth', None) is None: - wlist = (self.Wx,) - if self.regmesh.dim > 1: - wlist += (self.Wy,) - if self.regmesh.dim > 2: - wlist += (self.Wz,) - self._Wsmooth = sp.vstack(wlist) - return self._Wsmooth - - @property - def W(self): - """Full regularization matrix W""" - if getattr(self, '_W', None) is None: - wlist = (self.Wsmall, self.Wsmooth) - self._W = sp.vstack(wlist) - return self._W - - @Utils.timeIt - def _evalSmall(self, m): - r = self.Wsmall * ( self.mapping * (m - self.mref) ) - return 0.5 * r.dot(r) - - @Utils.timeIt - def _evalSmooth(self, m): - if self.mrefInSmooth == True: - r = self.Wsmooth * ( self.mapping * (m - self.mref) ) - elif self.mrefInSmooth == False: - r = self.Wsmooth * ( self.mapping * m) - return 0.5 * r.dot(r) - class Sparse(Simple): @@ -716,25 +869,6 @@ class Sparse(Simple): return Utils.sdiag(((self.regmesh.aveCC2Fz * self.regmesh.vol)*self.alpha_z*self.gamma*(self.regmesh.aveCC2Fz*self.wght))**0.5)*self.Rz*self.regmesh.cellDiffzStencil - @property - def Wsmooth(self): - """Full smoothness regularization matrix W""" - #if getattr(self, '_Wsmooth', None) is None: - wlist = (self.Wx,) - if self.regmesh.dim > 1: - wlist += (self.Wy,) - if self.regmesh.dim > 2: - wlist += (self.Wz,) - #self._Wsmooth = sp.vstack(wlist) - return sp.vstack(wlist) - - @property - def W(self): - """Full regularization matrix W""" - if getattr(self, '_W', None) is None: - wlist = (self.Wsmall, self.Wsmooth) - self._W = sp.vstack(wlist) - return self._W def R(self, f_m , eps, exponent):