TooN 2.1
irls.h
00001 // -*- c++ -*-
00002 
00003 // Copyright (C) 2005,2009 Tom Drummond (twd20@cam.ac.uk)
00004 //
00005 // This file is part of the TooN Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 
00031 #ifndef __IRLS_H
00032 #define __IRLS_H
00033 
00034 #include <TooN/wls.h>
00035 #include <cassert>
00036 #include <cmath>
00037 
00038 namespace TooN {
00039 
00040     /// Robust reweighting (type I) for IRLS.
00041     /// A reweighting class with \f$w(x)=\frac{1}{\sigma + |x|}\f$.
00042     /// This structure can be passed as the second template argument in IRLS.
00043     /// @ingroup gEquations
00044     template<typename Precision>
00045     struct RobustI {
00046         void set_sd(Precision x){ sd_inlier = x;} ///<Set the noise standard deviation.
00047         double sd_inlier; ///< The inlier standard deviation, \f$\sigma\f$.
00048         inline Precision reweight(Precision x) {return 1/(sd_inlier+fabs(x));}  ///< Returns \f$w(x)\f$.
00049         inline Precision true_scale(Precision x) {return reweight(x) - fabs(x)*reweight(x)*reweight(x);}  ///< Returns \f$w(x) + xw'(x)\f$.
00050         inline Precision objective(Precision x) {return fabs(x) + sd_inlier*::log(sd_inlier*reweight(x));}  ///< Returns \f$\int xw(x)dx\f$.
00051     };
00052 
00053     /// Robust reweighting (type II) for IRLS.
00054     /// A reweighting class with \f$w(x)=\frac{1}{\sigma + x^2}\f$.
00055     /// This structure can be passed as the second template argument in IRLS.
00056     /// @ingroup gEquations
00057     template<typename Precision>
00058     struct RobustII {
00059         void set_sd(Precision x){ sd_inlier = x*x;} ///<Set the noise standard deviation.
00060         Precision sd_inlier; ///< The inlier standard deviation squared, \f$\sigma\f$.
00061         inline Precision reweight(Precision d){return 1/(sd_inlier+d*d);} ///< Returns \f$w(x)\f$.
00062         inline Precision true_scale(Precision d){return d - 2*d*reweight(d);} ///< Returns \f$w(x) + xw'(x)\f$.
00063         inline Precision objective(Precision d){return 0.5 * ::log(1 + d*d/sd_inlier);} ///< Returns \f$\int xw(x)dx\f$.
00064     };
00065 
00066     /// A reweighting class representing no reweighting in IRLS.
00067     /// \f$w(x)=1\f$
00068     /// This structure can be passed as the second template argument in IRLS.
00069     /// @ingroup gEquations
00070     template<typename Precision>
00071     struct ILinear {
00072         void set_sd(Precision){} ///<Set the noise standard deviation (does nothing).
00073         inline Precision reweight(Precision d){return 1;} ///< Returns \f$w(x)\f$.
00074         inline Precision true_scale(Precision d){return 1;} ///< Returns \f$w(x) + xw'(x)\f$.
00075         inline Precision objective(Precision d){return d*d;} ///< Returns \f$\int xw(x)dx\f$.
00076     };
00077     
00078     ///A reweighting class where the objective function tends to a 
00079     ///fixed value, rather than infinity. Note that this is not therefore
00080     ///a proper distribution since its integral is not finite. It is considerably
00081     ///more efficient than RobustI and II, since log() is not used.
00082     /// @ingroup gEquations
00083     template<typename Precision>
00084     struct RobustIII {
00085 
00086         void set_sd(Precision x){ sd_inlier = x*x;} ///<Set the noise standard deviation.
00087         Precision sd_inlier; ///< Inlier standard deviation squared.
00088         /// Returns \f$w(x)\f$.
00089         Precision reweight(Precision x) const
00090         {
00091             double d = (1 + x*x/sd_inlier);
00092             return 1/(d*d);
00093         }   
00094         ///< Returns \f$\int xw(x)dx\f$.
00095         Precision objective(Precision x) const 
00096         {
00097             return x*x / (2*(1 + x*x/sd_inlier));
00098         }
00099     };
00100 
00101     /// Performs iterative reweighted least squares.
00102     /// @param Size the size
00103     /// @param Reweight The reweighting functor. This structure must provide reweight(), 
00104     /// true-scale() and objective() methods. Existing examples are  Robust I, Robust II and ILinear.
00105     /// @ingroup gEquations
00106     template <int Size, typename Precision, template <typename Precision> class Reweight>
00107     class IRLS
00108         : public Reweight<Precision>,
00109           public WLS<Size,Precision>
00110     {
00111     public:
00112         IRLS(int size=Size):
00113             WLS<Size,Precision>(size),
00114             my_true_C_inv(Zeros(size))
00115         {
00116             my_residual=0;
00117         }
00118         
00119         template<int Size2, typename Precision2, typename Base2>
00120         inline void add_mJ(Precision m, const Vector<Size2,Precision2,Base2>& J) {
00121             SizeMismatch<Size,Size2>::test(my_true_C_inv.num_rows(), J.size());
00122 
00123             Precision scale = Reweight<Precision>::reweight(m);
00124             Precision ts = Reweight<Precision>::true_scale(m);
00125             my_residual += Reweight<Precision>::objective(m);
00126 
00127             WLS<Size>::add_mJ(m,J,scale);
00128 
00129             Vector<Size,Precision> scaledm(m*ts);
00130 
00131             my_true_C_inv += scaledm.as_col() * scaledm.as_row();
00132 
00133         }
00134 
00135         void operator += (const IRLS& meas){
00136             WLS<Size>::operator+=(meas);
00137             my_true_C_inv += meas.my_true_C_inv;
00138         }
00139 
00140 
00141         Matrix<Size,Size,Precision>& get_true_C_inv() {return my_true_C_inv;}
00142         const Matrix<Size,Size,Precision>& get_true_C_inv()const {return my_true_C_inv;}
00143 
00144         Precision get_residual() {return my_residual;}
00145 
00146         void clear(){
00147             WLS<Size,Precision>::clear();
00148             my_residual=0;
00149             my_true_C_inv = Zeros;
00150         }
00151 
00152     private:
00153 
00154         Precision my_residual;
00155 
00156         Matrix<Size,Size,Precision> my_true_C_inv;
00157 
00158         // comment out to allow bitwise copying
00159         IRLS( IRLS& copyof );
00160         int operator = ( IRLS& copyof );
00161     };
00162 
00163 }
00164 
00165 #endif