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