2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
21 * @author Marion Foare (\c marion.foare@univ-savoie.fr )
22 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
26 * Implementation of inline methods defined in ATu0v1.h
28 * This file is part of the DGtal library.
32 //////////////////////////////////////////////////////////////////////////////
34 //////////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////////
37 // IMPLEMENTATION of inline methods.
38 ///////////////////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////////////////
41 // ----------------------- Standard services ------------------------------
42 template <typename TKSpace, typename TLinearAlgebra>
43 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
44 ATu0v1( int _verbose )
46 v1( calculus ), former_v1( calculus ),
47 L1( calculus ), alpha_Id0( calculus ),
48 l_L1( calculus ), l_1_over_4( calculus ),
49 left_V1( calculus ), l_1_over_4e( calculus )
52 template <typename TKSpace, typename TLinearAlgebra>
54 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
55 init( Clone<KSpace> aKSpace )
57 Base::init( aKSpace );
58 if ( verbose > 0 ) trace.beginBlock( "Initialize DEC specific operators" );
59 if ( verbose > 1 ) trace.info() << "primal_L1" << std::endl;
60 L1 = -1.0 * ( D0 * dual_h2 * dual_D1 * primal_h1
61 + dual_h1 * dual_D0 * primal_h2 * D1 );
62 // JOL: Does not work ! Sign problem ?
63 // L1 = -1.0 * ( D0 * AD1 + AD2 * D1 );
64 if ( verbose > 1 ) trace.info() << "v1" << std::endl;
65 v1 = KForm<Calculus, 1, PRIMAL>::ones( calculus );
66 if ( verbose > 0 ) trace.endBlock();
69 //-----------------------------------------------------------------------------
70 template <typename TKSpace, typename TLinearAlgebra>
71 template <typename Image, typename Function>
73 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
74 addInput( const Image& image,
78 if ( perfect_data ) i0.push_back( PrimalForm0( calculus ) );
79 else g0.push_back( PrimalForm0( calculus ) );
80 PrimalForm0& g = perfect_data ? i0.back() : g0.back();
81 const KSpace& K = calculus.myKSpace;
82 for ( Index index = 0; index < g.myContainer.rows(); index++)
84 SCell cell = g.getSCell( index );
85 g.myContainer( index ) = f( image( K.sCoords( cell ) ) );
89 //-----------------------------------------------------------------------------
90 template <typename TKSpace, typename TLinearAlgebra>
91 typename DGtal::ATu0v1<TKSpace, TLinearAlgebra>::Scalar
92 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
96 for ( Dimension i = 0; i < i0.size(); ++i )
99 const PrimalForm0 u_minus_i_snr = u0[ i ] - i0[ i ];
100 for ( Index j = 0; j < u_minus_i_snr.length(); ++j )
101 MSEi += u_minus_i_snr.myContainer( j ) * u_minus_i_snr.myContainer( j );
102 MSE += MSEi / (Scalar) u_minus_i_snr.length();
105 return 10.0 * log10(1.0 / MSE);
108 //-----------------------------------------------------------------------------
109 template <typename TKSpace, typename TLinearAlgebra>
111 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
112 setAlpha( Scalar _alpha )
114 ASSERT( _alpha >= 0.0 );
116 // Building alpha_Id0
117 alpha_Id0 = _alpha * calculus.template identity<0, PRIMAL>();
119 for ( unsigned int i = 0; i < g0.size(); i++ )
120 alpha_g0.push_back( alpha_Id0 * g0[ i ] );
123 //-----------------------------------------------------------------------------
124 template <typename TKSpace, typename TLinearAlgebra>
126 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
127 setAlpha( Scalar _alpha, const PrimalForm0& m )
129 ASSERT( _alpha >= 0.0 );
131 // Building alpha_Id0
132 alpha_Id0 = _alpha * functions::dec::diagonal( m ) * calculus.template identity<0, PRIMAL>();
134 for ( unsigned int i = 0; i < g0.size(); i++ )
135 alpha_g0.push_back( alpha_Id0 * g0[ i ] );
138 //-----------------------------------------------------------------------------
139 template <typename TKSpace, typename TLinearAlgebra>
141 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
142 setLambda( Scalar _lambda )
144 ASSERT( _lambda >= 0.0 );
147 l_1_over_4 = (lambda / 4.0 ) * KForm< Calculus, 1, PRIMAL >::ones( calculus );
150 //-----------------------------------------------------------------------------
151 template <typename TKSpace, typename TLinearAlgebra>
153 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
154 setEpsilon( Scalar _epsilon )
156 ASSERT( _epsilon > 0.0 );
158 left_V1 = epsilon * l_L1 +
159 ( lambda/(4.0*epsilon) ) * calculus.template identity<1, PRIMAL>();
160 l_1_over_4e = (1.0/epsilon) * l_1_over_4;
163 //-----------------------------------------------------------------------------
164 template <typename TKSpace, typename TLinearAlgebra>
166 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
172 //-----------------------------------------------------------------------------
173 template <typename TKSpace, typename TLinearAlgebra>
175 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
178 if ( verbose > 0 ) trace.beginBlock("Solving for u");
179 if ( verbose > 1 ) trace.info() << "- building matrix M : = alpha_Id0 - tA_Diag(v)^2_A" << std::endl;
181 PrimalIdentity1 diag_vv = functions::dec::squaredDiagonal( v1 );
182 PrimalIdentity0 Av2A = D0.transpose() * diag_vv * D0 + alpha_Id0;
183 if ( verbose > 1 ) trace.info() << "- prefactoring matrix M" << std::endl;
184 solver_u.compute( Av2A );
186 for ( Dimension i = 0; i < u0.size(); ++i )
188 if ( verbose > 1 ) trace.info() << "- solving M u[" << i << "] = alpha g[" << i << "]" << std::endl;
189 u0[ i ] = solver_u.solve( alpha_g0[ i ] );
190 if ( verbose > 1 ) trace.info() << ( solver_u.isValid() ? "=> OK" : "ERROR" ) << " " << solver_u.myLinearAlgebraSolver.info() << std::endl;
191 ok = ok && solver_u.isValid();
193 if ( verbose > 0 ) trace.endBlock();
197 //-----------------------------------------------------------------------------
198 template <typename TKSpace, typename TLinearAlgebra>
200 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
204 if ( verbose > 0 ) trace.beginBlock("Solving for v");
205 if ( verbose > 1 ) trace.info() << "- building matrix N := l/4e Id1 + le (tA' A' + tB B) + sum Diag(Au_i)^2" << std::endl;
206 // Not the same result as below ! Seems the "good" way of doing it.
207 PrimalIdentity1 N = left_V1;
208 for ( Dimension i = 0; i < u0.size(); ++i )
210 PrimalIdentity1 U2 = functions::dec::squaredDiagonal( D0 * u0[ i ] );
211 N.myContainer += U2.myContainer;
213 // Seems the "bad" way of doing it.
214 // PrimalIdentity0 U2 = functions::dec::squaredDiagonal( u0[ 0 ] );
215 // for ( Dimension i = 1; i < u0.size(); ++i )
216 // U2.myContainer += functions::dec::squaredDiagonal( u0[ i ] ).myContainer;
217 // PrimalIdentity1 N = left_V1 + D0 * U2 * D0.transpose();
218 typedef typename PrimalIdentity1::Container Matrix;
219 const Matrix & M = N.myContainer;
221 for (int k = 0; k < M.outerSize(); ++k)
222 for ( typename Matrix::InnerIterator it( M, k ); it; ++it )
223 if ( ( verbose > 3 ) || ( it.row() == it.col() ) )
224 trace.info() << "[" << it.row() << "," << it.col() << "] = " << it.value() << std::endl;
225 if ( verbose > 1 ) trace.info() << "- prefactoring matrix N" << std::endl;
226 solver_v.compute( N );
227 if ( verbose > 1 ) trace.info() << "- solving N v = l/4e 1" << std::endl;
228 v1 = solver_v.solve( l_1_over_4e );
229 if ( verbose > 1 ) trace.info() << ( solver_v.isValid() ? "OK" : "ERROR" )
230 << " " << solver_v.myLinearAlgebraSolver.info()
232 if ( verbose > 0 ) trace.endBlock();
233 return solver_v.isValid();
236 //-----------------------------------------------------------------------------
237 template <typename TKSpace, typename TLinearAlgebra>
238 typename DGtal::ATu0v1<TKSpace, TLinearAlgebra>::Scalar
239 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
242 if ( verbose > 0 ) trace.beginBlock( "Compute variation of v.");
246 for ( Index index = 0; index < size1(); index++)
248 delta_v_loo = std::max( delta_v_loo, std::fabs( v1.myContainer( index )
249 - former_v1.myContainer( index ) ) );
250 delta_v_l2 += ( v1.myContainer( index ) - former_v1.myContainer( index ) )
251 * ( v1.myContainer( index ) - former_v1.myContainer( index ) );
252 delta_v_l1 += fabs( v1.myContainer( index )
253 - former_v1.myContainer( index ) );
255 delta_v_l1 /= size1();
256 delta_v_l2 = sqrt( delta_v_l2 / size1() );
258 trace.info() << "Variation |v^k+1 - v^k|_oo = " << delta_v_loo << std::endl;
259 trace.info() << "Variation |v^k+1 - v^k|_2 = " << delta_v_l2 << std::endl;
260 trace.info() << "Variation |v^k+1 - v^k|_1 = " << delta_v_l1 << std::endl;
262 if ( verbose > 0 ) trace.endBlock();
266 //-----------------------------------------------------------------------------
267 template <typename TKSpace, typename TLinearAlgebra>
268 typename DGtal::ATu0v1<TKSpace, TLinearAlgebra>::Scalar
269 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::
272 if ( verbose > 0 ) trace.beginBlock("Checking v");
276 for ( Index index = 0; index < size1(); index++)
278 Scalar val = v1.myContainer( index );
279 m1 = std::min( m1, val );
280 m2 = std::max( m2, val );
284 trace.info() << "1-form v: min=" << m1 << " avg=" << ( ma / size1() )
285 << " max=" << m2 << std::endl;
286 // for ( Index index = 0; index < size1(); index++)
287 // v1.myContainer( index ) = std::min( std::max(v1.myContainer( index ), 0.0) , 1.0 );
288 if ( verbose > 0 ) trace.endBlock();
289 return std::max( std::fabs( m1 ), std::fabs( m2 - 1.0 ) );
293 ///////////////////////////////////////////////////////////////////////////////
294 // Interface - public :
297 * Writes/Displays the object on an output stream.
298 * @param out the output stream where the object is written.
300 template <typename TKSpace, typename TLinearAlgebra>
303 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::selfDisplay ( std::ostream & out ) const
305 out << "[ ATu0v1 #g=" << g0.size() << " dec=" << calculus << " ]";
309 * Checks the validity/consistency of the object.
310 * @return 'true' if the object is valid, 'false' otherwise.
312 template <typename TKSpace, typename TLinearAlgebra>
315 DGtal::ATu0v1<TKSpace, TLinearAlgebra>::isValid() const
322 ///////////////////////////////////////////////////////////////////////////////
323 // Implementation of inline functions //
325 template <typename TKSpace, typename TLinearAlgebra>
328 DGtal::operator<< ( std::ostream & out,
329 const ATu0v1<TKSpace, TLinearAlgebra> & object )
331 object.selfDisplay( out );
336 ///////////////////////////////////////////////////////////////////////////////