SHOGUN  v1.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ModelSelectionParameters.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 
13 #include <shogun/lib/DataType.h>
14 #include <shogun/base/Parameter.h>
15 #include <shogun/base/DynArray.h>
16 
17 using namespace shogun;
18 
20 {
21  init();
22 }
23 
25 {
26  init();
27 
28  m_node_name=node_name;
29 }
30 
32  CSGObject* sgobject)
33 {
34  init();
35 
36  m_node_name=node_name;
37  m_sgobject=sgobject;
38  SG_REF(sgobject);
39 }
40 
41 void CModelSelectionParameters::init()
42 {
43  m_node_name=NULL;
44  m_sgobject=NULL;
46  SG_REF(m_child_nodes);
47  m_value_type=MSPT_NONE;
48 
49  m_parameters->add((char*)m_node_name, "node_name", "Name of node");
50  m_parameters->add((CSGObject**)&m_sgobject, "sgobject",
51  "CSGObject of this node");
52  m_parameters->add((CSGObject**)m_child_nodes, "child nodes",
53  "children of this node");
54 // m_parameters->add(&m_value_type, "value_type",
55 // "type of the values of this node");
56 }
57 
59 {
60  SG_UNREF(m_child_nodes);
61  SG_UNREF(m_sgobject);
62 
63  delete_values();
64 }
65 
67 {
68  /* only possible if there are no values set */
69  if (m_values.vector)
70  SG_ERROR("not possible to append child: there already is a range\n");
71 
72  /* do a basic check if the add is possible */
73  if (m_sgobject)
74  {
75  /* (does this node's CSGObject contain a parameter with the name of the
76  * child?) to prevent problems when trying to set parameters that do not
77  * exist */
78  if (child->m_node_name)
79  {
80  if (!m_sgobject->m_parameters->contains_parameter(child->m_node_name))
81  {
82  SG_ERROR("Not possible to add child, node with CSGObject \"%s\""
83  " does not contain a parameter called \"%s\"\n",
84  m_sgobject->get_name(), child->m_node_name);
85  }
86  }
87  else
88  {
89  SG_ERROR("Not possible to add child which has no name.\n");
90  }
91  }
92 
93  m_child_nodes->append_element(child);
94 }
95 
96 template <class T>
98 {
99  /* possibly delete old range values */
100  delete_values();
101  m_values=(SGVector<char>) values;
102 }
103 
105  ERangeType type, float64_t step, float64_t type_base)
106 {
107  build_values(MSPT_FLOAT64, (void*)&min, (void*)&max, type, (void*)&step,
108  (void*)&type_base);
109 }
110 
111 void CModelSelectionParameters::build_values(int32_t min, int32_t max,
112  ERangeType type, int32_t step, int32_t type_base)
113 {
114  build_values(MSPT_INT32, (void*)&min, (void*)&max, type, (void*)&step,
115  (void*)&type_base);
116 }
117 
118 void CModelSelectionParameters::build_values(EMSParamType value_type, void* min,
119  void* max, ERangeType type, void* step, void* type_base)
120 {
121  if (m_sgobject || has_children())
122  {
123  SG_ERROR("unable to set range for an CSGObject model selection "
124  "parameter\n");
125  }
126 
127  /* possibly delete old range values */
128  delete_values();
129 
130  /* save new type */
131  m_value_type=value_type;
132 
133  if (value_type==MSPT_FLOAT64)
134  {
135  SGVector<float64_t> values=create_range_array<float64_t>(
136  *((float64_t*)min),
137  *((float64_t*)max),
138  type,
139  *((float64_t*)step),
140  *((float64_t*)type_base));
141 
142  m_values.vector=(char*)values.vector;
143  m_values.vlen=values.vlen;
144  }
145  else if (value_type==MSPT_INT32)
146  {
147  SGVector<int32_t> values=create_range_array<int32_t>(
148  *((int32_t*)min),
149  *((int32_t*)max),
150  type,
151  *((int32_t*)step),
152  *((int32_t*)type_base));
153 
154  m_values.vector=(char*)values.vector;
155  m_values.vlen=values.vlen;
156  }
157  else if (value_type==MSPT_NONE)
158  {
159  SG_ERROR("Value node has no type!\n");
160  }
161  else
162  {
163  SG_ERROR("Unknown type for model selection parameter!\n");
164  }
165 }
166 
168 {
171 
172  /* value case: node with values and no children.
173  * build trees of Parameter instances which each contain one value
174  */
175 
176  if (m_values.vector)
177  {
178  for (index_t i=0; i<m_values.vlen; ++i)
179  {
180  // create tree with only one parameter element //
181  Parameter* p=new Parameter();
182 
183  switch (m_value_type)
184  {
185  case MSPT_FLOAT64:
186  p->add(&((float64_t*)m_values.vector)[i], m_node_name);
187  break;
188  case MSPT_INT32:
189  p->add(&((int32_t*)m_values.vector)[i], m_node_name);;
190  break;
191  case MSPT_NONE:
192  SG_ERROR("Value node has no type!\n");
193  break;
194  default:
195  SG_ERROR("Unknown type for model selection parameter!\n");
196  break;
197  }
198 
199  result->append_element(new CParameterCombination(p));
200  }
201 
202  return result;
203  }
204 
205 
206  /* two cases here, similar
207  * -case CSGObject:
208  * -case root node (no name, no values, but children
209  * build all permutations of the result trees of children with values and
210  * combine them iteratively children which are something different
211  */
212  if (!((m_sgobject && m_node_name) || (!m_node_name && !m_sgobject)))
213  SG_ERROR("Illegal CModelSelectionParameters node type.\n");
214 
215  /* only consider combinations if this node has children */
216  if (m_child_nodes->get_num_elements())
217  {
218  /* split value and non-value child combinations */
221 
222  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
223  {
224  CModelSelectionParameters* current=m_child_nodes->get_element(i);
225 
226  /* split children with values and children with other */
227  if (current->m_values.vector)
228  value_children.append_element(current);
229  else
230  non_value_children.append_element(current);
231 
232  SG_UNREF(current);
233  }
234 
235  /* extract all tree sets of all value children */
237  for (index_t i=0; i<value_children.get_num_elements(); ++i)
238  {
239  /* recursively get all combinations in a new array */
240  CModelSelectionParameters* value_child=
241  value_children.get_element(i);
242  value_node_sets.append_element(value_child->get_combinations());
243  SG_UNREF(value_child);
244  }
245 
246  /* build product of all these tree sets */
247 
248  /* new root node is needed for new trees, depends on current case */
249  CParameterCombination* new_root=NULL;
250  if (m_sgobject)
251  {
252  Parameter* p=new Parameter();
253  p->add(&m_sgobject, m_node_name);
254  new_root=new CParameterCombination(p);
255  }
256  else
257  new_root=new CParameterCombination();
258 
259  SG_REF(new_root);
260 
261  CDynamicObjectArray<CParameterCombination>* value_combinations=
263  new_root);
264 
265  SG_UNREF(new_root);
266 
267  /* if there are no non-value sets, just use the above result */
268  if (!non_value_children.get_num_elements())
269  *result=*value_combinations;
270  /* in the other case, the non-values have also to be treated, but
271  * combined iteratively */
272  else
273  {
274  /* extract all tree sets of non-value nodes */
276  non_value_combinations;
277  for (index_t i=0; i<non_value_children.get_num_elements(); ++i)
278  {
279  /* recursively get all combinations in a new array */
280  CModelSelectionParameters* non_value_child=
281  non_value_children.get_element(i);
282  non_value_combinations.append_element(
283  non_value_child->get_combinations());
284  SG_UNREF(non_value_child);
285  }
286 
287  /* combine combinations of value and non-value nodes */
288 
289  /* if there are only non-value children, nothing is combined */
290  if (!value_combinations->get_num_elements())
291  {
292  /* non-value children are only pasted together. However, the
293  * new root node is to put as root in front of all trees.
294  * If there were value children before, this is done by
295  * value_node_sets_multiplication. In this case it has to be done
296  * by hand. */
297 
298  for (index_t j=0;
299  j<non_value_combinations.get_num_elements(); ++j)
300  {
301  CDynamicObjectArray<CParameterCombination>* current_non_value_set=
302  non_value_combinations.get_element(j);
303 
304  for (index_t k=0; k
305  <current_non_value_set->get_num_elements(); ++k)
306  {
307  CParameterCombination* current_non_value_tree=
308  current_non_value_set->get_element(k);
309 
310  /* append new root with rest of tree to current
311  * tree. re-use of new_root variable, safe here */
312  new_root=new CParameterCombination();
313  new_root->append_child(current_non_value_tree);
314  result->append_element(new_root);
315 
316  SG_UNREF(current_non_value_tree);
317  }
318 
319  SG_UNREF(current_non_value_set);
320  }
321  }
322  else
323  {
324  for (index_t i=0; i<value_combinations->get_num_elements(); ++i)
325  {
326  CParameterCombination* current_value_tree=
327  value_combinations->get_element(i);
328 
329  for (index_t j=0; j
330  <non_value_combinations.get_num_elements(); ++j)
331  {
332  CDynamicObjectArray<CParameterCombination> * current_non_value_set=
333  non_value_combinations.get_element(j);
334 
335  for (index_t k=0; k
336  <current_non_value_set->get_num_elements(); ++k)
337  {
338  CParameterCombination* current_non_value_tree=
339  current_non_value_set->get_element(k);
340 
341  /* copy the current trees and append non-value
342  * tree to value tree. Note that the root in the
343  * non-value tree is already the current
344  * CSGObject and therefore the non-value tree
345  * copy may just be appended as child */
346  CParameterCombination* value_copy=
347  current_value_tree->copy_tree();
348  CParameterCombination* non_value_copy=
349  current_non_value_tree->copy_tree();
350 
351  value_copy->append_child(non_value_copy);
352  result->append_element(value_copy);
353 
354  SG_UNREF(current_non_value_tree);
355  }
356 
357  SG_UNREF(current_non_value_set);
358  }
359 
360  SG_UNREF(current_value_tree);
361  }
362  }
363  }
364 
365  SG_UNREF(value_combinations);
366  }
367  else
368  {
369  /* if there are no children of a sgobject or root node, result is
370  * only one element (sgobject node) or empty (root node)
371  */
372  if (m_sgobject)
373  {
374  Parameter* p=new Parameter();
375  p->add(&m_sgobject, m_node_name);
376  result->append_element(new CParameterCombination(p));
377  }
378  }
379 
380  return result;
381 }
382 
384 {
385  /* prefix is enlarged */
386  char* prefix=SG_MALLOC(char, prefix_num+1);
387  for (index_t i=0; i<prefix_num; ++i)
388  prefix[i]='\t';
389 
390  prefix[prefix_num]='\0';
391 
392  if (has_children())
393  {
394  if (m_sgobject)
395  SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name());
396  else
397  SG_PRINT("%s%s with\n", prefix, m_node_name ? m_node_name : "root");
398 
399  /* now recursively print successors */
400 
401  /* cast safe because only CModelSelectionParameters are added to list */
402  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
403  {
404  CModelSelectionParameters* child=m_child_nodes->get_element(i);
405  child->print_tree(prefix_num+1);
406  SG_UNREF(child);
407  }
408  }
409  else
410  {
411  /* has to be a node with name and a numeric range or a single sg_object
412  * without children*/
413  if (m_sgobject)
414  {
415  SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name());
416  }
417  else
418  {
419  if (m_values.vector)
420  {
421  // value node
422  SG_PRINT("%s%s with values: ", prefix, m_node_name);
423 
424  switch (m_value_type)
425  {
426  case MSPT_FLOAT64:
427  CMath::display_vector((float64_t*)m_values.vector, m_values.vlen);
428  break;
429  case MSPT_INT32:
430  CMath::display_vector((int32_t*)m_values.vector, m_values.vlen);;
431  break;
432  case MSPT_NONE:
433  SG_ERROR("Value node has no type!\n");
434  break;
435  default:
436  SG_ERROR("Unknown type for model selection parameter!\n");
437  break;
438  }
439  }
440  else
441  SG_PRINT("root\n");
442  }
443  }
444 
445  SG_FREE(prefix);
446 }
447 
448 void CModelSelectionParameters::delete_values()
449 {
450  if (m_values.vector)
451  {
452  switch (m_value_type)
453  {
454  case MSPT_FLOAT64:
455  SG_FREE((float64_t*) m_values.vector);
456  break;
457  case MSPT_INT32:
458  SG_FREE((int32_t*) m_values.vector);
459  break;
460  case MSPT_NONE:
461  SG_ERROR("Value node has no type!\n");
462  break;
463  default:
464  SG_ERROR("Unknown type for model selection parameter!\n");
465  break;
466  }
467  }
468 }

SHOGUN Machine Learning Toolbox - Documentation