cvconvnetparser.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003 downloading, copying, installing or using the software you agree to this
00004 license. If you do not agree to this license, do not download, install, copy or
00005 use the software.
00006 
00007 Contributors License Agreement
00008 
00009 Copyright© 2007, Akhmed Umyarov. All rights reserved.
00010 
00011 Redistribution and use in source and binary forms, with or without modification,
00012 are permitted provided that the following conditions are met:
00013 - Redistributions of source code must retain the above copyright notice, this
00014 list of conditions and the following disclaimer.
00015 - Redistributions in binary form must reproduce the above copyright notice, this
00016 list of conditions and the following disclaimer in the documentation and/or
00017 other materials provided with the distribution.
00018 - The name of Contributor may not be used to endorse or promote products derived
00019 from this software without specific prior written permission.
00020 
00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00022 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024 DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00025 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00027 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00029 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00030 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 All information provided related to future Intel products and plans is
00032 preliminary and subject to change at any time, without notice.
00033 *****************************************************************************/
00034 
00051 #include <expat.h> // XML Parsing
00052 #include <cassert>
00053 #include <vector>
00054 #include <map>
00055 #include <string>
00056 #include <iostream>
00057 #include <iterator>
00058 #include <sstream>
00059 #include "cvgenericplane.h"
00060 #include "cvconvnetparser.h"
00061 #include "cvsourceplane.h"
00062 #include "cvconvolutionplane.h"
00063 #include "cvsubsamplingplane.h"
00064 #include "cvgenericplane.h"
00065 #include "cvrbfplane.h"
00066 #include "cvmaxplane.h"
00067 
00068 
00069 // Bit masks for tag processing
00070 const int INSIDE_TAG=1<<0;
00071 const int FOUND_VALUE=1<<1;
00072 
00073         
00074 using namespace std;
00075 
00076 // ***********************************************************************
00077 // ******************** Expat XML Parsing handlers ***********************
00078 // ***********************************************************************
00079 
00081 
00085 typedef struct
00086 {
00087         // Text parameters
00088         string &creator;        
00089         string &name;           
00090         string &info;           
00091 
00092         // Graph parameters
00093         vector<CvGenericPlane *> &plane; 
00094         map<string,int> &idmap; 
00095 
00096         // Current (recursive) parameters
00097         int depth;                      
00098         int isbias;                     
00099         int isinfo;                     
00100         int isconnection;               
00101         vector<double> cur_weight;      
00102         vector<CvGenericPlane *> cur_parents; 
00103         string cur_type;                
00104         
00105         // Parser 
00106         XML_Parser &parser;             
00107 } XMLparserData;
00108 
00110 static void XMLCALL icvXML_StopParser(XML_Parser &parser, string errstr)
00111 {
00112         cout << "XML Error: " << errstr << endl;
00113         XML_StopParser(parser,XML_FALSE); // Stop parser unresumably
00114 }
00115 
00117 #define CHK_POSSIBLE_FAIL(x,y) if ( x ) { \
00118         icvXML_StopParser(data.parser,(y));\
00119         return; }
00120 
00122 static void XMLCALL icvXML_StartElementHandler (void *userData, const XML_Char *name, const XML_Char **atts)
00123 {
00124         assert( userData != NULL && name != NULL );
00125 
00126         XMLparserData &data = *((XMLparserData *) userData);
00127         string namestr (name);
00128         
00129         if ((namestr == "net") && (data.depth == 0))
00130         // ****** Process <net> tag
00131         {
00132                 // Remove all existing planes
00133                 for (signed int i = data.plane.size()-1; i >= 0; i--)
00134                 {
00135                         assert ( data.plane[i] != NULL );
00136                         delete data.plane[i];
00137                 }
00138                 
00139                 // Clear all the structures;
00140                 data.plane.clear();
00141                 data.creator.clear();
00142                 data.name.clear();
00143                 data.idmap.clear();
00144                 data.isbias = 0;
00145                 data.isinfo = 0;
00146 
00147                 for (int i=0; (atts[i]!=NULL) && (atts[i+1]!=NULL); i+=2)
00148                 {
00149                         string attr = atts[i];
00150                         string val = atts[i+1];
00151 
00152                         if (attr=="creator")
00153                                 data.creator = val;
00154                         if (attr=="name")
00155                                 data.name = val;
00156                 }
00157         }
00158         else if ((namestr == "plane") && (data.depth == 1))
00159         // ****** Process <plane> tag   
00160         {
00161                 int curplaneid = data.plane.size(); // Planeid that is going to be assigned for this plane
00162                 string planeid,planetype; // Plane info as read from the files
00163                 int fmapszx = 0, fmapszy = 0, neuroszx = 0, neuroszy = 0;
00164 
00165                 // Initialize data structures
00166                 data.cur_parents.clear();
00167                 data.cur_weight.clear();        
00168                 data.isbias = 0;
00169                 data.isconnection = 0;
00170 
00171                 for (int i=0; (atts[i]!=NULL) && (atts[i+1]!=NULL); i+=2)
00172                 {
00173                         string attr = atts[i];
00174                         string val = atts[i+1];
00175                         if (attr=="id") planeid = val;
00176                         if (attr=="type") planetype = val;
00177                         if (attr=="featuremapsize")  
00178                         {
00179                                 istringstream iss ( val );
00180                                 char c;
00181                                 iss >> fmapszx >> c >> fmapszy;
00182                         }
00183                         if (attr=="neuronsize")  
00184                         {
00185                                 istringstream iss ( val );
00186                                 char c;
00187                                 iss >> neuroszx >> c >> neuroszy;
00188                         }
00189                 }
00190                 // Plane MUST have an id
00191                 CHK_POSSIBLE_FAIL( planeid.size()==0 , "plane has no id");
00192 
00193                 // For all planes except MAX check whether featuremap sizes and neuron sizes are consistent
00194                 if (planetype != "max")
00195                 {
00196                         CHK_POSSIBLE_FAIL( (fmapszx <= 0 || fmapszy <= 0 || fmapszx > CVCONVOLUTIONALNET_MAX_FMAPSZ || fmapszy > CVCONVOLUTIONALNET_MAX_FMAPSZ) ,"feature map size is inconsistent");
00197         
00198                         CHK_POSSIBLE_FAIL( (neuroszx < 0 || neuroszy < 0 || neuroszx > CVCONVOLUTIONALNET_MAX_FMAPSZ || neuroszy > CVCONVOLUTIONALNET_MAX_FMAPSZ), "neuron window size is inconsistent");
00199                 }
00200                                 
00201                 // Create required plane object with inited parameters 
00202                 if (planetype=="source")
00203                 {
00204                         data.plane.push_back( 
00205                                 new CvSourcePlane(planeid,cvSize(fmapszx,fmapszy)) 
00206                         );
00207                         data.idmap[planeid] = curplaneid;
00208                 } else if (planetype=="convolution")
00209                 {
00210                         data.plane.push_back(
00211                                 new CvConvolutionPlane(planeid,cvSize(fmapszx,fmapszy),cvSize(neuroszx,neuroszy))
00212                         );
00213                         data.idmap[planeid] = curplaneid;
00214                 } else if (planetype=="subsampling")
00215                 {
00216                         data.plane.push_back(
00217                                 new CvSubSamplingPlane(planeid,cvSize(fmapszx,fmapszy),cvSize(neuroszx,neuroszy))
00218                         );
00219                         data.idmap[planeid] = curplaneid;
00220                 } else if (planetype=="rbf")
00221                 {
00222                         data.plane.push_back(
00223                                 new CvRBFPlane(planeid,cvSize(fmapszx,fmapszy),cvSize(neuroszx,neuroszy))
00224                         );
00225                         data.idmap[planeid] = curplaneid;
00226                 } else if (planetype=="max")
00227                 {
00228                         data.plane.push_back(
00229                                 new CvMaxPlane(planeid)
00230                         );
00231                         data.idmap[planeid] = curplaneid;
00232                 } else
00233                 {
00234                         CHK_POSSIBLE_FAIL(1, "plane "+planeid+" has no type or unidentified type");                     
00235                 }
00236                 data.cur_type = planetype;
00237                 data.cur_weight.clear();
00238         } else if ((namestr == "connection") && (data.depth==2))
00239         // ****** Process <connection> tag      
00240         {
00241                 int curplaneid = data.plane.size()-1; // Planeid of the current plane
00242 
00243                 for (int i=0;  (atts[i]!=NULL) && (atts[i+1]!=NULL); i+=2)
00244                 {
00245                         string attr = atts[i];
00246                         string val = atts[i+1];
00247 
00248                         if (attr=="to")
00249                         {
00250                                 // Find the plane number by the plane id
00251                                 map<string,int>::iterator itr = data.idmap.find(val); 
00252                                 
00253                                 CHK_POSSIBLE_FAIL (itr == data.idmap.end(), "Connection to non-existing plane or graph is not topologically sorted! Attempt to connect to \""+val+"\"");
00254                                 
00255                                 data.cur_parents.push_back(data.plane[itr->second]);
00256                         }
00257                 }
00258                 data.isconnection |= INSIDE_TAG;
00259         }
00260         else if ((namestr == "bias") && (data.depth==2))
00261         {
00262                 data.isbias |= INSIDE_TAG; // Mark as inside <bias> tag
00263                 
00264                 CHK_POSSIBLE_FAIL(data.cur_type=="max","<bias> defined for max plane");
00265         }
00266         else if ((namestr == "info") && (data.depth == 1))
00267         {
00268                 data.isinfo |= INSIDE_TAG; // Mark as inside <info> tag
00269 
00270         } else
00271         {
00272                 // Undefined xml tag found
00273                 CHK_POSSIBLE_FAIL(1,"undefined or misplaced tag <"+namestr+"> found");
00274         }
00275         
00276         data.depth++;
00277 }
00278 
00280 static void XMLCALL icvXML_EndElementHandler(void *userData, const XML_Char *name)
00281 {
00282         assert( userData != NULL && name != NULL);
00283 
00284         XMLparserData &data = *((XMLparserData *) userData);
00285         data.depth--;   
00286 
00287         string namestr (name);
00288 
00289         if ((namestr == "plane") && (data.depth == 1))
00290         {
00291                 // Get current plane id
00292                 vector<CvGenericPlane *>::iterator i = data.plane.end()-1;
00293                 
00294                 // Check if we found <bias> for certain planes
00295                 CHK_POSSIBLE_FAIL( (!(data.isbias & FOUND_VALUE)) && (data.cur_type=="convolution" || data.cur_type=="subsampling"), "no bias found");
00296 
00297                 // Check if plane (except source) is connected to something
00298                 CHK_POSSIBLE_FAIL( (data.cur_parents.size()==0) && (data.cur_type!="source"), "plane is not connected to anything");
00299                 
00300                 // Connect to parent planes
00301                 CHK_POSSIBLE_FAIL( !(*i)->connto(data.cur_parents), "failed to accomplish connections");
00302 
00303                 // Assign weights that we have read so far
00304                 CHK_POSSIBLE_FAIL( !(*i)->setweight(data.cur_weight), "failed to assign weights");
00305                 
00306                 // Clear data structures
00307                 data.cur_parents.clear();
00308                 data.cur_weight.clear();        
00309                 data.isbias = 0;
00310                 data.isconnection = 0;
00311         } else if ((namestr == "connection") && (data.depth == 2))
00312         {
00313                 data.isconnection &= ~INSIDE_TAG;
00314         } else if ((namestr == "bias") && (data.depth == 2))
00315         {
00316                 data.isbias &= ~INSIDE_TAG;
00317         } else if ((namestr == "info") && (data.depth == 1))
00318         {
00319                 data.isinfo &= ~INSIDE_TAG;
00320         }
00321 }
00322 
00324 static void XMLCALL icvXML_CharacterDataHandler(void *userData, const XML_Char *s, int len)
00325 {
00326         assert( userData != NULL && s != NULL);
00327 
00328         XMLparserData &data = *((XMLparserData *) userData);
00329 
00330         string weights(s,len);
00331         istringstream iss(weights);
00332         
00333         double w;
00334         if (data.isbias & INSIDE_TAG) 
00335         // Process <bias> tag data
00336         {
00337                 if (iss >> w)
00338                 {
00339                         data.cur_weight.insert(data.cur_weight.begin(),w);
00340                         data.isbias |= FOUND_VALUE; // Mark as found
00341                 }
00342                 
00343         } else if (data.isinfo & INSIDE_TAG)
00344         // Process <info> tag data
00345         {
00346                 iss >> data.info;
00347                 data.isinfo |= FOUND_VALUE; // Mark as found
00348         } else if (data.isconnection & INSIDE_TAG)
00349         // Process <connection> tag data
00350         {
00351                 while (iss >> w)
00352                 {
00353                         CHK_POSSIBLE_FAIL(data.cur_type=="max","weights defined for MAX plane. Nonsense!");
00354                         data.cur_weight.push_back(w);
00355                 }
00356                 data.isconnection |= FOUND_VALUE;  // Mark as found
00357         };
00358         // Ignore other data in XML
00359 }
00360 
00362 int parse(string xml, string &creator,
00363                 string &name, 
00364                 string &info, 
00365                 vector<CvGenericPlane *> &plane,
00366                 map<string,int> &idmap)
00367 {
00368         XML_Parser parser = XML_ParserCreate(NULL);
00369 
00370         // Data that are to be passed to handler
00371         XMLparserData handlerdata = 
00372         {
00373                 creator, // string &creator;
00374                 name, // string &name;
00375                 info, // string &info;
00376 
00377                 plane, // vector<CvGenericPlane *> &plane;
00378                 idmap, // map<string,int> &idmap;
00379 
00380                 0, // int depth;
00381                 0, // int isbias;
00382                 0, // int isinfo;
00383                 0, // int isconnection;
00384                 
00385                 vector<double> (), //vector<double> cur_weight; 
00386                 vector<CvGenericPlane *> (), // vector<CvGenericPlane *> cur_parents; 
00387                 "", // string cur_type;
00388                 parser
00389         }; 
00390 
00391         // SAX initialization
00392         XML_SetUserData(parser,&handlerdata);
00393         XML_SetElementHandler(parser, icvXML_StartElementHandler,  icvXML_EndElementHandler);
00394         XML_SetCharacterDataHandler(parser, icvXML_CharacterDataHandler);
00395 
00396         int errcode = 1;
00397         
00398         // Main parsing
00399         if ( XML_Parse(parser, xml.c_str(), xml.size(), 1) == XML_STATUS_ERROR )
00400         {
00401                 cerr << "Error parsing the XML: " << XML_ErrorString( XML_GetErrorCode(parser) ) << " at line " << XML_GetCurrentLineNumber(parser) << endl;
00402                 errcode = 0;
00403         }
00404         XML_ParserFree(parser);
00405 
00406         return errcode;
00407 }

Generated on Fri Aug 3 16:17:27 2007 for ConvNet by  doxygen 1.5.0