PLearn 0.1
IndexedVMatrix.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 2003 Pascal Vincent, Olivier Delalleau
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //
00009 //  1. Redistributions of source code must retain the above copyright
00010 //     notice, this list of conditions and the following disclaimer.
00011 //
00012 //  2. Redistributions in binary form must reproduce the above copyright
00013 //     notice, this list of conditions and the following disclaimer in the
00014 //     documentation and/or other materials provided with the distribution.
00015 //
00016 //  3. The name of the authors may not be used to endorse or promote
00017 //     products derived from this software without specific prior written
00018 //     permission.
00019 //
00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //
00031 // This file is part of the PLearn library. For more information on the PLearn
00032 // library, go to the PLearn Web site at www.plearn.org
00033 
00034 
00035 /* *******************************************************
00036  * $Id: IndexedVMatrix.cc 5557 2006-05-10 20:36:58Z lamblin $
00037  ******************************************************* */
00038 
00039 #include "IndexedVMatrix.h"
00040 
00041 namespace PLearn {
00042 using namespace std;
00043 
00044 PLEARN_IMPLEMENT_OBJECT(IndexedVMatrix, "ONE LINE DESCR",
00045                         "VMat class that sees its source as a collection of\n"
00046                         "triplets (row, column, value). Thus it is a N x 3"
00047                         " matrix,\n"
00048                         "with N = the number of elements in source.\n");
00049 
00050 
00051 IndexedVMatrix::IndexedVMatrix(bool call_build_)
00052     : inherited(call_build_),
00053       need_fix_mappings(false)
00054 {
00055     if( call_build_ )
00056         build_();
00057 }
00058 
00059 IndexedVMatrix::IndexedVMatrix(VMat the_source, bool the_fully_check_mappings,
00060                                bool call_build_)
00061     : inherited(the_source, call_build_),
00062       need_fix_mappings(false),
00063       fully_check_mappings(the_fully_check_mappings)
00064 {
00065     if( call_build_ )
00066         build_();
00067 }
00068 
00069 
00070 void IndexedVMatrix::declareOptions(OptionList& ol)
00071 {
00072     declareOption(ol, "m", &IndexedVMatrix::source,
00073                   (OptionBase::learntoption | OptionBase::nosave),
00074                   "DEPRECATED - use 'source' instead.");
00075 
00076     declareOption(ol, "fully_check_mappings",
00077                   &IndexedVMatrix::fully_check_mappings,
00078                   OptionBase::buildoption,
00079                   "If set to 1, then columns for which there is a"
00080                   " string <-> real mapping\n"
00081                   "will be examined, to ensure that no numerical data in a\n"
00082                   "column conflicts with a mapping in another column.\n");
00083 
00084     inherited::declareOptions(ol);
00085 }
00086 
00087 void IndexedVMatrix::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00088 {
00089     inherited::makeDeepCopyFromShallowCopy(copies);
00090 
00091     deepCopyField(fixed_mappings, copies);
00092 }
00093 
00094 void IndexedVMatrix::build()
00095 {
00096     inherited::build();
00097     build_();
00098 }
00099 
00101 // build_ //
00103 void IndexedVMatrix::build_()
00104 {
00105     width_ = 3;
00106     length_ = source->length() * source->width();
00107 
00108     ensureMappingsConsistency();
00109 
00110     if( fully_check_mappings )
00111         fullyCheckMappings();
00112 
00113     if( need_fix_mappings && !fully_check_mappings )
00114         PLWARNING( "In IndexedVMatrix::build_ - Mappings need to be fixed,\n"
00115                    "but you did not set 'fully_check_mappings' to true,\n"
00116                    "this might be dangerous.\n" );
00117 
00118     TVec<string> fieldnames(3);
00119     fieldnames[0] = "row";
00120     fieldnames[1] = "column";
00121     fieldnames[2] = "value";
00122     declareFieldNames( fieldnames );
00123 
00124     setMetaInfoFromSource();
00125 }
00126 
00128 // getNewRow //
00130 void IndexedVMatrix::getNewRow(int i, const Vec& v) const
00131 {
00132 #ifdef BOUNDCHECK
00133     if(i<0 || i>=length())
00134         PLERROR("In IndexedVMatrix::getNewRow OUT OF BOUNDS");
00135     if(v.length() != width())
00136         PLERROR("In IndexedVMatrix::getNewRow v.length() must be equal to 3");
00137 #endif
00138 
00139     int w = source->width();
00140     int i_ = i / w; // the value of the first column at row i
00141     int j_ = i % w; // the value of the second column at row i
00142     real val = source->get(i_,j_);
00143 
00144     if( need_fix_mappings && fixed_mappings[j_].size()>0 && !is_missing(val) )
00145     {
00146         map<real, real>::iterator it = fixed_mappings[j_].find(val);
00147         if( it != fixed_mappings[j_].end() )
00148         {
00149             // We need to modify this value.
00150             val = it->second;
00151         }
00152     }
00153 
00154     v[0] = i_;
00155     v[1] = j_;
00156     v[2] = val;
00157 }
00158 
00159 /* implemented in RowBufferedVMatrix
00161 // get //
00163 real IndexedVMatrix::get(int i, int j) const {
00164     int w = source->width();
00165     int i_ = i / w; // the value of the first column at row i
00166     int j_ = i % w; // the value of the second column at row i
00167     switch (j) {
00168     case 0:
00169         return i_;
00170     case 1:
00171         return j_;
00172     case 2:
00173         return source->get(i_, j_);
00174     default:
00175         PLERROR("In IndexedVMatrix::get IndexedVMatrix has only 3 columns\n");
00176         return 0;
00177     }
00178 }
00179 */
00180 
00182 // put //
00184 void IndexedVMatrix::put(int i, int j, real value) {
00185     if (j != 2) {
00186         PLERROR("In IndexedVMatrix::put You can only modify the third column\n");
00187     }
00188     int w = source->width();
00189     int i_ = i / w; // the value of the first column at row i
00190     int j_ = i % w; // the value of the second column at row i
00191     source->put(i_, j_, value);
00192 }
00193 
00195 // ensureMappingsConsistency //
00197 void IndexedVMatrix::ensureMappingsConsistency()
00198 {
00199     // Make sure the string mappings are consistent.
00200     // For this, we start from the mapping of the first column, and add
00201     // missing mappings obtained from the other columns. If another
00202     // column has a different mapping for the same string, we remember
00203     // it in order to fix the output when a getxxxx() method is called.
00204     need_fix_mappings = false;
00205     setStringMapping(2, source->getStringToRealMapping(0));
00206     map<string, real>* first_map = &map_sr[2];
00207     map<string, real> other_map;
00208     map<string, real>::iterator it, find_map;
00209 
00210     // Find the maximum mapping value for first column.
00211     real max = -REAL_MAX;
00212     for( it = first_map->begin() ; it != first_map->end() ; it++ )
00213         if( it->second > max )
00214             max = it->second;
00215 
00216     for( int i = 1 ; i < source->width() ; i++ )
00217     {
00218         other_map = source->getStringToRealMapping(i);
00219         for( it = other_map.begin() ; it != other_map.end() ; it++ )
00220         {
00221             find_map = first_map->find( it->first );
00222             if( find_map != first_map->end() )
00223             {
00224                 // The string mapped in column 'i' is also mapped in our first
00225                 // mapping.
00226                 if( !fast_exact_is_equal(find_map->second, it->second) )
00227                 {
00228                     // But the same string is not mapped to the same value.
00229                     // This needs to be fixed.
00230                     need_fix_mappings = true;
00231                     fixed_mappings.resize( source->width() );
00232                     fixed_mappings[i][it->second] = find_map->second;
00233                 }
00234             }
00235             else
00236             {
00237                 // The string mapped in VMat 'i' is not mapped in our
00238                 // current mapping. We need to add this mapping.
00239                 // But we must make sure there is no existing mapping to
00240                 // the same real number.
00241                 real new_map_val = it->second;
00242                 if( getValString(2, it->second) != "" )
00243                 {
00244                     // There is already a mapping to this real number.
00245                     need_fix_mappings = true;
00246                     fixed_mappings.resize( source->width() );
00247                     // We pick for the number the maximum of the current mapped
00248                     // numbers, +1.
00249                     max++;
00250                     fixed_mappings[i][it->second] = max;
00251                     new_map_val = max;
00252                 }
00253                 else
00254                 {
00255                     // There is no mapping to this real number, it is thus ok
00256                     // to add it.
00257                     if( new_map_val > max )
00258                         max = new_map_val;
00259                 }
00260                 addStringMapping(2, it->first, new_map_val);
00261             }
00262         }
00263     }
00264 }
00265 
00267 // fullyCheckMappings //
00269 void IndexedVMatrix::fullyCheckMappings()
00270 {
00271     if( map_sr[2].size() == 0 )
00272         return;
00273 
00274     Vec row( source->width() );
00275     for( int i = 0 ; i < source->length() ; i++ )
00276     {
00277         source->getRow(i, row);
00278         for( int j = 0 ; j < source->width() ; j++ )
00279         {
00280             if( !is_missing(row[j]) )
00281             {
00282                 // Note that if the value is missing, we should not
00283                 // look for a mapping from this value, because it would
00284                 // find it even if it does not exist (see the STL map
00285                 // documentation to understand why this happens).
00286                 if( source->getValString(j, row[j]) == "" )
00287                 {
00288                     // It is a numerical value for the source's j-th column
00289                     if( map_rs[2].find(row[j]) != map_rs[2].end() )
00290                     {
00291                         // And, unfortunately, we have used this
00292                         // numerical value in the column (2) string
00293                         // mapping. It could be fixed, but this would be
00294                         // pretty annoying, thus we just raise an error.
00295                         PLERROR("In IndexedVMatrix::fullyCheckMappings - In"
00296                                 " column %d (%s) of source, the row %d\n"
00297                                 "contains a numerical value (%f) that is used"
00298                                 " in a string mapping (mapped to %s).\n",
00299                                 j, source->fieldName(j).c_str(), i,
00300                                 row[j], map_rs[2][ row[j] ].c_str() );
00301                     }
00302                 }
00303             }
00304         }
00305     }
00306 }
00307 
00308 
00309 } // end of namespace PLearn
00310 
00311 
00312 /*
00313   Local Variables:
00314   mode:c++
00315   c-basic-offset:4
00316   c-file-style:"stroustrup"
00317   c-file-offsets:((innamespace . 0)(inline-open . 0))
00318   indent-tabs-mode:nil
00319   fill-column:79
00320   End:
00321 */
00322 // 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