Module regpy.solvers.nonlinear.irgnm_semismooth
Classes
class IrgnmSemiSmooth (setting, data, psi_minus, psi_plus, regpar, regpar_step=0.6666666666666666, init=None, cg_pars=None)
-
Semismooth Newton Method. In each iteration, solves x_{n+1} \in \textrm{argmin}_{\psi_- < x_\ast < \psi_+} ||T(x_n) + T'[x_n] (x_\ast-x_n) - g_\text{data}||^2 + \alpha_n ||x_\ast - x_\text{init}||^2 where T is a Frechet-differentiable operator, using
TikhonovCG
. \alpha_n is a decreasing geometric sequence of regularization parameters.Parameters
setting
:RegularizationSetting
- Setting for regularization.
data
:array-like
- Data for reconstruction. Must be in the operators codomain.
psi_minus
:np.number
- lower constraint of the minimization. Must be larger then
psi_plus
psi_plus
:np.number
- upper constraint of the minimization. Must be smaller then
psi_minus
regpar
:np.number
- Initial regularization parameter \alpha
regpar_step
:np.number
, optional- Must be between 0 and 1. Multiplied to regularization parameter to construct the decreasing geometric sequence. (Default: 2/3)
init
:array-like
, optional- An element of operator domain that is an initial guess. (Default: None)
cg_pars
:dict
- Dictionary of parameter to be given to the inner
TikhonovCG
solver. (Default: None)
Expand source code
class IrgnmSemiSmooth(RegSolver): r""" Semismooth Newton Method. In each iteration, solves \[ x_{n+1} \in \textrm{argmin}_{\psi_- < x_\ast < \psi_+} ||T(x_n) + T'[x_n] (x_\ast-x_n) - g_\text{data}||^2 + \alpha_n ||x_\ast - x_\text{init}||^2 \] where \(T\) is a Frechet-differentiable operator, using `regpy.solvers.linear.tikhonov.TikhonovCG`. \(\alpha_n\) is a decreasing geometric sequence of regularization parameters. Parameters ---------- setting : RegularizationSetting Setting for regularization. data : array-like Data for reconstruction. Must be in the operators codomain. psi_minus : np.number lower constraint of the minimization. Must be larger then `psi_plus` psi_plus : np.number upper constraint of the minimization. Must be smaller then `psi_minus` regpar : np.number Initial regularization parameter \(\alpha\) regpar_step : np.number, optional Must be between 0 and 1. Multiplied to regularization parameter to construct the decreasing geometric sequence. (Default: 2/3) init : array-like, optional An element of operator domain that is an initial guess. (Default: None) cg_pars : dict Dictionary of parameter to be given to the inner `TikhonovCG` solver. (Default: None) """ def __init__(self, setting, data, psi_minus, psi_plus, regpar, regpar_step=2 / 3, init=None, cg_pars=None): assert isinstance(setting,RegularizationSetting) assert psi_minus < psi_plus super().__init__(setting) self.data=data """The measured data""" if init is None: init = self.op.domain.zeros() self.init = np.asarray(init) """The initial guess.""" self.x=np.copy(self.init) self.regpar=regpar """The regularizaton parameter.""" self.regpar_step = regpar_step """The `regpar` factor.""" if cg_pars is None: cg_pars = {} self.cg_pars = cg_pars """The additional `regpy.solvers.linear.tikhonov.TikhonovCG` parameters.""" self.psi_minus=psi_minus self.psi_plus=psi_plus """The upper and the lower bound""" self.size=self.init.shape[0] """Prepare first iteration step""" self.y, self.deriv = self.op.linearize(self.x) self.rhs=self.data-self.y+self.deriv(self.x) self.b=self.h_domain.gram_inv(self.deriv.adjoint(self.h_codomain.gram(self.rhs)))+self.regpar*self.init """Prepare newton-semismooth minimization""" self.lam_plus=np.maximum(np.zeros(self.size), self.b-self._A(self.x)) self.lam_minus=-np.minimum(np.zeros(self.size), self.b-self._A(self.x)) """sets where the upper constraint and the lower constarint are active""" self.active_plus=[self.lam_plus[j]+self.regpar*(self.x[j]-self.psi_plus)>0 for j in range(self.size)] self.active_minus=[self.lam_minus[j]-self.regpar*(self.x[j]-self.psi_minus)>0 for j in range(self.size)] self.active_plus_old=self.active_plus self.active_minus_old=self.active_minus """compute active and inactive sets, need to be computed in each step again""" self.active=np.zeros(self.size) self.inactive=np.zeros(self.size) def _next(self): iter_count = 0 while iter_count<=20 and (iter_count==0 or np.sum([old != new for old, new in zip(self.active_plus_old,self.active_plus)])>3 or np.sum([old != new for old, new in zip(self.active_minus_old,self.active_minus)])>3): self.active_plus_old=self.active_plus self.active_minus_old=self.active_minus self.inner_update() iter_count += 1 self.y, self.deriv = self.op.linearize(self.x) self.rhs=self.data-self.y+self.deriv(self.x) self.b=self.h_domain.gram_inv(self.deriv.adjoint(self.h_codomain.gram(self.rhs)))+self.regpar*self.init #Prepare newton-semismooth minimization self.lam_plus=np.maximum(np.zeros(self.size), self.b-self._A(self.x)) self.lam_minus=-np.minimum(np.zeros(self.size), self.b-self._A(self.x)) #sets where the upper constraint and the lower constarint are active self.active_plus=[self.lam_plus[j]+self.regpar*(self.x[j]-self.psi_plus)>0 for j in range(self.size)] self.active_minus=[self.lam_minus[j]-self.regpar*(self.x[j]-self.psi_minus)>0 for j in range(self.size)] self.active_plus_old=self.active_plus self.active_minus_old=self.active_minus self.regpar *= self.regpar_step def inner_update(self): self.active=[self.active_plus[j] or self.active_minus[j] for j in range(self.size)] self.inactive=[self.active[j]==False for j in range(self.size)] #On the active sets the solution takes the values of the constraints self.x[self.active_plus]=self.psi_plus self.x[self.active_minus]=self.psi_minus self.lam_plus[self.inactive]=0 self.lam_plus[self.active_minus]=0 self.lam_minus[self.inactive]=0 self.lam_minus[self.active_plus]=0 project = CoordinateMask(self.h_domain.vecsp, self.inactive) self.log.info('Running inner Tikhonov solver.') f, _ = TikhonovCG( setting=RegularizationSetting(self.deriv * project, self.h_domain, self.h_codomain), data=self.rhs, regpar=self.regpar, xref=self.init, logging_level="WARNING", **self.cg_pars ).run() self.x[self.inactive] = f[self.inactive] z = self._A(self.x) self.lam_plus[self.active_plus]=self.b[self.active_plus]+self.lam_minus[self.active_plus]-z[self.active_plus] self.lam_minus[self.active_minus]=-self.b[self.active_minus]+self.lam_plus[self.active_minus]+z[self.active_minus] #Update active and inactive sets self.active_plus=[self.lam_plus[j]+self.regpar*(self.x[j]-self.psi_plus)>0 for j in range(self.size)] self.active_minus=[self.lam_minus[j]-self.regpar*(self.x[j]-self.psi_minus)>0 for j in range(self.size)] def _A(self, u): return self.regpar*u+self.h_domain.gram_inv(self.deriv.adjoint(self.h_codomain.gram(self.deriv(u))))
Ancestors
Instance variables
var data
-
The measured data
var init
-
The initial guess.
var regpar
-
The regularizaton parameter.
var regpar_step
-
The
regpar
factor. var cg_pars
-
The additional
TikhonovCG
parameters. var psi_plus
-
The upper and the lower bound
var size
-
Prepare first iteration step
var b
-
Prepare newton-semismooth minimization
var lam_minus
-
sets where the upper constraint and the lower constarint are active
var active_minus_old
-
compute active and inactive sets, need to be computed in each step again
Methods
def inner_update(self)
Inherited members