00001 """
00002 General solver builder
00003 """
00004 from slimpy_base.User.adiFactories import VectorFactory as _vf
00005 from slimpy_base.utils.slim_decorators import depends_on,depends_on_functions
00006 from slimpy_base.setup.ParseEnv import parse_env
00007 from slimpy_base.Environment.InstanceManager import InstanceManager
00008
00009
00010 __author__ = "Sean Ross-Ross"
00011
00012 vector = _vf( )
00013 __env__ = InstanceManager( )
00014
00015 @depends_on( 'solver')
00016 @depends_on_functions('setup_callback')
00017 @depends_on_functions('precondition_callback')
00018 @depends_on_functions('transform_callback')
00019 @depends_on_functions('inv_callback')
00020 @depends_on_functions('solver_callback')
00021 @depends_on_functions('result_callback')
00022 def SolveBuilder( target, source, env ):
00023 """
00024 @ingroup sconsint
00025
00026 Base solve routine with no default values
00027 env must define the following functions:
00028
00029 @param problem is a package containing default callbacks and documentation.
00030 see \ref contrib_problems for a list of existing problems in SLIMpy
00031
00032 @param setup_callback defined as setup_callback( target, source, env ):
00033 returns the initial vector, useful for
00034 managing augmented vectors
00035
00036 @param solver_callback defined as solver_callback( target, source, env, A ):
00037 returns a solver instance
00038
00039 @param precondition_callback defined as precondition_callback( target, source, env, space ):
00040 returns the preconditioner linear operator 'P'
00041
00042 @param transform_callback defined as transform_callback( target, source, env, space ):
00043 returns the transform 'A' to pass to the solver
00044 'solve' method
00045
00046 @param inv_callback defined as inv_callback( target, source, env, space ):
00047 optional, returns the linear operator 'C'
00048 in not specified uses the \a transform_callback
00049
00050 @param result_callback defined as result_callback( target, source, env, result )
00051 returns None
00052 sets the name of the result, useful for
00053 managing augmented vectors
00054
00055
00056 @remarks
00057 Solves The system of equations:
00058 @code
00059 >>> b = P*data
00060 >>> x = solver.solve(A, b )
00061 >>> result = P.adj() * ( C*x )
00062 @endcode
00063 where:
00064 - \a data is the result of calling setup_callback
00065 - \a P is the result of calling precondition_callback
00066 - \a solver is the result of calling solver_callback
00067 - \a C is the result of calling inv_callback
00068 \par
00069 also
00070 - \a result will be given to result_callback if it was given otherwise
00071 SolveBuilder calls result.setName for the fist SCons target passed in.
00072
00073 \par Examle
00074 The SolveBuilder builder ultimately ends up as a SLIMpy builder.
00075 Using SolveBuilder in SCons is a bit different. In SCons SolveBulider
00076 is just called Solve.
00077 @code
00078 from slimproj import *
00079 from SLIMpy.problems import *
00080 def transform_callback( target, source, env, space ):
00081 return Identity( space )
00082 Solve( target, source, problem=l2_min_problem,
00083 transform_callback=transform_callback )
00084
00085 @endcode
00086
00087 \sa \ref slimpy_contrib.problems "problems"
00088 """
00089 parse_env( env )
00090
00091 default_package = env.get( 'problem', env.get( 'default_pack' ,{} ) )
00092 Get = lambda name : env.get( name, default_package.get(name) )
00093
00094
00095 vector_setup = Get( 'setup_callback')
00096 if vector_setup is None:
00097 data = vector( str( source[0] ) )
00098 else:
00099 data = vector_setup( target,source, env )
00100
00101
00102
00103
00104
00105 precondition_callback = Get( 'precondition_callback' )
00106 if precondition_callback is not None:
00107 P = precondition_callback( target,source, env, data.space )
00108 else:
00109 raise Exception( "need to specify precondition_callback")
00110
00111
00112
00113
00114
00115 transform_callback = Get( 'transform_callback' )
00116 if transform_callback is not None:
00117 A = transform_callback( target, source, env, P.range() )
00118 else:
00119 raise Exception( "need to specify transform_callback")
00120
00121
00122
00123
00124
00125 inv_callback = Get( 'inv_callback' )
00126 if inv_callback is not None:
00127 C = inv_callback( target, source, env, P.range( ) )
00128 else:
00129 C = A
00130
00131
00132
00133
00134
00135 solver = Get( 'solver' )
00136 if solver is None:
00137 solver_callback = Get( 'solver_callback' )
00138 if solver_callback is not None:
00139 solver = solver_callback( target, source, env, A )
00140 if solver is None:
00141 raise Exception( "need to specify 'solver' or 'solver_callback' ")
00142
00143
00144
00145
00146
00147 result_callback = Get( 'result_callback' )
00148
00149
00150
00151
00152
00153 b = P*data
00154
00155 x = solver.solve(A, b )
00156
00157 result = P.adj() * ( C*x )
00158
00159
00160
00161
00162
00163 if result_callback is None:
00164 result.setName( str( target[0] ) )
00165 else:
00166 result_callback( target, source, env, result )
00167
00168 __env__.Execute( )
00169 return result
00170
00171 SolveBuilder.__example__ = """
00172 Solve( b, x, transform_callback=operator, solver=my_solver )
00173 """
00174
00175
00176