SHOGUN  4.1.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  EContainerType ctype = m_param->get_parameter(i)->m_datatype.m_ctype;
312 
313  /* distinction between sgobject and values */
314  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
315  {
316  TParameter* param=m_param->get_parameter(i);
317  CSGObject* current_sgobject=*((CSGObject**) param->m_parameter);
318  SG_SPRINT("\"%s\":%s at %p ", param->m_name,
319  current_sgobject->get_name(), current_sgobject);
320  }
321  else if (ctype == CT_SGVECTOR || ctype == CT_VECTOR)
322  {
323  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name)
324  float64_t** param = (float64_t**)(m_param->
325  get_parameter(i)->m_parameter);
326  if (!m_param->get_parameter(i)->m_datatype.m_length_y)
327  {
328  SG_ERROR("Parameter vector %s has no length\n",
329  m_param->get_parameter(i)->m_name);
330  }
331 
332  index_t length = *(m_param->get_parameter(i)->m_datatype.m_length_y);
333 
334  for (index_t j = 0; j < length; j++)
335  SG_SPRINT("%f ", (*param)[j])
336  }
337 
338  else
339  {
340  SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name)
341  void* param=m_param->get_parameter(i)->m_parameter;
342 
343  if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_FLOAT64)
344  SG_SPRINT("%f ", *((float64_t*)param))
345  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_INT32)
346  SG_SPRINT("%i ", *((int32_t*)param))
347  else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_BOOL)
348  SG_SPRINT("%s ", *((bool*)param ? "true" : "false"))
349  else
351  }
352 
353  }
354 
355  }
356  else
357  SG_SPRINT("%sroot", prefix)
358 
359  SG_SPRINT("\n")
360 
361  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
362  {
364  m_child_nodes->get_element(i);
365  child->print_tree(prefix_num+1);
366  SG_UNREF(child);
367  }
368 
369  SG_FREE(prefix);
370 }
371 
373  const DynArray<Parameter*>& set_1, const DynArray<Parameter*>& set_2)
374 {
375  SG_SDEBUG("entering CParameterCombination::parameter_set_multiplication()\n")
376 
377  SG_SDEBUG("set 1:\n")
378  for (index_t i=0; i<set_1.get_num_elements(); ++i)
379  {
380  for (index_t j=0; j<set_1.get_element(i)->get_num_parameters(); ++j)
381  SG_SDEBUG("\t%s\n", set_1.get_element(i)->get_parameter(j)->m_name)
382  }
383 
384  SG_SDEBUG("set 2:\n")
385  for (index_t i=0; i<set_2.get_num_elements(); ++i)
386  {
387  for (index_t j=0; j<set_2.get_element(i)->get_num_parameters(); ++j)
388  SG_SDEBUG("\t%s\n", set_2.get_element(i)->get_parameter(j)->m_name)
389  }
390 
392 
393  for (index_t i=0; i<set_1.get_num_elements(); ++i)
394  {
395  for (index_t j=0; j<set_2.get_num_elements(); ++j)
396  {
397  Parameter* p=new Parameter();
398  p->add_parameters(set_1[i]);
399  p->add_parameters(set_2[j]);
400  result->append_element(p);
401  }
402  }
403 
404  SG_SDEBUG("leaving CParameterCombination::parameter_set_multiplication()\n")
405  return result;
406 }
407 
409  const CDynamicObjectArray& sets, const CParameterCombination* new_root)
410 {
412 
413  /* check marginal cases */
414  if (sets.get_num_elements()==1)
415  {
416  CDynamicObjectArray* current_set=
418 
419  /* just use the only element into result array.
420  * put root node before all combinations*/
421  *result=*current_set;
422 
423  SG_UNREF(current_set);
424 
425  for (index_t i=0; i<result->get_num_elements(); ++i)
426  {
427  /* put new root as root into the tree and replace tree */
429  result->get_element(i);
430  CParameterCombination* root=new_root->copy_tree();
431  root->append_child(current);
432  result->set_element(root, i);
433  SG_UNREF(current);
434  }
435  }
436  else if (sets.get_num_elements()>1)
437  {
438  /* now the case where at least two sets are given */
439 
440  /* first, extract Parameter instances of given sets */
441  DynArray<DynArray<Parameter*>*> param_sets;
442 
443  for (index_t set_nr=0; set_nr<sets.get_num_elements(); ++set_nr)
444  {
446  sets.get_element(set_nr);
447  DynArray<Parameter*>* new_param_set=new DynArray<Parameter*> ();
448  param_sets.append_element(new_param_set);
449 
450  for (index_t i=0; i<current_set->get_num_elements(); ++i)
451  {
453  current_set->get_element(i);
454 
455  if (current_node->m_child_nodes->get_num_elements())
456  {
457  SG_SERROR("leaf sets multiplication only possible if all "
458  "trees are leafs");
459  }
460 
461  Parameter* current_param=current_node->m_param;
462 
463  if (current_param)
464  new_param_set->append_element(current_param);
465  else
466  {
467  SG_SERROR("leaf sets multiplication only possible if all "
468  "leafs have non-NULL Parameter instances\n");
469  }
470 
471  SG_UNREF(current_node);
472  }
473 
474  SG_UNREF(current_set);
475  }
476 
477  /* second, build products of all parameter sets */
478  DynArray<Parameter*>* param_product=parameter_set_multiplication(
479  *param_sets[0], *param_sets[1]);
480 
481  delete param_sets[0];
482  delete param_sets[1];
483 
484  /* build product of all remaining sets and collect results. delete all
485  * parameter instances of interim products*/
486  for (index_t i=2; i<param_sets.get_num_elements(); ++i)
487  {
488  DynArray<Parameter*>* old_temp_result=param_product;
489  param_product=parameter_set_multiplication(*param_product,
490  *param_sets[i]);
491 
492  /* delete interim result parameter instances */
493  for (index_t j=0; j<old_temp_result->get_num_elements(); ++j)
494  delete old_temp_result->get_element(j);
495 
496  /* and dyn arrays of interim result and of param_sets */
497  delete old_temp_result;
498  delete param_sets[i];
499  }
500 
501  /* at this point there is only one DynArray instance remaining:
502  * param_product. contains all combinations of parameters of all given
503  * sets */
504 
505  /* third, build tree sets with the given root and the parameter product
506  * elements */
507  for (index_t i=0; i<param_product->get_num_elements(); ++i)
508  {
509  /* build parameter node from parameter product to append to root */
511  param_product->get_element(i));
512 
513  /* copy new root node, has to be a new one each time */
514  CParameterCombination* root=new_root->copy_tree();
515 
516  /* append both and add them to result set */
517  root->append_child(param_node);
518  result->append_element(root);
519  }
520 
521  /* this is not needed anymore, because the Parameter instances are now
522  * in the resulting tree sets */
523  delete param_product;
524  }
525 
526  return result;
527 }
528 
530  const CDynamicObjectArray* sets,
531  const CParameterCombination* new_root)
532 {
533  SG_SDEBUG("entering CParameterCombination::non_value_tree_multiplication()\n")
535 
536  /* first step: get all names in the sets */
537  set<string> names;
538 
539  for (index_t j=0;
540  j<sets->get_num_elements(); ++j)
541  {
542  CDynamicObjectArray* current_set=
544  sets->get_element(j);
545 
546  for (index_t k=0; k
547  <current_set->get_num_elements(); ++k)
548  {
550  current_set->get_element(k);
551 
552  names.insert(string(current_tree->m_param->get_parameter(0)->m_name));
553 
554  SG_UNREF(current_tree);
555  }
556 
557  SG_UNREF(current_set);
558  }
559 
560  SG_SDEBUG("all names\n")
561  for (set<string>::iterator it=names.begin(); it!=names.end(); ++it)
562  SG_SDEBUG("\"%s\"\n", (*it).c_str())
563 
564  /* only do stuff if there are names */
565  if (!names.empty())
566  {
567  /* next step, build temporary structure where all elements with first
568  * name are put. Elements of that structure will be extend iteratively
569  * per name */
570 
571 
572  /* extract all trees with first name */
573  const char* first_name=(*(names.begin())).c_str();
574  CDynamicObjectArray* trees=
576 
577  SG_SDEBUG("adding trees for first name \"%s\":\n", first_name)
578  for (index_t i=0; i<trees->get_num_elements(); ++i)
579  {
580  CParameterCombination* current_tree=
582 
583  CParameterCombination* current_root=new_root->copy_tree();
584  current_root->append_child(current_tree);
585  result->append_element(current_root);
586 
587  // current_tree->print_tree(1);
588  SG_UNREF(current_tree);
589  }
590  SG_UNREF(trees);
591 
592  /* now iterate over the remaining names and build products */
593  SG_SDEBUG("building products with remaining trees:\n")
594  set<string>::iterator it=names.begin();
595  for (++it; it!=names.end(); ++it)
596  {
597  SG_SDEBUG("processing \"%s\"\n", (*it).c_str())
598 
599  /* extract all trees with current name */
600  const char* current_name=(*it).c_str();
602  current_name);
603 
604  /* create new set of trees where each element is put once for each
605  * of the just generated trees */
606  CDynamicObjectArray* new_result=new CDynamicObjectArray();
607  for (index_t i=0; i<result->get_num_elements(); ++i)
608  {
609  for (index_t j=0; j<trees->get_num_elements(); ++j)
610  {
611  CParameterCombination* to_copy=
612  (CParameterCombination*)result->get_element(i);
613 
614  /* create a copy of current element */
615  CParameterCombination* new_element=to_copy->copy_tree();
616  SG_UNREF(to_copy);
617 
618  CParameterCombination* to_add=
620  new_element->append_child(to_add);
621  SG_UNREF(to_add);
622  new_result->append_element(new_element);
623  // SG_SDEBUG("added:\n")
624  // new_element->print_tree();
625  }
626  }
627 
628  /* clean up */
629  SG_UNREF(trees);
630 
631  /* replace result by new_result */
632  SG_UNREF(result);
633  result=new_result;
634  }
635  }
636 
637  SG_SDEBUG("leaving CParameterCombination::non_value_tree_multiplication()\n")
638  return result;
639 }
640 
642  const CDynamicObjectArray* sets, const char* desired_name)
643 {
645 
646  for (index_t j=0;
647  j<sets->get_num_elements(); ++j)
648  {
649  CDynamicObjectArray* current_set=
650  (CDynamicObjectArray*) sets->get_element(j);
651 
652  for (index_t k=0; k<current_set->get_num_elements(); ++k)
653  {
655  current_set->get_element(k);
656 
657  char* current_name=current_tree->m_param->get_parameter(0)->m_name;
658 
659  if (!strcmp(current_name, desired_name))
660  result->append_element(current_tree);
661 
662  SG_UNREF(current_tree);
663  }
664 
665  SG_UNREF(current_set);
666  }
667 
668  return result;
669 }
670 
672 {
674 
675  /* but build new Parameter instance */
676 
677  /* only call add_parameters() argument is non-null */
678  if (m_param)
679  {
680  copy->m_param=new Parameter();
681  copy->m_param->add_parameters(m_param);
682  } else
683  copy->m_param=NULL;
684 
685  /* recursively copy all children */
686  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
687  {
689  m_child_nodes->get_element(i);
690  copy->m_child_nodes->append_element(child->copy_tree());
691  SG_UNREF(child);
692  }
693 
694  return copy;
695 }
696 
698 {
699  apply_to_modsel_parameter(machine->m_model_selection_parameters);
700 }
701 
703  Parameter* parameter) const
704 {
705  /* case root node */
706  if (!m_param)
707  {
708  /* iterate over all children and recursively set parameters from
709  * their values to the current parameter input (its just handed one
710  * recursion level downwards) */
711  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
712  {
714  m_child_nodes->get_element(i);
715  child->apply_to_modsel_parameter(parameter);
716  SG_UNREF(child);
717  }
718  }
719  /* case parameter node */
720  else if (m_param)
721  {
722  /* set parameters */
723  parameter->set_from_parameters(m_param);
724 
725  /* does this node has sub parameters? */
726  if (has_children())
727  {
728  /* if a parameter node has children, it has to have ONE CSGObject as
729  * parameter */
730  if (m_param->get_num_parameters()>1 ||
731  m_param->get_parameter(0)->m_datatype.m_ptype!=PT_SGOBJECT)
732  {
733  SG_SERROR("invalid CParameterCombination node type, has children"
734  " and more than one parameter or is not a "
735  "CSGObject.\n");
736  }
737 
738  /* cast is now safe */
739  CSGObject* current_sgobject=
740  *((CSGObject**)(m_param->get_parameter(0)->m_parameter));
741 
742  /* iterate over all children and recursively set parameters from
743  * their values */
744  for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
745  {
747  m_child_nodes->get_element(i);
749  current_sgobject->m_model_selection_parameters);
750  SG_UNREF(child);
751  }
752  }
753  }
754  else
755  SG_SERROR("CParameterCombination node has illegal type.\n")
756 }
757 
760 {
761  if (m_param)
762  {
763  for (index_t i=0; i<m_param->get_num_parameters(); i++)
764  {
765  TParameter* param=m_param->get_parameter(i);
766  TSGDataType type=param->m_datatype;
767 
768  if (type.m_ptype==PT_FLOAT64 || type.m_ptype==PT_FLOAT32 ||
769  type.m_ptype==PT_FLOATMAX)
770  {
771  if ((type.m_ctype==CT_SGVECTOR || type.m_ctype==CT_VECTOR))
772  {
773  SGVector<float64_t> value(*((float64_t **)param->m_parameter),
774  (*type.m_length_y));
775  dict->add(param, value);
776  }
777  else if (type.m_ctype==CT_SCALAR)
778  {
779  SGVector<float64_t> value(1);
780  value.set_const(*((float64_t *)param->m_parameter));
781  dict->add(param, value);
782  }
783  }
784  }
785  }
786 
787  for (index_t i=0; i<m_child_nodes->get_num_elements(); i++)
788  {
790  m_child_nodes->get_element(i);
791  child->build_parameter_values_map(dict);
792  SG_UNREF(child);
793  }
794 }
795 
798 {
799  CSGObject* parent=NULL;
800 
801  if (m_param)
802  {
803  for (index_t i=0; i<m_param->get_num_parameters(); i++)
804  {
805  TParameter* param=m_param->get_parameter(i);
806  TSGDataType type=param->m_datatype;
807 
808  if (type.m_ptype==PT_SGOBJECT)
809  {
810  if (type.m_ctype==CT_SCALAR)
811  {
812  parent=(*(CSGObject**)param->m_parameter);
813  break;
814  }
815  else
816  {
818  }
819  }
820  }
821  }
822 
823  for (index_t i=0; i<m_child_nodes->get_num_elements(); i++)
824  {
826  m_child_nodes->get_element(i);
827 
828  for (index_t j=0; j<child->m_param->get_num_parameters(); j++)
829  {
830  TParameter* param=child->m_param->get_parameter(j);
831  TSGDataType type=param->m_datatype;
832 
833  if (type.m_ptype==PT_SGOBJECT)
834  {
835  if (type.m_ctype==CT_SCALAR)
836  {
837  child->build_parameter_parent_map(dict);
838  }
839  else
840  {
842  }
843  }
844  else
845  {
846  dict->add(param, parent);
847  }
848  }
849  SG_UNREF(child);
850  }
851 }

SHOGUN Machine Learning Toolbox - Documentation