SHOGUN
v3.2.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/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 }