PLearn 0.1
SparseVMatrix.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: SparseVMatrix.cc 8617 2008-03-03 17:45:54Z nouiz $
00039  ******************************************************* */
00040 
00041 #include "SparseVMatrix.h"
00042 
00043 namespace PLearn {
00044 using namespace std;
00045 
00046 
00049 PLEARN_IMPLEMENT_OBJECT(SparseVMatrix, "ONE LINE DESC", "NO HELP");
00050 
00051 SparseVMatrix::SparseVMatrix(const string& filename)
00052     : nelements(0), positions(0), values(0), rows(0)
00053 {
00054     load(filename);
00055     updateMtime(filename);
00056 }
00057 
00058 SparseVMatrix::SparseVMatrix(VMat m)
00059     : inherited(m.length(),m.width()), nelements(0), positions(0), values(0), rows(0)
00060 {
00061     fieldinfos = m->getFieldInfos();                // Copy the field infos
00062 
00063     updateMtime(m);
00064 
00065     if(m.width()>USHRT_MAX)
00066         PLERROR("In SparseVMatrix constructor: m.width()=%d can't be greater than USHRT_MAX=%d",m.width(),USHRT_MAX);
00067     Vec v(m.width());
00068     real* vptr = v.data();
00069 
00070     // First count nelements
00071     nelements = 0;
00072     if(m->hasStats()) // use the stats!
00073     {
00074         for(int j=0; j<m.width(); j++)
00075         {
00076             const VMFieldStat& st = m->fieldStat(j);
00077             nelements += st.nmissing() + st.npositive() + st.nnegative();
00078         }
00079     }
00080     else // let's count them ourself
00081     {
00082         for(int i=0; i<m.length(); i++)
00083         {
00084             m->getRow(i,v);
00085             for(int j=0; j<v.length(); j++)
00086                 if(!fast_exact_is_equal(vptr[j], 0.))
00087                     nelements++;
00088         }
00089     }
00090 
00091     // Now allocate space for those elements
00092     if(nelements>0)
00093     {
00094         positions = new unsigned short[nelements];
00095         values = new float[nelements];
00096         int l=length();
00097         rows = new SparseVMatrixRow[l];
00098 
00099         int pos = 0;
00100         // Fill the representation
00101         for(int i=0; i<m.length(); i++)
00102         {
00103             m->getRow(i,v);
00104             SparseVMatrixRow& r = rows[i];
00105             r.row_startpos = pos;
00106             int nelem = 0;
00107             for(int j=0; j<v.length(); j++)
00108                 if(!fast_exact_is_equal(vptr[j], 0.))
00109                 {
00110                     positions[pos] = j;
00111                     values[pos] = (float)vptr[j];
00112                     pos++;
00113                     nelem++;
00114                 }
00115             r.nelements = nelem;
00116         }
00117     }
00118 }
00119 
00120 void
00121 SparseVMatrix::build()
00122 {
00123     inherited::build();
00124     build_();
00125 }
00126 
00127 void
00128 SparseVMatrix::build_()
00129 {
00130     // TODO
00131 }
00132 
00133 void
00134 SparseVMatrix::declareOptions(OptionList &ol)
00135 {
00136     inherited::declareOptions(ol);
00137 }
00138 
00139 void SparseVMatrix::getNewRow(int i, const Vec& v) const
00140 {
00141 #ifdef BOUNDCHECK
00142     if(i<0 || i>=length())
00143         PLERROR("In SparseVMatrix::getNewRow, row number i=%d OUT OF BOUNDS (matrix is %dx%d)",i,length(),width());
00144     if(v.length()!=width())
00145         PLERROR("In SparseVMatrix::getNewRow, length of v (%d) is different from width of VMatris (%d)",v.length(),width());
00146 #endif
00147 
00148     if(nelements==0)
00149         v.clear();
00150     else
00151     {
00152         SparseVMatrixRow row_i = rows[i];
00153         float* valueptr =  values + row_i.row_startpos;
00154         unsigned short* positionptr = positions + row_i.row_startpos;
00155         int n = row_i.nelements;
00156 
00157         real* vdata = v.data();
00158 
00159         int j = 0;
00160         while(n--)
00161         {
00162             int nextpos = (int) *positionptr++;
00163             real nextval = (real) *valueptr++;
00164             while(j<nextpos)
00165                 vdata[j++] = 0.;
00166             vdata[j++] = nextval;
00167         }
00168         while(j<v.length())
00169             vdata[j++] = 0.;
00170     }
00171 }
00172 
00173 real SparseVMatrix::dot(int i1, int i2, int inputsize) const
00174 {
00175 #ifdef BOUNDCHECK
00176     if(i1<0 || i1>=length() || i2<0 || i2>=length() || inputsize>width())
00177         PLERROR("IN SparseVMatrix::dot OUT OF BOUNDS");
00178 #endif
00179 
00180     if(nelements==0)
00181         return 0.;
00182 
00183     SparseVMatrixRow row_1 = rows[i1];
00184     float* valueptr_1 =  values + row_1.row_startpos;
00185     unsigned short* positionptr_1 = positions + row_1.row_startpos;
00186     int n_1 = row_1.nelements;
00187 
00188     SparseVMatrixRow row_2 = rows[i2];
00189     float* valueptr_2 =  values + row_2.row_startpos;
00190     unsigned short* positionptr_2 = positions + row_2.row_startpos;
00191     int n_2 = row_2.nelements;
00192 
00193     real res = 0.;
00194 
00195     while(n_1 && n_2)
00196     {
00197         if(*positionptr_1>=inputsize)
00198             break;
00199         if(*positionptr_1==*positionptr_2)
00200         {
00201             res += (*valueptr_1)*(*valueptr_2);
00202             positionptr_1++;
00203             valueptr_1++;
00204             n_1--;
00205             positionptr_2++;
00206             valueptr_2++;
00207             n_2--;
00208         }
00209         else if(*positionptr_1<*positionptr_2)
00210         {
00211             positionptr_1++;
00212             valueptr_1++;
00213             n_1--;
00214         }
00215         else
00216         {
00217             positionptr_2++;
00218             valueptr_2++;
00219             n_2--;
00220         }
00221     }
00222 
00223     return res;
00224 }
00225 
00226 real SparseVMatrix::dot(int i, const Vec& v) const
00227 {
00228 #ifdef BOUNDCHECK
00229     if(i<0 || i>=length() || v.length()>width())
00230         PLERROR("IN SparseVMatrix::dot OUT OF BOUNDS");
00231 #endif
00232 
00233     if(nelements==0)
00234         return 0.;
00235 
00236     SparseVMatrixRow row_i = rows[i];
00237     float* valueptr =  values + row_i.row_startpos;
00238     unsigned short* positionptr = positions + row_i.row_startpos;
00239     int n = row_i.nelements;
00240 
00241     real* vdata = v.data();
00242     real res = 0.;
00243 
00244     while(n--)
00245     {
00246         int nextpos = (int) *positionptr++;
00247         real nextval = (real) *valueptr++;
00248         if(nextpos>=v.length())
00249             break;
00250         res += nextval*vdata[nextpos];
00251     }
00252     return res;
00253 }
00254 /*
00255   void SparseVMatrix::write(ostream& out) const
00256   {
00257   writeHeader(out,"SparseVMatrix");
00258   writeField(out,"length",length_);
00259   writeField(out,"width",width_);
00260   writeField(out,"fieldinfos",fieldinfos);
00261   writeField(out,"fieldstats",fieldstats);
00262   writeField(out,"nelements",nelements);
00263   write_ushort(out,positions,nelements,false);
00264   write_float(out,values,nelements,false);
00265   for(int i=0; i<length(); i++)
00266   {
00267   write_int(out,rows[i].nelements);
00268   write_int(out,rows[i].row_startpos);
00269   }
00270   writeFooter(out,"SparseVMatrix");
00271   }
00272 
00273   void SparseVMatrix::oldread(istream& in)
00274   {
00275   readHeader(in,"SparseVMatrix");
00276   readField(in,"length",length_);
00277   readField(in,"width",width_);
00278   readField(in,"fieldinfos",fieldinfos);
00279   fieldinfos.resize(0); // to fix current bug in setting fieldinfos
00280   readField(in,"fieldstats",fieldstats);
00281 
00282   if(nelements>0)
00283   {
00284   delete[] positions;
00285   delete[] values;
00286   delete[] rows;
00287   }
00288   readField(in,"nelements",nelements);
00289   positions = new unsigned short[nelements];
00290   values = new float[nelements];
00291   rows = new SparseVMatrixRow[length()];
00292 
00293   read_ushort(in,positions,nelements,false);
00294   read_float(in,values,nelements,false);
00295   for(int i=0; i<length(); i++)
00296   {
00297   rows[i].nelements = read_int(in);
00298   rows[i].row_startpos = read_int(in);
00299   }
00300   readFooter(in,"SparseVMatrix");
00301   }
00302 */
00303 SparseVMatrix::~SparseVMatrix()
00304 {
00305     if(nelements>0)
00306     {
00307         delete[] positions;
00308         delete[] values;
00309         delete[] rows;
00310     }
00311 }
00312 
00313 
00314 } // end of namespace PLearn
00315 
00316 
00317 /*
00318   Local Variables:
00319   mode:c++
00320   c-basic-offset:4
00321   c-file-style:"stroustrup"
00322   c-file-offsets:((innamespace . 0)(inline-open . 0))
00323   indent-tabs-mode:nil
00324   fill-column:79
00325   End:
00326 */
00327 // 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