00001
00002 """
00003 Aumented operator class
00004 """
00005
00006 __copyright__ = """
00007 Copyright 2008 Sean Ross-Ross
00008 """
00009 __license__ = """
00010 This file is part of SLIMpy .
00011
00012 SLIMpy is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as published by
00014 the Free Software Foundation, either version 3 of the License, or
00015 (at your option) any later version.
00016
00017 SLIMpy is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021
00022 You should have received a copy of the GNU Lesser General Public License
00023 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00024 """
00025
00026 from slimpy_base.Core.User.Structures.VectorSpace import VectorAddition
00027 from slimpy_base.Core.User.linop.LinearOperatorType import LinearOperatorType,is_oper
00028 from slimpy_base.Core.User.linop.linear_operator import LinearOperator, CompoundOperator
00029 from slimpy_base.User.AumentedMatrix.AugVector import AugVector
00030 from slimpy_base.User.AumentedMatrix.AugmentedBase import AugmentBase
00031 from slimpy_base.User.AumentedMatrix.MetaSpace import MetaSpace
00032 from slimpy_base.api.linearops.ScatterOperator import apply_along_axis
00033
00034 from numpy import mat, diag, ndarray, asarray
00035 from pdb import set_trace
00036 from slimpy_base.api.linearops.transforms import DiagonalWeight
00037
00038 from slimpy_base.Core.User.Structures.Scalar import is_scalar_obj
00039 from slimpy_base.Core.User.Structures.Scalar import is_number
00040
00041 is_array = lambda item: isinstance( item , ndarray )
00042
00043
00044
00045 class AugOperator( AugmentBase ):
00046 """
00047 augmented operator is a matrix of Linear Operators
00048 ie.
00049 Aug = AugOperator( meta_space, [ [A,0],
00050 [0,A] ] )
00051 new_vec = Aug * aug_vec
00052 """
00053 def __new__(cls, *pars, **kw ):
00054 from slimpy_base.Core.Interface.PSpace import PSpace
00055 if pars:
00056 meta = pars[0]
00057 if len(pars) < 2 or not isinstance( meta, PSpace ):
00058 meta = None
00059 else:
00060 pars = pars[1:]
00061
00062 new_aug_oper = AugmentBase.__new__( cls, *pars, **kw )
00063 new_aug_oper.meta = meta
00064
00065 else:
00066 new_aug_oper = AugmentBase.__new__( cls, *pars, **kw )
00067
00068 ndim = new_aug_oper.ndim
00069 if ndim != 2:
00070 raise TypeError("AugOperator should have dim 2, got only dim %s matrix" %(ndim) )
00071
00072 return new_aug_oper
00073
00074
00075 _contained_type = LinearOperator
00076 __metaclass__ = LinearOperatorType
00077
00078 def _get_meta_rng(self):
00079 if not hasattr(self, '_meta_space_rng' ):
00080 self._meta_space_rng = None
00081 return self._meta_space_rng
00082
00083 def _set_meta_rng(self,val):
00084 self._meta_space_rng = val
00085
00086 def _get_meta_dom(self):
00087 if not hasattr(self, '_meta_space_dom' ):
00088 self._meta_space_dom = None
00089 return self._meta_space_dom
00090
00091 def _set_meta_dom(self,val):
00092 self._meta_space_dom = val
00093
00094 def _set_meta(self,val):
00095 self._meta_space_dom = val
00096 self._meta_space_rng = val
00097
00098 meta = property( fset=_set_meta )
00099 meta_domain = property( _get_meta_dom, _set_meta_dom )
00100 meta_range = property( _get_meta_rng, _set_meta_rng )
00101
00102 def copy( self ):
00103 new = AugmentBase.copy( self )
00104
00105 new.meta_domain = self.meta_domain
00106 new.meta_range = self.meta_range
00107 return new
00108
00109 def domain( self ):
00110 """
00111 return inSpace
00112 """
00113
00114 pkw_obj = self.__pk_expannder__()
00115 dom = self.__attr_func__( "domain", pkw_obj )
00116
00117 colspace = apply_along_axis( lambda axis:VectorAddition( axis.tolist() ) ,0, dom )
00118
00119 if colspace.size == 1:
00120 return colspace.item()
00121
00122 colspace = colspace.view( MetaSpace )
00123 colspace.meta = self.meta_domain
00124
00125 return colspace
00126
00127
00128 def range( self ):
00129 """
00130 return outSpace
00131 """
00132 pkw_obj = self.__pk_expannder__()
00133 rng = self.__attr_func__( "range", pkw_obj )
00134
00135
00136
00137 rowspace = apply_along_axis( lambda axis:VectorAddition( axis.tolist() ) ,1, rng )
00138
00139 if rowspace.size == 1:
00140 return rowspace.item()
00141
00142 rowspace = rowspace.view( MetaSpace )
00143 rowspace.meta = self.meta_domain
00144
00145 return rowspace
00146
00147 def adj( self ):
00148 """
00149 The adjoint flips the operator_dict key transp. and updates the domain and range.
00150 """
00151
00152 adj = self.transpose( )
00153
00154 pkw_obj = self.__pk_expannder__()
00155 SH = adj.__attr_func__( 'adj', pkw_obj )
00156
00157 SH.meta_range = self.meta_range
00158 SH.meta_domain = self.meta_domain
00159
00160 return SH
00161
00162 H = property( adj )
00163
00164 def _getadj( self ):
00165 "get the adj key in the kparams"
00166 raise NotImplementedError
00167
00168 def _setadj( self, val ):
00169 "set the adj key in the kparams"
00170 raise NotImplementedError
00171
00172 isadj = property( _getadj , _setadj )
00173
00174 def __mul__( self, other ):
00175 """
00176 Not defined in this class
00177 """
00178 return self.applyop( other )
00179
00180 def __call__( self, other ):
00181 """
00182 Not defined in this class
00183 """
00184 return self.applyop( other )
00185
00186 def applyop( self, other ):
00187
00188 if is_oper( other ):
00189 return CompoundOperator( [self, other] )
00190 import pdb
00191 if is_number( other ):
00192 new = self.copy( )
00193 for i, oper in enumerate(new.flat):
00194 if is_oper( oper ):
00195 D = DiagonalWeight( oper.range(), other )
00196 C = CompoundOperator( [oper, D] )
00197 elif oper is 0:
00198 C = 0
00199 else:
00200 C = oper * other
00201
00202 new.flat[i] = C
00203
00204 return new
00205
00206 n = self.shape[1]
00207 m = 1
00208 if is_array( other ): m = other.size
00209
00210 assert m == n, "AugOperator expected an Augment Vector of length %s, got length %s" %(n,m)
00211
00212
00213 if is_array( other ):
00214 other_long_vector = other.reshape( [-1, 1] )
00215 new = mat( self ) * other_long_vector
00216
00217 else:
00218 new = asarray( self ) * other
00219
00220 if is_array( new ):
00221 other_cls = AugVector
00222 if new.size == 1:
00223 ret = new.item()
00224 else:
00225 ret = new.view( other_cls )
00226 else:
00227 ret = new
00228
00229 if is_array( ret ):
00230 ret.meta = self.meta_range
00231
00232 return ret
00233
00234
00235 def getdim( self ):
00236 """
00237 Returns the dimensions of the operator. Usually not defined.
00238 """
00239 raise NotImplementedError
00240 return [ len( self.domain( ) ), len( self.range( ) )]
00241
00242 def norm( self ):
00243 """
00244 returns Identity
00245 """
00246 raise NotImplementedError
00247
00248 def normalize( self ):
00249 """
00250 returns comp( [self.norm(), self] )
00251 """
00252 raise NotImplementedError
00253
00254 def minvelconst( self, *args, **kargs ):
00255 """
00256 returns Identity
00257 """
00258 raise NotImplementedError
00259