PLearn 0.1
MemoryVMatrix.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines