SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParameterMap.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2011 Heiko Strathmann
8  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
9  */
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <shogun/lib/common.h>
15 #include <shogun/lib/memory.h>
16 
18 #include <shogun/base/Parameter.h>
20 #include <shogun/io/SGIO.h>
21 #include <shogun/base/DynArray.h>
22 #include <shogun/lib/DataType.h>
23 
24 using namespace shogun;
25 
27 {
28  m_name=NULL;
29  m_ctype=CT_UNDEFINED;
30  m_stype=ST_UNDEFINED;
31  m_ptype=PT_UNDEFINED;
32  m_param_version=-1;
33 }
34 
36 {
37  /* copy name if existent */
38  m_name=get_strdup(orig.m_name);
39 
40  m_ctype=orig.m_ctype;
41  m_stype=orig.m_stype;
42  m_ptype=orig.m_ptype;
44 }
45 
46 SGParamInfo::SGParamInfo(const char* name, EContainerType ctype,
47  EStructType stype, EPrimitiveType ptype, int32_t param_version)
48 {
49  /* copy name if existent */
50  m_name=get_strdup(name);
51 
52  m_ctype=ctype;
53  m_stype=stype;
54  m_ptype=ptype;
55  m_param_version=param_version;
56 }
57 
58 SGParamInfo::SGParamInfo(const TParameter* param, int32_t param_version)
59 {
60  /* copy name if existent */
61  m_name=get_strdup(param->m_name);
62 
63  TSGDataType type=param->m_datatype;
64  m_ctype=type.m_ctype;
65  m_stype=type.m_stype;
66  m_ptype=type.m_ptype;
67  m_param_version=param_version;
68 }
69 
71 {
72  SG_FREE(m_name);
73 }
74 
76 {
77  char* buffer=SG_MALLOC(char, 200);
78  strcpy(buffer, "SGParamInfo with: ");
79  strcat(buffer, "name=\"");
80  strcat(buffer, m_name ? m_name : "NULL");
81  strcat(buffer, "\", type=");
82 
83  char* b;
84  /* only cat type if it is defined (is not when std constructor was used)*/
85  if (!is_empty())
86  {
88  index_t l=100;
89  b=SG_MALLOC(char, l);
90  t.to_string(b, l);
91  strcat(buffer, b);
92  SG_FREE(b);
93  }
94  else
95  strcat(buffer, "no type");
96 
97  b=SG_MALLOC(char, 10);
98  sprintf(b, "%d", m_param_version);
99  strcat(buffer, ", version=");
100  strcat(buffer, b);
101  SG_FREE(b);
102 
103  return buffer;
104 }
105 
106 void SGParamInfo::print_param_info(const char* prefix) const
107 {
108  char* s=to_string();
109  SG_SPRINT("%s%s\n", prefix, s)
110  SG_FREE(s);
111 }
112 
114 {
116 }
117 
118 bool SGParamInfo::operator==(const SGParamInfo& other) const
119 {
120  bool result=true;
121 
122  /* handle NULL strings */
123  if ((!m_name && other.m_name) || (m_name && !other.m_name))
124  return false;
125 
126  if (m_name && other.m_name)
127  result&=!strcmp(m_name, other.m_name);
128 
129  result&=m_ctype==other.m_ctype;
130  result&=m_stype==other.m_stype;
131  result&=m_ptype==other.m_ptype;
132  result&=m_param_version==other.m_param_version;
133  return result;
134 }
135 
136 bool SGParamInfo::operator!=(const SGParamInfo& other) const
137 {
138  return !operator ==(other);
139 }
140 
141 bool SGParamInfo::operator<(const SGParamInfo& other) const
142 {
143  /* NULL here is always smaller than anything */
144  if (!m_name)
145  {
146  if (!other.m_name)
147  return false;
148  else
149  return true;
150  }
151  else if (!other.m_name)
152  return true;
153 
154  int32_t result=strcmp(m_name, other.m_name);
155 
156  if (result==0)
157  {
158  if (m_param_version==other.m_param_version)
159  {
160  if (m_ctype==other.m_ctype)
161  {
162  if (m_stype==other.m_stype)
163  {
164  if (m_ptype==other.m_ptype)
165  {
166  return false;
167  }
168  else
169  return m_ptype<other.m_ptype;
170  }
171  else
172  return m_stype<other.m_stype;
173  }
174  else
175  return m_ctype<other.m_ctype;
176  }
177  else
178  return m_param_version<other.m_param_version;
179 
180  }
181  else
182  return result<0;
183 }
184 
185 bool SGParamInfo::operator>(const SGParamInfo& other) const
186 {
187  return !(*this<(other)) && !(*this==other);
188 }
189 
191 {
192  /* return true if this info is for empty parameter */
193  return m_ctype==CT_UNDEFINED && m_stype==ST_UNDEFINED && m_ptype==PT_UNDEFINED && !m_name;
194 }
195 
197 {
198  m_key=NULL;
199  m_values=NULL;
200 }
201 
204 {
205  m_key=key;
206  m_values=values;
207 }
208 
210 {
211  delete m_key;
212 
213  if (m_values)
214  {
215  for (index_t i=0; i<m_values->get_num_elements(); ++i)
216  delete m_values->get_element(i);
217 
218  delete m_values;
219  }
220 }
221 
223 {
224  return *m_key==*other.m_key;
225 }
226 
228 {
229  return *m_key<*other.m_key;
230 }
231 
233 {
234  return *m_key>*other.m_key;
235 }
236 
237 /*
238  Initializing m_map_elements(1), m_multi_map_elements(1) with small
239  preallocation-size, because ParameterMap will be constructed several
240  times for EACH SGObject instance.
241 */
243 : m_map_elements(1), m_multi_map_elements(1)
244 {
245  m_finalized=false;
246 }
247 
249 {
250  for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
251  delete m_map_elements[i];
252 
253  for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
254  delete m_multi_map_elements[i];
255 }
256 
257 void ParameterMap::put(const SGParamInfo* key, const SGParamInfo* value)
258 {
259  /* assert that versions do differ exactly one if mapping is non-empty */
260  if (key->m_param_version-value->m_param_version!=1)
261  {
262  if (!key->is_empty() && !value->is_empty())
263  {
264  char* s=key->to_string();
265  char* t=value->to_string();
266  SG_SERROR("Versions of parameter mappings from \"%s\" to \"%s\" have"
267  " to differ exactly one\n", s, t);
268  SG_FREE(s);
269  SG_FREE(t);
270  }
271  }
272 
273  /* always add array of ONE element as values, will be processed later
274  * in finalize map method */
276  values->append_element(value);
278  m_finalized=false;
279 }
280 
282 {
283  return get(&key);
284 }
285 
287 {
289 
290  /* check if maps is finalized */
291  if (!m_finalized && num_elements)
292  SG_SERROR("Call finalize_map() before calling get()\n")
293 
294  /* do binary search in array of pointers */
295  /* dummy element for searching */
296  ParameterMapElement* dummy=new ParameterMapElement(key->duplicate(), NULL);
297  index_t index=CMath::binary_search<ParameterMapElement> (
298  m_multi_map_elements.get_array(), num_elements, dummy);
299  delete dummy;
300 
301  if (index==-1)
302  return NULL;
303 
305  return element->m_values;
306 }
307 
309 {
310  /* only do something if there are elements in map */
312  return;
313 
314  /* sort underlying array */
315  CMath::qsort<ParameterMapElement> (m_map_elements.get_array(),
317 
318 // SG_SPRINT("map elements before finalize\n")
319 // for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
320 // {
321 // ParameterMapElement* current=m_map_elements[i];
322 // SG_SPRINT("element %d:\n", i)
323 // SG_SPRINT("\tkey: ")
324 // current->m_key->print_param_info();
325 // SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements())
326 // for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
327 // current->m_values->get_element(j)->print_param_info("\t\t");
328 // }
329 
330  /* clear old multi elements. These were copies. */
331  for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
332  delete m_multi_map_elements[i];
333 
335 // SG_SPRINT("\nstarting finalization\n")
336 
337  /* iterate over all elements of map elements (have all one value (put)) and
338  * add all values of same key to ONE map element of hidden structure */
340  const SGParamInfo* current_key=m_map_elements[0]->m_key;
341 // char* s=current_key->to_string();
342 // SG_SPRINT("current key: %s\n", s)
343 // SG_FREE(s);
344  for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
345  {
346  const ParameterMapElement* current=m_map_elements[i];
347  if (*current_key != *current->m_key)
348  {
349  /* create new values array to add and update key */
350  values=new DynArray<const SGParamInfo*>();
351  current_key=current->m_key;
352 // s=current_key->to_string();
353 // SG_SPRINT("new current key: %s\n", s)
354 // SG_FREE(s);
355  }
356 
357  /* add to values array */
358  char* t=current->m_values->get_element(0)->to_string();
359 // SG_SPRINT("\tadding %s\n", t)
360  SG_FREE(t);
361  values->append_element(current->m_values->get_element(0)->duplicate());
362 
363  /* if current values array has not been added to multi map elements, do
364  * now */
366  if (last_idx<0 ||
367  m_multi_map_elements.get_element(last_idx)->m_values != values)
368  {
369 // SG_SPRINT("adding values array\n")
371  new ParameterMapElement(current_key->duplicate(), values));
372  }
373  }
374 
375  m_finalized=true;
376 // SG_SPRINT("leaving finalize_map()\n")
377 }
378 
380 {
381  /* check if maps is finalized */
383  SG_SERROR("Call finalize_map() before calling print_map()\n")
384 
385 // SG_SPRINT("map with %d keys:\n", m_multi_map_elements.get_num_elements())
386  for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
387  {
389 // SG_SPRINT("element %d:\n", i)
390 // SG_SPRINT("\tkey: ")
391 // current->m_key->print_param_info();
392 // SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements())
393  for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
394  current->m_values->get_element(j)->print_param_info("\t\t");
395  }
396 }

SHOGUN Machine Learning Toolbox - Documentation