PLearn 0.1
ObservationWindow.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // ObservationWindow.cc
00003 // 
00004 // Copyright (C) 2006 Christian Dorion
00005 // Copyright (C) 2006 ApStat Technologies Inc.
00006 // Copyright (C) 2007 Xavier Saint-Mleux, ApSTAT Technologies inc.
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00037 #include "ObservationWindow.h"
00038 
00039 namespace PLearn {
00040 using namespace std;
00041 
00042 PLEARN_IMPLEMENT_OBJECT(
00043     ObservationWindow,
00044     "Used by StatsCollector to keep a finite-size window of observations",
00045     "This allows StatsCollector to compute finite-horizon moving averages, for\n"
00046     "instance."
00047     );
00048 
00049 
00050 ObservationWindow::ObservationWindow(int window)
00051     : m_window(window), unlimited_size(window == -2)
00052 {
00053     forget();
00054 }
00055 
00056 
00057 // ### Nothing to add here, simply calls build_
00058 void ObservationWindow::build()
00059 {
00060     inherited::build();
00061     build_();
00062 }
00063 
00064 void ObservationWindow::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00065 {
00066     inherited::makeDeepCopyFromShallowCopy(copies);
00067 
00068     // ### Call deepCopyField on all "pointer-like" fields
00069     // ### that you wish to be deepCopied rather than
00070     // ### shallow-copied.
00071     // ### ex:
00072     // deepCopyField(trainvec, copies);
00073 
00074     // ### Remove this line when you have fully implemented this method.
00075     //PLERROR("ObservationWindow::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!");
00076 
00077     deepCopyField(m_observations, copies);
00078     deepCopyField(m_obs_weights,  copies);
00079     deepCopyField(m_last_update_rvalue,  copies);
00080 
00081 }
00082 
00083 void ObservationWindow::declareOptions(OptionList& ol)
00084 {
00085     // ### Declare all of this object's options here.
00086     // ### For the "flags" of each option, you should typically specify
00087     // ### one of OptionBase::buildoption, OptionBase::learntoption or
00088     // ### OptionBase::tuningoption. If you don't provide one of these three,
00089     // ### this option will be ignored when loading values from a script.
00090     // ### You can also combine flags, for example with OptionBase::nosave:
00091     // ### (OptionBase::buildoption | OptionBase::nosave)
00092 
00093     // ### ex:
00094     // declareOption(ol, "myoption", &ObservationWindow::myoption,
00095     //               OptionBase::buildoption,
00096     //               "Help text describing this option");
00097     // ...
00098 
00099     declareOption(ol, "window", &ObservationWindow::m_window,
00100                   OptionBase::buildoption,
00101                   "Window length");
00102 
00103     declareOption(ol, "nobs", &ObservationWindow::m_nobs,
00104                   OptionBase::learntoption,
00105                   "nb. observations");
00106 
00107     declareOption(ol, "cursor", &ObservationWindow::m_cursor,
00108                   OptionBase::learntoption | OptionBase::nosave | OptionBase::remotetransmit,
00109                   "cursor pos.");
00110 
00111     declareOption(ol, "observations", &ObservationWindow::m_observations,
00112                   OptionBase::learntoption | OptionBase::nosave | OptionBase::remotetransmit,
00113                   "the observations themselves");
00114 
00115     declareOption(ol, "obs_weights", &ObservationWindow::m_obs_weights,
00116                   OptionBase::learntoption | OptionBase::nosave | OptionBase::remotetransmit,
00117                   "observation weights");
00118 
00119     declareOption(ol, "last_update_rvalue", &ObservationWindow::m_last_update_rvalue,
00120                   OptionBase::learntoption | OptionBase::nosave | OptionBase::remotetransmit,
00121                   "last_update_rvalue");
00122 
00123     // Now call the parent class' declareOptions
00124     inherited::declareOptions(ol);
00125 }
00126 
00127 void ObservationWindow::build_()
00128 {
00129     // ### This method should do the real building of the object,
00130     // ### according to set 'options', in *any* situation.
00131     // ### Typical situations include:
00132     // ###  - Initial building of an object from a few user-specified options
00133     // ###  - Building of a "reloaded" object: i.e. from the complete set of
00134     // ###    all serialised options.
00135     // ###  - Updating or "re-building" of an object after a few "tuning"
00136     // ###    options have been modified.
00137     // ### You should assume that the parent class' build_() has already been
00138     // ### called.
00139 }
00140 
00141 
00142 
00143 int ObservationWindow::length() const
00144 {
00145     return m_observations.length();
00146 }
00147 
00148 void ObservationWindow::forget()        
00149 {
00150     m_nobs = 0;
00151     m_cursor = 0;
00152     if(unlimited_size)
00153         m_window= 0;
00154     else if(m_window >= 0)
00155         m_observations.resize(m_window, 0);
00156     m_observations.resize(0, 0);                
00157 }
00158 
00159 tuple<Vec, real>
00160 ObservationWindow::update(const Vec& obs, real weight/*=1.0*/)
00161 {
00162     Vec outdated;
00163     real outdated_weight = 0.0;
00164     
00165     ++m_nobs;
00166     if(unlimited_size) m_window= m_nobs;
00167     int new_size= MIN(m_nobs,m_window);
00168     int extra= unlimited_size? new_size : 0;//extra rows to alloc. when resizing
00169     m_observations.resize(new_size, obs.size(), extra*obs.size());
00170     m_obs_weights.resize(new_size, extra);
00171     if (m_nobs > m_window)
00172     {
00173         outdated.resize(obs.size());
00174         outdated << m_observations(m_cursor % m_window);
00175         outdated_weight = m_obs_weights[m_cursor % m_window];
00176         m_nobs--;
00177     }
00178 
00179     m_observations(m_cursor % m_window) << obs;
00180     m_obs_weights[m_cursor % m_window] = weight;
00181     m_cursor++;        
00182     
00183     PLASSERT( m_nobs <= m_window );
00184     m_last_update_rvalue = tuple<Vec, real>(outdated, outdated_weight);
00185     return m_last_update_rvalue;
00186 }
00187 
00188 const Vec ObservationWindow::getObs(int t) const
00189 {
00190     PLASSERT( t < m_window );
00191     if ( length() < m_window )
00192         return m_observations(t);
00193 
00194     int obs_index = (m_cursor+t) % m_window;
00195     return m_observations(obs_index);
00196 }
00197 
00198 real ObservationWindow::getObs(int t, int col) const
00199 {
00200     PLASSERT( t < m_window ); 
00201     if ( length() < m_window )
00202         return m_observations(t, col);
00203 
00204     int obs_index = (m_cursor+t) % m_window;
00205     return m_observations(obs_index, col);
00206 }
00207 
00208 real ObservationWindow::getWeight(int t) const
00209 {
00210     PLASSERT( t < m_window ); 
00211     if ( length() < m_window )
00212         return m_obs_weights[t];
00213 
00214     int obs_index = (m_cursor+t) % m_window;
00215     return m_obs_weights[obs_index];
00216 }
00217 
00218 const Vec ObservationWindow::lastObs() const
00219 {
00220     int last_obs = (m_cursor-1) % m_window;
00221     return m_observations(last_obs);
00222 }
00223 
00224 real ObservationWindow::lastWeight() const
00225 {
00226     int last_obs = (m_cursor-1) % m_window;
00227     return m_obs_weights[last_obs];
00228 }
00229 
00230 // The TMatElementIterator<double> are not as easy to handle as real*...
00231 //
00232 //TBA:// Get the min/max value in a column
00233 //TBA:void ObservationWindow::columnMin(int col, real& min, real& agemin) const
00234 //TBA:{
00235 //TBA:    const Mat& column = m_observations.column(col);
00236 //TBA:    real* beg = column.begin();
00237 //TBA:    real* ptr = std::min_element(beg, column.end());
00238 //TBA:    min = *ptr;
00239 //TBA:
00240 //TBA:    // The cursor is now at the position *after* the position of the last added
00241 //TBA:    // value... 
00242 //TBA:    agemin = abs((ptr - beg) - m_cursor);
00243 //TBA:    if ( agemin == 0 )
00244 //TBA:        agemin = m_window;
00245 //TBA:}
00246 //TBA:
00247 //TBA:void ObservationWindow::columnMax(int col, real& max, real& agemax) const
00248 //TBA:{
00249 //TBA:    const Mat& column = m_observations.column(col);
00250 //TBA:    real* beg = column.begin();
00251 //TBA:    real* ptr = std::max_element(beg, column.end());
00252 //TBA:    max = *ptr;
00253 //TBA:
00254 //TBA:    // The cursor is now at the position *after* the position of the last added
00255 //TBA:    // value... 
00256 //TBA:    agemax = abs((ptr - beg) - m_cursor);
00257 //TBA:    if ( agemax == 0 )
00258 //TBA:        agemax = m_window;
00259 //TBA:}
00260 
00261 /*
00263 ObservationWindow* ObservationWindow::deepCopy(CopiesMap& copies) const
00264 {
00265     CopiesMap::iterator it = copies.find(this);
00266     if(it!=copies.end())  //!<  a copy already exists, so return it
00267         return (ObservationWindow*) it->second;
00268   
00270     ObservationWindow* deep_copy = new ObservationWindow(*this);
00271     deepCopyField(deep_copy->m_observations, copies);
00272     deepCopyField(deep_copy->m_obs_weights,  copies);
00273 
00275     copies[this] = deep_copy;
00276 
00278     return deep_copy;
00279 }
00280 */
00281 
00282 } // end of namespace PLearn
00283 
00284 
00285 /*
00286   Local Variables:
00287   mode:c++
00288   c-basic-offset:4
00289   c-file-style:"stroustrup"
00290   c-file-offsets:((innamespace . 0)(inline-open . 0))
00291   indent-tabs-mode:nil
00292   fill-column:79
00293   End:
00294 */
00295 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines