SHOGUN  v3.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  * Written (W) 2013 Roman Votyakov
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 
35 {
36  init();
37 
38  Parameter* gradient_params=obj->m_gradient_parameters;
39 
40  for (index_t i=0; i<gradient_params->get_num_parameters(); i++)
41  {
42  TParameter* param=gradient_params->get_parameter(i);
43  TSGDataType type=param->m_datatype;
44 
45  if (type.m_ptype==PT_FLOAT64 || type.m_ptype==PT_FLOAT32 ||
46  type.m_ptype==PT_FLOATMAX)
47  {
48  if ((type.m_ctype==CT_SGVECTOR || type.m_ctype==CT_VECTOR))
49  {
50  Parameter* p=new Parameter();
51  p->add_vector((float64_t**)param->m_parameter, type.m_length_y,
52  param->m_name);
53 
54  m_child_nodes->append_element(new CParameterCombination(p));
55  m_parameters_length+=*(type.m_length_y);
56  }
57  else if (type.m_ctype==CT_SCALAR)
58  {
59  Parameter* p=new Parameter();
60  p->add((float64_t*)param->m_parameter, param->m_name);
61 
62  m_child_nodes->append_element(new CParameterCombination(p));
63  m_parameters_length++;
64  }
65  }
66  else
67  {
68  SG_WARNING("Parameter %s.%s was not added to parameter combination, "
69  "since it isn't of floating point type\n", obj->get_name(),
70  param->m_name);
71  }
72  }
73 
74  Parameter* modsel_params=obj->m_model_selection_parameters;
75 
76  for (index_t i=0; i<modsel_params->get_num_parameters(); i++)
77  {
78  TParameter* param=modsel_params->get_parameter(i);
79  TSGDataType type=param->m_datatype;
80 
81  if (type.m_ptype==PT_SGOBJECT)
82  {
83  if (type.m_ctype==CT_SCALAR)
84  {
85  CSGObject* child=*((CSGObject**)(param->m_parameter));
86 
88  {
90 
91  comb->m_param=new Parameter();
92  comb->m_param->add((CSGObject**)(param->m_parameter),
93  param->m_name);
94 
95  m_child_nodes->append_element(comb);
96  m_parameters_length+=comb->m_parameters_length;
97  }
98  }
99  else
100  {
102  }
103  }
104  }
105 }
106 
107 void CParameterCombination::init()
108 {
109  m_parameters_length=0;
110  m_param=NULL;
111  m_child_nodes=new CDynamicObjectArray();
112  SG_REF(m_child_nodes);
113 
114  SG_ADD((CSGObject**)&m_child_nodes, "child_nodes", "Children of this node",
116 }
117 
119 {
120  delete m_param;
121  SG_UNREF(m_child_nodes);
122 }
123 
125 {
126  m_child_nodes->append_element(child);
127 }
128 
130  const char* name, bool value, index_t index)
131 {
132  if (m_param)
133  {
134  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
135  {
136  void* param = m_param->get_parameter(i)->m_parameter;
137 
138  if (!strcmp(m_param->get_parameter(i)->m_name, name))
139  {
140  if (m_param->get_parameter(i)->m_datatype.m_ptype
141  != PT_BOOL)
142  SG_ERROR("Parameter %s not a boolean parameter", name)
143 
144  if (index < 0)
145  *((bool*)(param)) = value;
146 
147  else
148  (*((bool**)(param)))[index] = value;
149 
150  return true;
151  }
152  }
153 
154  }
155 
156  return false;
157 }
158 
160  const char* name, int32_t value, index_t index)
161 {
162  if (m_param)
163  {
164  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
165  {
166  void* param = m_param->get_parameter(i)->m_parameter;
167 
168  if (!strcmp(m_param->get_parameter(i)->m_name, name))
169  {
170  if (m_param->get_parameter(i)->m_datatype.m_ptype
171  != PT_INT32)
172  SG_ERROR("Parameter %s not a integer parameter", name)
173 
174  if (index < 0)
175  *((int32_t*)(param)) = value;
176 
177  else
178  (*((int32_t**)(param)))[index] = value;
179 
180  return true;
181  }
182  }
183  }
184 
185  return false;
186 }
187 
189  const char* name, float64_t value, index_t index)
190 {
191  if (m_param)
192  {
193  for (index_t i = 0; i < m_param->get_num_parameters(); ++i)
194  {
195  void* param = m_param->get_parameter(i)->m_parameter;
196 
197  if (!strcmp(m_param->get_parameter(i)->m_name, name))
198  {
199  if (m_param->get_parameter(i)->m_datatype.m_ptype
200  != PT_FLOAT64)
201  SG_ERROR("Parameter %s not a double parameter", name)
202 
203  if (index < 0)
204  *((float64_t*)(param)) = value;
205 
206  else
207  (*((float64_t**)(param)))[index] = value;
208 
209  return true;
210  }
211  }
212 
213  }
214 
215  return false;
216 }
217 
218 
220 {
221  if (m_param)
222  {
223  for (index_t i = 0; i < m_param->get_num_parameters(); i++)
224  {
225  if (!strcmp(m_param->get_parameter(i)->m_name, name))
226  return m_param->get_parameter(i);
227  }
228 
229  }
230 
231  return NULL;
232 }
233 
234 
236  CSGObject* parent)
237 {
238  bool match = false;
239 
240  if (m_param)
241  {
242  for (index_t i = 0; i < m_param->get_num_parameters(); i++)
243  {
244  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
245  {
246  CSGObject* obj =
247  (*((CSGObject**)m_param->get_parameter(i)->m_parameter));
248  if (parent == obj)
249  match = true;
250  }
251  }
252 
253  }
254 
255  for (index_t i = 0; i < m_child_nodes->get_num_elements(); ++i)
256  {
258  m_child_nodes->get_element(i);
259 
260  TParameter* p;
261 
262  if (!match)
263  p = child->get_parameter(name, parent);
264 
265  else
266  p = child->get_parameter_helper(name);
267 
268  if (p)
269  {
270  SG_UNREF(child);
271  return p;
272  }
273 
274  SG_UNREF(child);
275  }
276 
277  return NULL;
278 }
279 
280 
282 {
283  for (index_t i=0; i<node->m_child_nodes->get_num_elements(); ++i)
284  {
285  CParameterCombination* child=
287  append_child(child->copy_tree());
288  SG_UNREF(child);
289  }
290 }
291 
292 void CParameterCombination::print_tree(int prefix_num) const
293 {
294  /* prefix is enlarged */
295  char* prefix=SG_MALLOC(char, prefix_num+1);
296  for (index_t i=0; i<prefix_num; ++i)
297  prefix[i]='\t';
298 
299  prefix[prefix_num]='\0';
300 
301  /* cases:
302  * -node with a Parameter instance and a possible children
303  * -root node with children
304  */
305 
306  if (m_param)
307  {
308  SG_SPRINT("%s", prefix)
309  for (index_t i=0; i<m_param->get_num_parameters(); ++i)
310  {
311  /* distinction between sgobject and values */
312  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
313  {
314  TParameter* param=m_param->get_parameter(i);
315  CSGObject* current_sgobject=*((CSGObject**) param->m_parameter);
316  SG_SPRINT("\"%s\":%s at %p ", param->m_name,
317  current_sgobject->get_name(), current_sgobject);
318  }
319 
320  else if (m_param->get_parameter(i)->m_datatype.m_ctype == CT_SGVECTOR)
321  {
322  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name)
323  float64_t** param = (float64_t**)(m_param->
324  get_parameter(i)->m_parameter);
325  if (!m_param->get_parameter(i)->m_datatype.m_length_y)
326  {
327  SG_ERROR("Parameter vector %s has no length\n",
328  m_param->get_parameter(i)->m_name);
329  }
330 
331  index_t length = *(m_param->get_parameter(i)->m_datatype.m_length_y);
332 
333  for (index_t j = 0; j < length; j++)
334  SG_SPRINT("%f ", (*param)[j])
335  }
336 
337  else
338  {
339  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name)
340  void* param=m_param->get_parameter(i)->m_parameter;
341 
342  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_FLOAT64)
343  SG_SPRINT("%f ", *((float64_t*)param))
344  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_INT32)
345  SG_SPRINT("%i ", *((int32_t*)param))
346  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_BOOL)
347  SG_SPRINT("%s ", *((bool*)param ? "true" : "false"))
348  else
350  }
351 
352  }
353 
354  }
355  else
356  SG_SPRINT("%sroot", prefix)
357 
358  SG_SPRINT("\n")
359 
360  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
361  {
363  m_child_nodes->get_element(i);
364  child->print_tree(prefix_num+1);
365  SG_UNREF(child);
366  }
367 
368  SG_FREE(prefix);
369 }
370 
372  const DynArray<Parameter*>& set_1, const DynArray<Parameter*>& set_2)
373 {
374  SG_SDEBUG("entering CParameterCombination::parameter_set_multiplication()\n")
375 
376  SG_SDEBUG("set 1:\n")
377  for (index_t i=0; i<set_1.get_num_elements(); ++i)
378  {
379  for (index_t j=0; j<set_1.get_element(i)->get_num_parameters(); ++j)
380  SG_SDEBUG("\t%s\n", set_1.get_element(i)->get_parameter(j)->m_name)
381  }
382 
383  SG_SDEBUG("set 2:\n")
384  for (index_t i=0; i<set_2.get_num_elements(); ++i)
385  {
386  for (index_t j=0; j<set_2.get_element(i)->get_num_parameters(); ++j)
387  SG_SDEBUG("\t%s\n", set_2.get_element(i)->get_parameter(j)->m_name)
388  }
389 
391 
392  for (index_t i=0; i<set_1.get_num_elements(); ++i)
393  {
394  for (index_t j=0; j<set_2.get_num_elements(); ++j)
395  {
396  Parameter* p=new Parameter();
397  p->add_parameters(set_1[i]);
398  p->add_parameters(set_2[j]);
399  result->append_element(p);
400  }
401  }
402 
403  SG_SDEBUG("leaving CParameterCombination::parameter_set_multiplication()\n")
404  return result;
405 }
406 
408  const CDynamicObjectArray& sets, const CParameterCombination* new_root)
409 {
411 
412  /* check marginal cases */
413  if (sets.get_num_elements()==1)
414  {
415  CDynamicObjectArray* current_set=
417 
418  /* just use the only element into result array.
419  * put root node before all combinations*/
420  *result=*current_set;
421 
422  SG_UNREF(current_set);
423 
424  for (index_t i=0; i<result->get_num_elements(); ++i)
425  {
426  /* put new root as root into the tree and replace tree */
428  result->get_element(i);
429  CParameterCombination* root=new_root->copy_tree();
430  root->append_child(current);
431  result->set_element(root, i);
432  SG_UNREF(current);
433  }
434  }
435  else if (sets.get_num_elements()>1)
436  {
437  /* now the case where at least two sets are given */
438 
439  /* first, extract Parameter instances of given sets */
440  DynArray<DynArray<Parameter*>*> param_sets;
441 
442  for (index_t set_nr=0; set_nr<sets.get_num_elements(); ++set_nr)
443  {
445  sets.get_element(set_nr);
446  DynArray<Parameter*>* new_param_set=new DynArray<Parameter*> ();
447  param_sets.append_element(new_param_set);
448 
449  for (index_t i=0; i<current_set->get_num_elements(); ++i)
450  {
452  current_set->get_element(i);
453 
454  if (current_node->m_child_nodes->get_num_elements())
455  {
456  SG_SERROR("leaf sets multiplication only possible if all "
457  "trees are leafs");
458  }
459 
460  Parameter* current_param=current_node->m_param;
461 
462  if (current_param)
463  new_param_set->append_element(current_param);
464  else
465  {
466  SG_SERROR("leaf sets multiplication only possible if all "
467  "leafs have non-NULL Parameter instances\n");
468  }
469 
470  SG_UNREF(current_node);
471  }
472 
473  SG_UNREF(current_set);
474  }
475 
476  /* second, build products of all parameter sets */
477  DynArray<Parameter*>* param_product=parameter_set_multiplication(
478  *param_sets[0], *param_sets[1]);
479 
480  delete param_sets[0];
481  delete param_sets[1];
482 
483  /* build product of all remaining sets and collect results. delete all
484  * parameter instances of interim products*/
485  for (index_t i=2; i<param_sets.get_num_elements(); ++i)
486  {
487  DynArray<Parameter*>* old_temp_result=param_product;
488  param_product=parameter_set_multiplication(*param_product,
489  *param_sets[i]);
490 
491  /* delete interim result parameter instances */
492  for (index_t j=0; j<old_temp_result->get_num_elements(); ++j)
493  delete old_temp_result->get_element(j);
494 
495  /* and dyn arrays of interim result and of param_sets */
496  delete old_temp_result;
497  delete param_sets[i];
498  }
499 
500  /* at this point there is only one DynArray instance remaining:
501  * param_product. contains all combinations of parameters of all given
502  * sets */
503 
504  /* third, build tree sets with the given root and the parameter product
505  * elements */
506  for (index_t i=0; i<param_product->get_num_elements(); ++i)
507  {
508  /* build parameter node from parameter product to append to root */
510  param_product->get_element(i));
511 
512  /* copy new root node, has to be a new one each time */
513  CParameterCombination* root=new_root->copy_tree();
514 
515  /* append both and add them to result set */
516  root->append_child(param_node);
517  result->append_element(root);
518  }
519 
520  /* this is not needed anymore, because the Parameter instances are now
521  * in the resulting tree sets */
522  delete param_product;
523  }
524 
525  return result;
526 }
527 
529  const CDynamicObjectArray* sets,
530  const CParameterCombination* new_root)
531 {
532  SG_SDEBUG("entering CParameterCombination::non_value_tree_multiplication()\n")
534 
535  /* first step: get all names in the sets */
536  set<string> names;
537 
538  for (index_t j=0;
539  j<sets->get_num_elements(); ++j)
540  {
541  CDynamicObjectArray* current_set=
543  sets->get_element(j);
544 
545  for (index_t k=0; k
546  <current_set->get_num_elements(); ++k)
547  {
549  current_set->get_element(k);
550 
551  names.insert(string(current_tree->m_param->get_parameter(0)->m_name));
552 
553  SG_UNREF(current_tree);
554  }
555 
556  SG_UNREF(current_set);
557  }
558 
559  SG_SDEBUG("all names\n")
560  for (set<string>::iterator it=names.begin(); it!=names.end(); ++it)
561  SG_SDEBUG("\"%s\"\n", (*it).c_str())
562 
563  /* only do stuff if there are names */
564  if (!names.empty())
565  {
566  /* next step, build temporary structure where all elements with first
567  * name are put. Elements of that structure will be extend iteratively
568  * per name */
569 
570 
571  /* extract all trees with first name */
572  const char* first_name=(*(names.begin())).c_str();
573  CDynamicObjectArray* trees=
575 
576  SG_SDEBUG("adding trees for first name \"%s\":\n", first_name)
577  for (index_t i=0; i<trees->get_num_elements(); ++i)
578  {
579  CParameterCombination* current_tree=
581 
582  CParameterCombination* current_root=new_root->copy_tree();
583  current_root->append_child(current_tree);
584  result->append_element(current_root);
585 
586  // current_tree->print_tree(1);
587  SG_UNREF(current_tree);
588  }
589  SG_UNREF(trees);
590 
591  /* now iterate over the remaining names and build products */
592  SG_SDEBUG("building products with remaining trees:\n")
593  set<string>::iterator it=names.begin();
594  for (++it; it!=names.end(); ++it)
595  {
596  SG_SDEBUG("processing \"%s\"\n", (*it).c_str())
597 
598  /* extract all trees with current name */
599  const char* current_name=(*it).c_str();
601  current_name);
602 
603  /* create new set of trees where each element is put once for each
604  * of the just generated trees */
605  CDynamicObjectArray* new_result=new CDynamicObjectArray();
606  for (index_t i=0; i<result->get_num_elements(); ++i)
607  {
608  for (index_t j=0; j<trees->get_num_elements(); ++j)
609  {
610  CParameterCombination* to_copy=
611  (CParameterCombination*)result->get_element(i);
612 
613  /* create a copy of current element */
614  CParameterCombination* new_element=to_copy->copy_tree();
615  SG_UNREF(to_copy);
616 
617  CParameterCombination* to_add=
619  new_element->append_child(to_add);
620  SG_UNREF(to_add);
621  new_result->append_element(new_element);
622  // SG_SDEBUG("added:\n")
623  // new_element->print_tree();
624  }
625  }
626 
627  /* clean up */
628  SG_UNREF(trees);
629 
630  /* replace result by new_result */
631  SG_UNREF(result);
632  result=new_result;
633  }
634  }
635 
636  SG_SDEBUG("leaving CParameterCombination::non_value_tree_multiplication()\n")
637  return result;
638 }
639 
641  const CDynamicObjectArray* sets, const char* desired_name)
642 {
644 
645  for (index_t j=0;
646  j<sets->get_num_elements(); ++j)
647  {
648  CDynamicObjectArray* current_set=
649  (CDynamicObjectArray*) sets->get_element(j);
650 
651  for (index_t k=0; k<current_set->get_num_elements(); ++k)
652  {
654  current_set->get_element(k);
655 
656  char* current_name=current_tree->m_param->get_parameter(0)->m_name;
657 
658  if (!strcmp(current_name, desired_name))
659  result->append_element(current_tree);
660 
661  SG_UNREF(current_tree);
662  }
663 
664  SG_UNREF(current_set);
665  }
666 
667  return result;
668 }
669 
671 {
673 
674  /* but build new Parameter instance */
675 
676  /* only call add_parameters() argument is non-null */
677  if (m_param)
678  {
679  copy->m_param=new Parameter();
680  copy->m_param->add_parameters(m_param);
681  } else
682  copy->m_param=NULL;
683 
684  /* recursively copy all children */
685  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
686  {
688  m_child_nodes->get_element(i);
689  copy->m_child_nodes->append_element(child->copy_tree());
690  SG_UNREF(child);
691  }
692 
693  return copy;
694 }
695 
697 {
698  apply_to_modsel_parameter(machine->m_model_selection_parameters);
699 }
700 
702  Parameter* parameter) const
703 {
704  /* case root node */
705  if (!m_param)
706  {
707  /* iterate over all children and recursively set parameters from
708  * their values to the current parameter input (its just handed one
709  * recursion level downwards) */
710  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
711  {
713  m_child_nodes->get_element(i);
714  child->apply_to_modsel_parameter(parameter);
715  SG_UNREF(child);
716  }
717  }
718  /* case parameter node */
719  else if (m_param)
720  {
721  /* set parameters */
722  parameter->set_from_parameters(m_param);
723 
724  /* does this node has sub parameters? */
725  if (has_children())
726  {
727  /* if a parameter node has children, it has to have ONE CSGObject as
728  * parameter */
729  if (m_param->get_num_parameters()>1 ||
730  m_param->get_parameter(0)->m_datatype.m_ptype!=PT_SGOBJECT)
731  {
732  SG_SERROR("invalid CParameterCombination node type, has children"
733  " and more than one parameter or is not a "
734  "CSGObject.\n");
735  }
736 
737  /* cast is now safe */
738  CSGObject* current_sgobject=
739  *((CSGObject**)(m_param->get_parameter(0)->m_parameter));
740 
741  /* iterate over all children and recursively set parameters from
742  * their values */
743  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
744  {
746  m_child_nodes->get_element(i);
748  current_sgobject->m_model_selection_parameters);
749  SG_UNREF(child);
750  }
751  }
752  }
753  else
754  SG_SERROR("CParameterCombination node has illegal type.\n")
755 }
756 
759 {
760  if (m_param)
761  {
762  for (index_t i=0; i<m_param->get_num_parameters(); i++)
763  {
764  TParameter* param=m_param->get_parameter(i);
765  TSGDataType type=param->m_datatype;
766 
767  if (type.m_ptype==PT_FLOAT64 || type.m_ptype==PT_FLOAT32 ||
768  type.m_ptype==PT_FLOATMAX)
769  {
770  if ((type.m_ctype==CT_SGVECTOR || type.m_ctype==CT_VECTOR))
771  {
772  SGVector<float64_t> value(*((float64_t **)param->m_parameter),
773  (*type.m_length_y));
774  dict->add(param, value);
775  }
776  else if (type.m_ctype==CT_SCALAR)
777  {
778  SGVector<float64_t> value(1);
779  value.set_const(*((float64_t *)param->m_parameter));
780  dict->add(param, value);
781  }
782  }
783  }
784  }
785 
786  for (index_t i=0; i<m_child_nodes->get_num_elements(); i++)
787  {
789  m_child_nodes->get_element(i);
790  child->build_parameter_values_map(dict);
791  SG_UNREF(child);
792  }
793 }
794 
797 {
798  CSGObject* parent=NULL;
799 
800  if (m_param)
801  {
802  for (index_t i=0; i<m_param->get_num_parameters(); i++)
803  {
804  TParameter* param=m_param->get_parameter(i);
805  TSGDataType type=param->m_datatype;
806 
807  if (type.m_ptype==PT_SGOBJECT)
808  {
809  if (type.m_ctype==CT_SCALAR)
810  {
811  parent=(*(CSGObject**)param->m_parameter);
812  break;
813  }
814  else
815  {
817  }
818  }
819  }
820  }
821 
822  for (index_t i=0; i<m_child_nodes->get_num_elements(); i++)
823  {
825  m_child_nodes->get_element(i);
826 
827  for (index_t j=0; j<child->m_param->get_num_parameters(); j++)
828  {
829  TParameter* param=child->m_param->get_parameter(j);
830  TSGDataType type=param->m_datatype;
831 
832  if (type.m_ptype==PT_SGOBJECT)
833  {
834  if (type.m_ctype==CT_SCALAR)
835  {
836  child->build_parameter_parent_map(dict);
837  }
838  else
839  {
841  }
842  }
843  else
844  {
845  dict->add(param, parent);
846  }
847  }
848  SG_UNREF(child);
849  }
850 }

SHOGUN Machine Learning Toolbox - Documentation