SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParameterCombination.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-2012 Heiko Strathmann
8  * Written (W) 2012 Jacob Walker
9  *
10  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
11  */
12 
14 #include <shogun/base/Parameter.h>
15 #include <shogun/machine/Machine.h>
16 #include <set>
17 #include <string>
18 
19 using namespace shogun;
20 using namespace std;
21 
23 {
24  init();
25 }
26 
28 {
29  init();
30 
31  m_param=param;
32 }
33 
34 void CParameterCombination::init()
35 {
36  m_param=NULL;
37  m_child_nodes=new CDynamicObjectArray();
38  SG_REF(m_child_nodes);
39 
40  SG_ADD((CSGObject**)&m_child_nodes, "child_nodes",
41  "children of this node", MS_NOT_AVAILABLE);
42 }
43 
45 {
46  delete m_param;
47  SG_UNREF(m_child_nodes);
48 }
49 
51 {
52  m_child_nodes->append_element(child);
53 }
54 
55 
56 
58  const char* name, bool value, index_t index)
59 {
60  if (m_param)
61  {
62  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
63  {
64  void* param = m_param->get_parameter(i)->m_parameter;
65 
66  if (!strcmp(m_param->get_parameter(i)->m_name, name))
67  {
68  if (m_param->get_parameter(i)->m_datatype.m_ptype
69  != PT_BOOL)
70  SG_ERROR("Parameter %s not a boolean parameter", name);
71 
72  if (index < 0)
73  *((bool*)(param)) = value;
74 
75  else
76  (*((bool**)(param)))[index] = value;
77 
78  return true;
79  }
80  }
81 
82  }
83 
84  return false;
85 }
86 
88  const char* name, int32_t value, index_t index)
89 {
90  if (m_param)
91  {
92  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
93  {
94  void* param = m_param->get_parameter(i)->m_parameter;
95 
96  if (!strcmp(m_param->get_parameter(i)->m_name, name))
97  {
98  if (m_param->get_parameter(i)->m_datatype.m_ptype
99  != PT_INT32)
100  SG_ERROR("Parameter %s not a integer parameter", name);
101 
102  if (index < 0)
103  *((int32_t*)(param)) = value;
104 
105  else
106  (*((int32_t**)(param)))[index] = value;
107 
108  return true;
109  }
110  }
111  }
112 
113  return false;
114 }
115 
117  const char* name, float64_t value, index_t index)
118 {
119  if (m_param)
120  {
121  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
122  {
123  void* param = m_param->get_parameter(i)->m_parameter;
124 
125  if (!strcmp(m_param->get_parameter(i)->m_name, name))
126  {
127  if (m_param->get_parameter(i)->m_datatype.m_ptype
128  != PT_FLOAT64)
129  SG_ERROR("Parameter %s not a double parameter", name);
130 
131  if (index < 0)
132  *((float64_t*)(param)) = value;
133 
134  else
135  (*((float64_t**)(param)))[index] = value;
136 
137  return true;
138  }
139  }
140 
141  }
142 
143  return false;
144 }
145 
146 
148 {
149  if (m_param)
150  {
151  for (index_t i = 0; i < m_param->get_num_parameters(); i++)
152  {
153  if (!strcmp(m_param->get_parameter(i)->m_name, name))
154  return m_param->get_parameter(i);
155  }
156 
157  }
158 
159  return NULL;
160 }
161 
162 
164  CSGObject* parent)
165 {
166  bool match = false;
167 
168  if (m_param)
169  {
170  for (index_t i = 0; i < m_param->get_num_parameters(); i++)
171  {
172  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
173  {
174  CSGObject* obj =
175  (*((CSGObject**)m_param->get_parameter(i)->m_parameter));
176  if (parent == obj)
177  match = true;
178  }
179  }
180 
181  }
182 
183  for (index_t i = 0; i < m_child_nodes->get_num_elements(); ++i)
184  {
186  m_child_nodes->get_element(i);
187 
188  TParameter* p;
189 
190  if (!match)
191  p = child->get_parameter(name, parent);
192 
193  else
194  p = child->get_parameter_helper(name);
195 
196  if (p)
197  {
198  SG_UNREF(child);
199  return p;
200  }
201 
202  SG_UNREF(child);
203  }
204 
205  return NULL;
206 }
207 
208 
210 {
211  for (index_t i=0; i<node->m_child_nodes->get_num_elements(); ++i)
212  {
213  CParameterCombination* child=
215  append_child(child->copy_tree());
216  SG_UNREF(child);
217  }
218 }
219 
220 void CParameterCombination::print_tree(int prefix_num) const
221 {
222  /* prefix is enlarged */
223  char* prefix=SG_MALLOC(char, prefix_num+1);
224  for (index_t i=0; i<prefix_num; ++i)
225  prefix[i]='\t';
226 
227  prefix[prefix_num]='\0';
228 
229  /* cases:
230  * -node with a Parameter instance and a possible children
231  * -root node with children
232  */
233 
234  if (m_param)
235  {
236  SG_SPRINT("%s", prefix);
237  for (index_t i=0; i<m_param->get_num_parameters(); ++i)
238  {
239  /* distinction between sgobject and values */
240  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
241  {
242  TParameter* param=m_param->get_parameter(i);
243  CSGObject* current_sgobject=*((CSGObject**) param->m_parameter);
244  SG_SPRINT("\"%s\":%s at %p ", param->m_name,
245  current_sgobject->get_name(), current_sgobject);
246  }
247 
248  else if (m_param->get_parameter(i)->m_datatype.m_ctype == CT_SGVECTOR)
249  {
250  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name);
251  float64_t** param = (float64_t**)(m_param->
252  get_parameter(i)->m_parameter);
253  if (!m_param->get_parameter(i)->m_datatype.m_length_y)
254  {
255  SG_ERROR("Parameter vector %s has no length\n",
256  m_param->get_parameter(i)->m_name);
257  }
258 
259  index_t length = *(m_param->get_parameter(i)->m_datatype.m_length_y);
260 
261  for (index_t j = 0; j < length; j++)
262  SG_SPRINT("%f ", (*param)[j]);
263  }
264 
265  else
266  {
267  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name);
268  void* param=m_param->get_parameter(i)->m_parameter;
269 
270  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_FLOAT64)
271  SG_SPRINT("%f ", *((float64_t*)param));
272  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_INT32)
273  SG_SPRINT("%i ", *((int32_t*)param));
274  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_BOOL)
275  SG_SPRINT("%s ", *((bool*)param ? "true" : "false"));
276  else
278  }
279 
280  }
281 
282  }
283  else
284  SG_SPRINT("%sroot", prefix);
285 
286  SG_SPRINT("\n");
287 
288  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
289  {
291  m_child_nodes->get_element(i);
292  child->print_tree(prefix_num+1);
293  SG_UNREF(child);
294  }
295 
296  SG_FREE(prefix);
297 }
298 
300  const DynArray<Parameter*>& set_1, const DynArray<Parameter*>& set_2)
301 {
302  SG_SDEBUG("entering CParameterCombination::parameter_set_multiplication()\n");
303 
304  SG_SDEBUG("set 1:\n");
305  for (index_t i=0; i<set_1.get_num_elements(); ++i)
306  {
307  for (index_t j=0; j<set_1.get_element(i)->get_num_parameters(); ++j)
308  SG_SDEBUG("\t%s\n", set_1.get_element(i)->get_parameter(j)->m_name);
309  }
310 
311  SG_SDEBUG("set 2:\n");
312  for (index_t i=0; i<set_2.get_num_elements(); ++i)
313  {
314  for (index_t j=0; j<set_2.get_element(i)->get_num_parameters(); ++j)
315  SG_SDEBUG("\t%s\n", set_2.get_element(i)->get_parameter(j)->m_name);
316  }
317 
319 
320  for (index_t i=0; i<set_1.get_num_elements(); ++i)
321  {
322  for (index_t j=0; j<set_2.get_num_elements(); ++j)
323  {
324  Parameter* p=new Parameter();
325  p->add_parameters(set_1[i]);
326  p->add_parameters(set_2[j]);
327  result->append_element(p);
328  }
329  }
330 
331  SG_SDEBUG("leaving CParameterCombination::parameter_set_multiplication()\n");
332  return result;
333 }
334 
336  const CDynamicObjectArray& sets, const CParameterCombination* new_root)
337 {
339 
340  /* check marginal cases */
341  if (sets.get_num_elements()==1)
342  {
343  CDynamicObjectArray* current_set=
345 
346  /* just use the only element into result array.
347  * put root node before all combinations*/
348  *result=*current_set;
349 
350  SG_UNREF(current_set);
351 
352  for (index_t i=0; i<result->get_num_elements(); ++i)
353  {
354  /* put new root as root into the tree and replace tree */
356  result->get_element(i);
357  CParameterCombination* root=new_root->copy_tree();
358  root->append_child(current);
359  result->set_element(root, i);
360  SG_UNREF(current);
361  }
362  }
363  else if (sets.get_num_elements()>1)
364  {
365  /* now the case where at least two sets are given */
366 
367  /* first, extract Parameter instances of given sets */
368  DynArray<DynArray<Parameter*>*> param_sets;
369 
370  for (index_t set_nr=0; set_nr<sets.get_num_elements(); ++set_nr)
371  {
373  sets.get_element(set_nr);
374  DynArray<Parameter*>* new_param_set=new DynArray<Parameter*> ();
375  param_sets.append_element(new_param_set);
376 
377  for (index_t i=0; i<current_set->get_num_elements(); ++i)
378  {
380  current_set->get_element(i);
381 
382  if (current_node->m_child_nodes->get_num_elements())
383  {
384  SG_SERROR("leaf sets multiplication only possible if all "
385  "trees are leafs");
386  }
387 
388  Parameter* current_param=current_node->m_param;
389 
390  if (current_param)
391  new_param_set->append_element(current_param);
392  else
393  {
394  SG_SERROR("leaf sets multiplication only possible if all "
395  "leafs have non-NULL Parameter instances\n");
396  }
397 
398  SG_UNREF(current_node);
399  }
400 
401  SG_UNREF(current_set);
402  }
403 
404  /* second, build products of all parameter sets */
405  DynArray<Parameter*>* param_product=parameter_set_multiplication(
406  *param_sets[0], *param_sets[1]);
407 
408  delete param_sets[0];
409  delete param_sets[1];
410 
411  /* build product of all remaining sets and collect results. delete all
412  * parameter instances of interim products*/
413  for (index_t i=2; i<param_sets.get_num_elements(); ++i)
414  {
415  DynArray<Parameter*>* old_temp_result=param_product;
416  param_product=parameter_set_multiplication(*param_product,
417  *param_sets[i]);
418 
419  /* delete interim result parameter instances */
420  for (index_t j=0; j<old_temp_result->get_num_elements(); ++j)
421  delete old_temp_result->get_element(j);
422 
423  /* and dyn arrays of interim result and of param_sets */
424  delete old_temp_result;
425  delete param_sets[i];
426  }
427 
428  /* at this point there is only one DynArray instance remaining:
429  * param_product. contains all combinations of parameters of all given
430  * sets */
431 
432  /* third, build tree sets with the given root and the parameter product
433  * elements */
434  for (index_t i=0; i<param_product->get_num_elements(); ++i)
435  {
436  /* build parameter node from parameter product to append to root */
438  param_product->get_element(i));
439 
440  /* copy new root node, has to be a new one each time */
441  CParameterCombination* root=new_root->copy_tree();
442 
443  /* append both and add them to result set */
444  root->append_child(param_node);
445  result->append_element(root);
446  }
447 
448  /* this is not needed anymore, because the Parameter instances are now
449  * in the resulting tree sets */
450  delete param_product;
451  }
452 
453  return result;
454 }
455 
457  const CDynamicObjectArray* sets,
458  const CParameterCombination* new_root)
459 {
460  SG_SDEBUG("entering CParameterCombination::non_value_tree_multiplication()\n");
462 
463  /* first step: get all names in the sets */
464  set<string> names;
465 
466  for (index_t j=0;
467  j<sets->get_num_elements(); ++j)
468  {
469  CDynamicObjectArray* current_set=
471  sets->get_element(j);
472 
473  for (index_t k=0; k
474  <current_set->get_num_elements(); ++k)
475  {
477  current_set->get_element(k);
478 
479  names.insert(string(current_tree->m_param->get_parameter(0)->m_name));
480 
481  SG_UNREF(current_tree);
482  }
483 
484  SG_UNREF(current_set);
485  }
486 
487  SG_SDEBUG("all names\n");
488  for (set<string>::iterator it=names.begin(); it!=names.end(); ++it)
489  SG_SDEBUG("\"%s\"\n", (*it).c_str());
490 
491  /* only do stuff if there are names */
492  if (!names.empty())
493  {
494  /* next step, build temporary structure where all elements with first
495  * name are put. Elements of that structure will be extend iteratively
496  * per name */
497 
498 
499  /* extract all trees with first name */
500  const char* first_name=(*(names.begin())).c_str();
501  CDynamicObjectArray* trees=
503 
504  SG_SDEBUG("adding trees for first name \"%s\":\n", first_name);
505  for (index_t i=0; i<trees->get_num_elements(); ++i)
506  {
507  CParameterCombination* current_tree=
509 
510  CParameterCombination* current_root=new_root->copy_tree();
511  current_root->append_child(current_tree);
512  result->append_element(current_root);
513 
514 // current_tree->print_tree(1);
515  SG_UNREF(current_tree);
516  }
517  SG_UNREF(trees);
518 
519  /* now iterate over the remaining names and build products */
520  SG_SDEBUG("building products with remaining trees:\n");
521  set<string>::iterator it=names.begin();
522  for (++it; it!=names.end(); ++it)
523  {
524  SG_SDEBUG("processing \"%s\"\n", (*it).c_str());
525 
526  /* extract all trees with current name */
527  const char* current_name=(*it).c_str();
529  current_name);
530 
531  /* create new set of trees where each element is put once for each
532  * of the just generated trees */
533  CDynamicObjectArray* new_result=new CDynamicObjectArray();
534  for (index_t i=0; i<result->get_num_elements(); ++i)
535  {
536  for (index_t j=0; j<trees->get_num_elements(); ++j)
537  {
538  CParameterCombination* to_copy=
539  (CParameterCombination*)result->get_element(i);
540 
541  /* create a copy of current element */
542  CParameterCombination* new_element=to_copy->copy_tree();
543  SG_UNREF(to_copy);
544 
545  CParameterCombination* to_add=
547  new_element->append_child(to_add);
548  SG_UNREF(to_add);
549  new_result->append_element(new_element);
550 // SG_SDEBUG("added:\n");
551 // new_element->print_tree();
552  }
553  }
554 
555  /* clean up */
556  SG_UNREF(trees);
557 
558  /* replace result by new_result */
559  SG_UNREF(result);
560  result=new_result;
561  }
562  }
563 
564  SG_SDEBUG("leaving CParameterCombination::non_value_tree_multiplication()\n");
565  return result;
566 }
567 
569  const CDynamicObjectArray* sets, const char* desired_name)
570 {
572 
573  for (index_t j=0;
574  j<sets->get_num_elements(); ++j)
575  {
576  CDynamicObjectArray* current_set=
577  (CDynamicObjectArray*) sets->get_element(j);
578 
579  for (index_t k=0; k<current_set->get_num_elements(); ++k)
580  {
582  current_set->get_element(k);
583 
584  char* current_name=current_tree->m_param->get_parameter(0)->m_name;
585 
586  if (!strcmp(current_name, desired_name))
587  result->append_element(current_tree);
588 
589  SG_UNREF(current_tree);
590  }
591 
592  SG_UNREF(current_set);
593  }
594 
595  return result;
596 }
597 
599 {
601 
602  /* but build new Parameter instance */
603 
604  /* only call add_parameters() argument is non-null */
605  if (m_param)
606  {
607  copy->m_param=new Parameter();
608  copy->m_param->add_parameters(m_param);
609  } else
610  copy->m_param=NULL;
611 
612  /* recursively copy all children */
613  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
614  {
616  m_child_nodes->get_element(i);
617  copy->m_child_nodes->append_element(child->copy_tree());
618  SG_UNREF(child);
619  }
620 
621  return copy;
622 }
623 
625 {
626  apply_to_modsel_parameter(machine->m_model_selection_parameters);
627 }
628 
630  Parameter* parameter) const
631 {
632  /* case root node */
633  if (!m_param)
634  {
635  /* iterate over all children and recursively set parameters from
636  * their values to the current parameter input (its just handed one
637  * recursion level downwards) */
638  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
639  {
641  m_child_nodes->get_element(i);
642  child->apply_to_modsel_parameter(parameter);
643  SG_UNREF(child);
644  }
645  }
646  /* case parameter node */
647  else if (m_param)
648  {
649  /* set parameters */
650  parameter->set_from_parameters(m_param);
651 
652  /* does this node has sub parameters? */
653  if (has_children())
654  {
655  /* if a parameter node has children, it has to have ONE CSGObject as
656  * parameter */
657  if (m_param->get_num_parameters()>1 ||
658  m_param->get_parameter(0)->m_datatype.m_ptype!=PT_SGOBJECT)
659  {
660  SG_SERROR("invalid CParameterCombination node type, has children"
661  " and more than one parameter or is not a "
662  "CSGObject.\n");
663  }
664 
665  /* cast is now safe */
666  CSGObject* current_sgobject=
667  *((CSGObject**)(m_param->get_parameter(0)->m_parameter));
668 
669  /* iterate over all children and recursively set parameters from
670  * their values */
671  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
672  {
674  m_child_nodes->get_element(i);
676  current_sgobject->m_model_selection_parameters);
677  SG_UNREF(child);
678  }
679  }
680  }
681  else
682  SG_SERROR("CParameterCombination node has illegal type.\n");
683 }

SHOGUN Machine Learning Toolbox - Documentation