PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PLearn (A C++ Machine Learning Library) 00004 // Copyright (C) 1998 Pascal Vincent 00005 // Copyright (C) 1999-2001 Pascal Vincent, Yoshua Bengio, Rejean Ducharme and University of Montreal 00006 // Copyright (C) 2002 Pascal Vincent, Julien Keable, Xavier Saint-Mleux 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 00036 00037 /* ******************************************************* 00038 * $Id: MemoryVMatrix.cc 9441 2008-09-08 20:01:39Z tihocan $ 00039 ******************************************************* */ 00040 00041 #include "MemoryVMatrix.h" 00042 00043 namespace PLearn { 00044 using namespace std; 00045 00046 00047 00050 PLEARN_IMPLEMENT_OBJECT( 00051 MemoryVMatrix, 00052 "A VMatrix whose data is stored in memory.", 00053 "The data can either be given directly by a Mat, or by another VMat that\n" 00054 "will be precomputed in memory at build time.\n" 00055 ); 00056 00058 // MemoryVMatrix // 00060 MemoryVMatrix::MemoryVMatrix() 00061 : synch_data(true), 00062 data(Mat()), 00063 deep_copy_memory_data(true) 00064 { 00065 memory_data = data; 00066 } 00067 00068 MemoryVMatrix::MemoryVMatrix(int l, int w) 00069 : inherited(l, w), 00070 synch_data(false), 00071 deep_copy_memory_data(true) 00072 { 00073 data.resize(l,w); 00074 memory_data = data; 00075 defineSizes(data.width(), 0, 0); 00076 } 00077 00078 MemoryVMatrix::MemoryVMatrix(const Mat& the_data) 00079 : inherited(the_data.length(), the_data.width()), 00080 synch_data(true), 00081 data(the_data), 00082 deep_copy_memory_data(true) 00083 00084 { 00085 memory_data = the_data; 00086 defineSizes(the_data.width(), 0, 0); 00087 } 00088 00089 MemoryVMatrix::MemoryVMatrix(VMat the_source, bool call_build_): 00090 inherited(the_source->length(), the_source->width(), call_build_), 00091 synch_data(false), 00092 source(the_source), 00093 deep_copy_memory_data(true) 00094 { 00095 if (call_build_) 00096 build_(); 00097 } 00098 00100 // declareOptions // 00102 void MemoryVMatrix::declareOptions(OptionList& ol) 00103 { 00104 declareOption(ol, "data", &MemoryVMatrix::data, OptionBase::buildoption, 00105 "The external Mat source"); 00106 00107 declareOption(ol, "data_vm", &MemoryVMatrix::source, 00108 (OptionBase::learntoption | OptionBase::nosave), 00109 "DEPRECATED - Use 'source' instead."); 00110 00111 declareOption(ol, "source", &MemoryVMatrix::source, 00112 OptionBase::buildoption, 00113 "The (optional) source VMatrix. Will overwrite 'data'" 00114 " if provided."); 00115 00116 declareOption( ol, "fieldnames", &MemoryVMatrix::fieldnames, 00117 OptionBase::buildoption, 00118 "If provided, will be used to set this VMatrix's" 00119 " fieldnames." ); 00120 00121 declareOption( ol, "deep_copy_memory_data", &MemoryVMatrix::deep_copy_memory_data, 00122 OptionBase::buildoption, 00123 "If true, when this object is deep copied, we will deep copy the memory_data"); 00124 00125 /* This field was declared as an option, but the author does not remember 00126 * why. The problem is that we do not want it to be a learnt option, since 00127 * it may save the whole dataset pointed by 'source', which could waste a 00128 * lot of disk space. 00129 * As a result, the two lines below are now commented out. 00130 declareOption(ol, "memory_data", &MemoryVMatrix::memory_data, OptionBase::learntoption, 00131 "The underlying Mat with the data."); 00132 */ 00133 00134 inherited::declareOptions(ol); 00135 } 00136 00138 // makeDeepCopyFromShallowCopy // 00140 void MemoryVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00141 { 00142 inherited::makeDeepCopyFromShallowCopy(copies); 00143 if(deep_copy_memory_data){ 00144 deepCopyField(memory_data, copies); 00145 deepCopyField(data, copies); 00146 } 00147 deepCopyField(fieldnames, copies); 00148 deepCopyField(source, copies); 00149 } 00150 00152 // build_ // 00154 void MemoryVMatrix::build_() 00155 { 00156 if (source) { 00157 // Precompute data from source 00158 memory_data = source->toMat(); 00159 copySizesFrom(source); 00160 setMetaInfoFrom(source); 00161 synch_data = false; 00162 } else { 00163 synch_data = true; 00164 } 00165 if (synch_data) { 00166 memory_data = data; 00167 // We temporarily set data to a new empty Mat, so that memory_data 00168 // can be safely resized. 00169 data = Mat(); 00170 } 00171 if (this->length() >= 0 && this->length() != memory_data.length()) { 00172 // New length specified. 00173 memory_data.resize(this->length(), memory_data.width()); 00174 } 00175 if (this->width() >= 0 && this->width() != memory_data.width()) { 00176 // New width specified. 00177 memory_data.resize(memory_data.length(), this->width()); 00178 } 00179 if (this->length() < 0 && memory_data.length() >= 0) { 00180 // Take the length from the data matrix. 00181 this->length_ = memory_data.length(); 00182 } 00183 if (this->width() < 0 && memory_data.width() >= 0) { 00184 // Take the width from the data matrix. 00185 this->width_ = memory_data.width(); 00186 } 00187 if (synch_data) 00188 // Restore data so that it is equal to memory_data. 00189 data = memory_data; 00190 00191 if ( fieldnames.length() == memory_data.width() ) 00192 declareFieldNames(fieldnames); 00193 } 00194 00196 // build // 00198 void MemoryVMatrix::build() 00199 { 00200 inherited::build(); 00201 build_(); 00202 } 00203 00205 // get // 00207 real MemoryVMatrix::get(int i, int j) const 00208 { return memory_data(i,j); } 00209 00210 void MemoryVMatrix::put(int i, int j, real value) 00211 { memory_data(i,j) = value; } 00212 00213 void MemoryVMatrix::getColumn(int i, Vec v) const 00214 { v << memory_data.column(i); } 00215 00216 void MemoryVMatrix::getSubRow(int i, int j, Vec v) const 00217 { 00218 #ifdef BOUNDCHECK 00219 if (j+v.length()>width()) 00220 PLERROR("MemoryVMatrix::getSubRow(int i, int j, Vec v) OUT OF BOUNDS. " 00221 "j=%d, v.length()=%d, width()=%d", j, v.length(), width()); 00222 #endif 00223 if (v.length() > 0) 00224 v.copyFrom(memory_data[i]+j, v.length()); 00225 } 00226 00228 // getRow // 00230 void MemoryVMatrix::getRow(int i, Vec v) const 00231 { 00232 PLASSERT( v.length() == width_ ); 00233 if (width_ > 0) 00234 v.copyFrom(memory_data[i], width_); 00235 } 00236 00238 // getMat // 00240 void MemoryVMatrix::getMat(int i, int j, Mat m) const 00241 { m << memory_data.subMat(i,j,m.length(),m.width()); } 00242 00244 // putSubRow // 00246 void MemoryVMatrix::putSubRow(int i, int j, Vec v) 00247 { 00248 #ifdef BOUNDCHECK 00249 if (j+v.length()>width()) 00250 PLERROR("MemoryVMatrix::putSubRow(int i, int j, Vec v) OUT OF BOUNDS. " 00251 "j=%d, v.length()=%d, width()=%d", j, v.length(), width()); 00252 #endif 00253 if (v.length() > 0) 00254 v.copyTo(memory_data[i]+j); 00255 00256 // Every method that writes data has the following two lines, because: 00257 // (1) The correct implementation when using a source VMat should be to 00258 // write in this source VMat as well, but it is not currently implemented, 00259 // so we just throw an error if we try to do this. 00260 // (2) We need to ensure that 'data' points to 'memory_data', in case this 00261 // VMat was initially created without any 'data' build option. Otherwise 00262 // the data will not be saved. 00263 PLASSERT(!source); 00264 data = memory_data; 00265 } 00266 00268 // fill // 00270 void MemoryVMatrix::fill(real value) 00271 { 00272 memory_data.fill(value); 00273 PLASSERT(!source); 00274 data = memory_data; 00275 } 00276 00277 00279 // putRow // 00281 void MemoryVMatrix::putRow(int i, Vec v) 00282 { 00283 if (v.length() > 0) 00284 v.copyTo(memory_data[i]); 00285 PLASSERT(!source); 00286 data = memory_data; 00287 } 00288 00290 // putMat // 00292 void MemoryVMatrix::putMat(int i, int j, Mat m) 00293 { 00294 memory_data.subMat(i,j,m.length(),m.width()) << m; 00295 PLASSERT(!source); 00296 data = memory_data; 00297 } 00298 00300 // appendRow // 00302 void MemoryVMatrix::appendRow(Vec v) 00303 { 00304 memory_data.appendRow(v); 00305 length_++; 00306 PLASSERT(!source); 00307 data = memory_data; 00308 } 00309 00311 // toMat // 00313 Mat MemoryVMatrix::toMat() const 00314 { return memory_data; } 00315 00317 // subMat // 00319 VMat MemoryVMatrix::subMat(int i, int j, int l, int w) 00320 { 00321 MemoryVMatrix* result = new MemoryVMatrix(memory_data.subMat(i,j,l,w)); 00322 result->deep_copy_memory_data=deep_copy_memory_data; 00323 result->setMetaInfoFrom(this); 00324 return (VMat)result; 00325 } 00326 00328 // dot // 00330 real MemoryVMatrix::dot(int i1, int i2, int inputsize) const 00331 { 00332 #ifdef BOUNDCHECK 00333 if(inputsize>width()) 00334 PLERROR("In MemoryVMatrix::dot inputsize>width()"); 00335 #endif 00336 real* v1 = memory_data.rowdata(i1); 00337 real* v2 = memory_data.rowdata(i2); 00338 real res = 0.; 00339 for(int k=0; k<inputsize; k++) 00340 res += (*v1++) * (*v2++); 00341 return res; 00342 } 00343 00344 real MemoryVMatrix::dot(int i, const Vec& v) const 00345 { 00346 #ifdef BOUNDCHECK 00347 if(v.length()>width()) 00348 PLERROR("In MemoryVMatrix::dot length of vector v is greater than VMat's width"); 00349 #endif 00350 if (v.length() > 0) { 00351 real* v1 = memory_data.rowdata(i); 00352 real* v2 = v.data(); 00353 real res = 0.; 00354 for(int k=0; k<v.length(); k++) 00355 res += v1[k]*v2[k]; 00356 return res; 00357 } 00358 return 0.0; // in the case of a null vector 00359 } 00360 00361 } // end of namespace PLearn 00362 00363 00364 /* 00365 Local Variables: 00366 mode:c++ 00367 c-basic-offset:4 00368 c-file-style:"stroustrup" 00369 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00370 indent-tabs-mode:nil 00371 fill-column:79 00372 End: 00373 */ 00374 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :