contrib/mul/mcal/mcal_sparse_basis_cost.cxx
Go to the documentation of this file.
00001 #include "mcal_sparse_basis_cost.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Cost function to promote sparse basis vectors
00006 
00007 #include <vcl_cstdlib.h>
00008 #include <vcl_string.h>
00009 #include <vcl_cmath.h>
00010 #include <vcl_sstream.h>
00011 
00012 #include <vsl/vsl_indent.h>
00013 #include <vsl/vsl_binary_io.h>
00014 #include <vul/vul_string.h>
00015 #include <mbl/mbl_parse_block.h>
00016 #include <mbl/mbl_read_props.h>
00017 #include <mbl/mbl_exception.h>
00018 
00019 //=======================================================================
00020 // Constructors
00021 //=======================================================================
00022 
00023 mcal_sparse_basis_cost::mcal_sparse_basis_cost()
00024 {
00025   alpha_ = 1.0;
00026 }
00027 
00028 //=======================================================================
00029 // Destructor
00030 //=======================================================================
00031 
00032 mcal_sparse_basis_cost::~mcal_sparse_basis_cost()
00033 {
00034 }
00035 
00036 //: Weighting for sparseness penalty
00037 void mcal_sparse_basis_cost::set_alpha(double a)
00038 {
00039   alpha_ = a;
00040 }
00041 
00042 //: Returns true since cost can be computed from the variance.
00043 bool mcal_sparse_basis_cost::can_use_variance() const
00044 {
00045   return true;
00046 }
00047 
00048   //: Compute component of the cost function from given basis vector
00049   // \param[in] unit_basis   Unit vector defining basis direction
00050   // \param[in] projections  Projections of the dataset onto this basis vector
00051 double mcal_sparse_basis_cost::cost(const vnl_vector<double>& unit_basis,
00052                                     const vnl_vector<double>& projections)
00053 {
00054   double var = projections.squared_magnitude()/projections.size();
00055   return cost_from_variance(unit_basis,var);
00056 }
00057 
00058   //: Compute component of the cost function from given basis vector
00059   // Cost is log(variance) + alpha sum |e_i|.
00060   // \param[in] unit_basis Unit vector defining basis direction
00061   // \param[in] variance   Variance of projections of the dataset onto this basis vector
00062 double mcal_sparse_basis_cost::cost_from_variance(const vnl_vector<double>& unit_basis,
00063                                                   double variance)
00064 {
00065   return vcl_log(1e-8+variance) + alpha_ * unit_basis.one_norm();
00066 }
00067 
00068 
00069 //=======================================================================
00070 // Method: is_a
00071 //=======================================================================
00072 
00073 vcl_string  mcal_sparse_basis_cost::is_a() const
00074 {
00075   return vcl_string("mcal_sparse_basis_cost");
00076 }
00077 
00078 //=======================================================================
00079 // Method: version_no
00080 //=======================================================================
00081 
00082 short mcal_sparse_basis_cost::version_no() const
00083 {
00084   return 1;
00085 }
00086 
00087 //=======================================================================
00088 // Method: clone
00089 //=======================================================================
00090 
00091 mcal_single_basis_cost* mcal_sparse_basis_cost::clone() const
00092 {
00093   return new mcal_sparse_basis_cost(*this);
00094 }
00095 
00096 //=======================================================================
00097 // Method: print
00098 //=======================================================================
00099 
00100 void mcal_sparse_basis_cost::print_summary(vcl_ostream& os) const
00101 {
00102   os<<vsl_indent()<<"alpha: "<<alpha_;
00103 }
00104 
00105 //=======================================================================
00106 // Method: save
00107 //=======================================================================
00108 
00109 void mcal_sparse_basis_cost::b_write(vsl_b_ostream& bfs) const
00110 {
00111   vsl_b_write(bfs,version_no());
00112   vsl_b_write(bfs,alpha_);
00113 }
00114 
00115 //=======================================================================
00116 // Method: load
00117 //=======================================================================
00118 
00119 void mcal_sparse_basis_cost::b_read(vsl_b_istream& bfs)
00120 {
00121   short version;
00122   vsl_b_read(bfs,version);
00123   switch (version)
00124   {
00125     case (1):
00126       vsl_b_read(bfs,alpha_);
00127       break;
00128     default:
00129       vcl_cerr << "mcal_sparse_basis_cost::b_read()\n"
00130                << "Unexpected version number " << version << vcl_endl;
00131       vcl_abort();
00132   }
00133 }
00134 
00135 //=======================================================================
00136 //: Read initialisation settings from a stream.
00137 // Parameters:
00138 // \verbatim
00139 // {
00140 //   min_modes: 0 max_modes: 99 prop_modes: 0.99
00141 //   // Maximum number of doubles to store in memory at once
00142 //   max_d_in_memory: 1e8
00143 //   // Indicate how to build from large amounts of data
00144 //   use_chunks: false
00145 // }
00146 // \endverbatim
00147 // \throw mbl_exception_parse_error if the parse fails.
00148 void mcal_sparse_basis_cost::config_from_stream(vcl_istream & is)
00149 {
00150   vcl_string s = mbl_parse_block(is);
00151 
00152   vcl_istringstream ss(s);
00153   mbl_read_props_type props = mbl_read_props_ws(ss);
00154 
00155   if (!props["alpha"].empty())
00156   {
00157     alpha_=vul_string_atof(props["alpha"]);
00158   }
00159   props.erase("alpha");
00160 
00161   try
00162   {
00163     mbl_read_props_look_for_unused_props(
00164           "mcal_sparse_basis_cost::config_from_stream", props);
00165   }
00166   catch(mbl_exception_unused_props &e)
00167   {
00168     throw mbl_exception_parse_error(e.what());
00169   }
00170 }