SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ParameterMap.cpp
Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2011 Heiko Strathmann
00008  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
00009  */
00010 
00011 #include <shogun/base/ParameterMap.h>
00012 #include <shogun/base/Parameter.h>
00013 #include <shogun/lib/memory.h>
00014 #include <shogun/mathematics/Math.h>
00015 #include <shogun/lib/DataType.h>
00016 
00017 using namespace shogun;
00018 
00019 SGParamInfo::SGParamInfo()
00020 {
00021     m_name=NULL;
00022     m_ctype=CT_UNDEFINED;
00023     m_stype=ST_UNDEFINED;
00024     m_ptype=PT_UNDEFINED;
00025     m_param_version=-1;
00026 }
00027 
00028 SGParamInfo::SGParamInfo(const SGParamInfo& orig)
00029 {
00030     /* copy name if existent */
00031     m_name=get_strdup(orig.m_name);
00032 
00033     m_ctype=orig.m_ctype;
00034     m_stype=orig.m_stype;
00035     m_ptype=orig.m_ptype;
00036     m_param_version=orig.m_param_version;
00037 }
00038 
00039 SGParamInfo::SGParamInfo(const char* name, EContainerType ctype,
00040         EStructType stype, EPrimitiveType ptype, int32_t param_version)
00041 {
00042     /* copy name if existent */
00043     m_name=get_strdup(name);
00044 
00045     m_ctype=ctype;
00046     m_stype=stype;
00047     m_ptype=ptype;
00048     m_param_version=param_version;
00049 }
00050 
00051 SGParamInfo::SGParamInfo(const TParameter* param, int32_t param_version)
00052 {
00053     /* copy name if existent */
00054     m_name=get_strdup(param->m_name);
00055 
00056     TSGDataType type=param->m_datatype;
00057     m_ctype=type.m_ctype;
00058     m_stype=type.m_stype;
00059     m_ptype=type.m_ptype;
00060     m_param_version=param_version;
00061 }
00062 
00063 SGParamInfo::~SGParamInfo()
00064 {
00065     SG_FREE(m_name);
00066 }
00067 
00068 char* SGParamInfo::to_string() const
00069 {
00070     char* buffer=SG_MALLOC(char, 200);
00071     strcpy(buffer, "SGParamInfo with: ");
00072     strcat(buffer, "name=\"");
00073     strcat(buffer, m_name ? m_name : "NULL");
00074     strcat(buffer, "\", type=");
00075 
00076     char* b;
00077     /* only cat type if it is defined (is not when std constructor was used)*/
00078     if (!is_empty())
00079     {
00080         TSGDataType t(m_ctype, m_stype, m_ptype);
00081         index_t l=100;
00082         b=SG_MALLOC(char, l);
00083         t.to_string(b, l);
00084         strcat(buffer, b);
00085         SG_FREE(b);
00086     }
00087     else
00088         strcat(buffer, "no type");
00089 
00090     b=SG_MALLOC(char, 10);
00091     sprintf(b, "%d", m_param_version);
00092     strcat(buffer, ", version=");
00093     strcat(buffer, b);
00094     SG_FREE(b);
00095 
00096     return buffer;
00097 }
00098 
00099 void SGParamInfo::print_param_info(const char* prefix) const
00100 {
00101     char* s=to_string();
00102     SG_SPRINT("%s%s\n", prefix, s)
00103     SG_FREE(s);
00104 }
00105 
00106 SGParamInfo* SGParamInfo::duplicate() const
00107 {
00108     return new SGParamInfo(m_name, m_ctype, m_stype, m_ptype, m_param_version);
00109 }
00110 
00111 bool SGParamInfo::operator==(const SGParamInfo& other) const
00112 {
00113     bool result=true;
00114 
00115     /* handle NULL strings */
00116     if ((!m_name && other.m_name) || (m_name && !other.m_name))
00117         return false;
00118 
00119     if (m_name && other.m_name)
00120         result&=!strcmp(m_name, other.m_name);
00121 
00122     result&=m_ctype==other.m_ctype;
00123     result&=m_stype==other.m_stype;
00124     result&=m_ptype==other.m_ptype;
00125     result&=m_param_version==other.m_param_version;
00126     return result;
00127 }
00128 
00129 bool SGParamInfo::operator!=(const SGParamInfo& other) const
00130 {
00131     return !operator ==(other);
00132 }
00133 
00134 bool SGParamInfo::operator<(const SGParamInfo& other) const
00135 {
00136     /* NULL here is always smaller than anything */
00137     if (!m_name)
00138     {
00139         if (!other.m_name)
00140             return false;
00141         else
00142             return true;
00143     }
00144     else if (!other.m_name)
00145         return true;
00146 
00147     int32_t result=strcmp(m_name, other.m_name);
00148 
00149     if (result==0)
00150     {
00151         if (m_param_version==other.m_param_version)
00152         {
00153             if (m_ctype==other.m_ctype)
00154             {
00155                 if (m_stype==other.m_stype)
00156                 {
00157                     if (m_ptype==other.m_ptype)
00158                     {
00159                         return false;
00160                     }
00161                     else
00162                         return m_ptype<other.m_ptype;
00163                 }
00164                 else
00165                     return m_stype<other.m_stype;
00166             }
00167             else
00168                 return m_ctype<other.m_ctype;
00169         }
00170         else
00171             return m_param_version<other.m_param_version;
00172 
00173     }
00174     else
00175         return result<0;
00176 }
00177 
00178 bool SGParamInfo::operator>(const SGParamInfo& other) const
00179 {
00180     return !(*this<(other)) && !(*this==other);
00181 }
00182 
00183 bool SGParamInfo::is_empty() const
00184 {
00185     /* return true if this info is for empty parameter */
00186     return m_ctype==CT_UNDEFINED && m_stype==ST_UNDEFINED && m_ptype==PT_UNDEFINED && !m_name;
00187 }
00188 
00189 ParameterMapElement::ParameterMapElement()
00190 {
00191     m_key=NULL;
00192     m_values=NULL;
00193 }
00194 
00195 ParameterMapElement::ParameterMapElement(const SGParamInfo* key,
00196         DynArray<const SGParamInfo*>* values)
00197 {
00198     m_key=key;
00199     m_values=values;
00200 }
00201 
00202 ParameterMapElement::~ParameterMapElement()
00203 {
00204     delete m_key;
00205 
00206     if (m_values)
00207     {
00208         for (index_t i=0; i<m_values->get_num_elements(); ++i)
00209             delete m_values->get_element(i);
00210 
00211         delete m_values;
00212     }
00213 }
00214 
00215 bool ParameterMapElement::operator==(const ParameterMapElement& other) const
00216 {
00217     return *m_key==*other.m_key;
00218 }
00219 
00220 bool ParameterMapElement::operator<(const ParameterMapElement& other) const
00221 {
00222     return *m_key<*other.m_key;
00223 }
00224 
00225 bool ParameterMapElement::operator>(const ParameterMapElement& other) const
00226 {
00227     return *m_key>*other.m_key;
00228 }
00229 
00230 /*
00231   Initializing m_map_elements(1), m_multi_map_elements(1) with small
00232   preallocation-size, because ParameterMap will be constructed several
00233   times for EACH SGObject instance.
00234 */
00235 ParameterMap::ParameterMap()
00236 : m_map_elements(1), m_multi_map_elements(1)
00237 {
00238     m_finalized=false;
00239 }
00240 
00241 ParameterMap::~ParameterMap()
00242 {
00243     for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
00244         delete m_map_elements[i];
00245 
00246     for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
00247         delete m_multi_map_elements[i];
00248 }
00249 
00250 void ParameterMap::put(const SGParamInfo* key, const SGParamInfo* value)
00251 {
00252     /* assert that versions do differ exactly one if mapping is non-empty */
00253     if (key->m_param_version-value->m_param_version!=1)
00254     {
00255         if (!key->is_empty() && !value->is_empty())
00256         {
00257             char* s=key->to_string();
00258             char* t=value->to_string();
00259             SG_SERROR("Versions of parameter mappings from \"%s\" to \"%s\" have"
00260                     " to differ exactly one\n", s, t);
00261             SG_FREE(s);
00262             SG_FREE(t);
00263         }
00264     }
00265 
00266     /* always add array of ONE element as values, will be processed later
00267      * in finalize map method */
00268     DynArray<const SGParamInfo*>* values=new DynArray<const SGParamInfo*>();
00269     values->append_element(value);
00270     m_map_elements.append_element(new ParameterMapElement(key, values));
00271     m_finalized=false;
00272 }
00273 
00274 DynArray<const SGParamInfo*>* ParameterMap::get(const SGParamInfo key) const
00275 {
00276     return get(&key);
00277 }
00278 
00279 DynArray<const SGParamInfo*>* ParameterMap::get(const SGParamInfo* key) const
00280 {
00281     index_t num_elements=m_multi_map_elements.get_num_elements();
00282 
00283     /* check if maps is finalized */
00284     if (!m_finalized && num_elements)
00285         SG_SERROR("Call finalize_map() before calling get()\n")
00286 
00287     /* do binary search in array of pointers */
00288     /* dummy element for searching */
00289     ParameterMapElement* dummy=new ParameterMapElement(key->duplicate(), NULL);
00290     index_t index=CMath::binary_search<ParameterMapElement> (
00291             m_multi_map_elements.get_array(), num_elements, dummy);
00292     delete dummy;
00293 
00294     if (index==-1)
00295         return NULL;
00296 
00297     ParameterMapElement* element=m_multi_map_elements.get_element(index);
00298     return element->m_values;
00299 }
00300 
00301 void ParameterMap::finalize_map()
00302 {
00303     /* only do something if there are elements in map */
00304     if (!m_map_elements.get_num_elements())
00305         return;
00306 
00307     /* sort underlying array */
00308     CMath::qsort<ParameterMapElement> (m_map_elements.get_array(),
00309             m_map_elements.get_num_elements());
00310 
00311 //  SG_SPRINT("map elements before finalize\n")
00312 //  for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
00313 //  {
00314 //      ParameterMapElement* current=m_map_elements[i];
00315 //      SG_SPRINT("element %d:\n", i)
00316 //      SG_SPRINT("\tkey: ")
00317 //      current->m_key->print_param_info();
00318 //      SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements())
00319 //      for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
00320 //          current->m_values->get_element(j)->print_param_info("\t\t");
00321 //  }
00322 
00323     /* clear old multi elements. These were copies. */
00324     for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
00325         delete m_multi_map_elements[i];
00326 
00327     m_multi_map_elements.reset(NULL);
00328 //  SG_SPRINT("\nstarting finalization\n")
00329 
00330     /* iterate over all elements of map elements (have all one value (put)) and
00331      * add all values of same key to ONE map element of hidden structure */
00332     DynArray<const SGParamInfo*>* values=new DynArray<const SGParamInfo*>();
00333     const SGParamInfo* current_key=m_map_elements[0]->m_key;
00334 //  char* s=current_key->to_string();
00335 //  SG_SPRINT("current key: %s\n", s)
00336 //  SG_FREE(s);
00337     for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
00338     {
00339         const ParameterMapElement* current=m_map_elements[i];
00340         if (*current_key != *current->m_key)
00341         {
00342             /* create new values array to add and update key */
00343             values=new DynArray<const SGParamInfo*>();
00344             current_key=current->m_key;
00345 //          s=current_key->to_string();
00346 //          SG_SPRINT("new current key: %s\n", s)
00347 //          SG_FREE(s);
00348         }
00349 
00350         /* add to values array */
00351         char* t=current->m_values->get_element(0)->to_string();
00352 //      SG_SPRINT("\tadding %s\n", t)
00353         SG_FREE(t);
00354         values->append_element(current->m_values->get_element(0)->duplicate());
00355 
00356         /* if current values array has not been added to multi map elements, do
00357          * now */
00358         index_t last_idx=m_multi_map_elements.get_num_elements()-1;
00359         if (last_idx<0 ||
00360                 m_multi_map_elements.get_element(last_idx)->m_values != values)
00361         {
00362 //          SG_SPRINT("adding values array\n")
00363             m_multi_map_elements.append_element(
00364                 new ParameterMapElement(current_key->duplicate(), values));
00365         }
00366     }
00367 
00368     m_finalized=true;
00369 //  SG_SPRINT("leaving finalize_map()\n")
00370 }
00371 
00372 void ParameterMap::print_map()
00373 {
00374     /* check if maps is finalized */
00375     if (!m_finalized && m_map_elements.get_num_elements())
00376         SG_SERROR("Call finalize_map() before calling print_map()\n")
00377 
00378 //  SG_SPRINT("map with %d keys:\n", m_multi_map_elements.get_num_elements())
00379     for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
00380     {
00381         ParameterMapElement* current=m_multi_map_elements[i];
00382 //      SG_SPRINT("element %d:\n", i)
00383 //      SG_SPRINT("\tkey: ")
00384 //      current->m_key->print_param_info();
00385 //      SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements())
00386         for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
00387             current->m_values->get_element(j)->print_param_info("\t\t");
00388     }
00389 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation