PLearn 0.1
|
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 :