SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SGObject.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) 2008-2009 Soeren Sonnenburg
8  * Written (W) 2011-2013 Heiko Strathmann
9  * Written (W) 2013 Thoralf Klein
10  * Copyright (C) 2008-2009 Fraunhofer Institute FIRST and Max Planck Society
11  */
12 
13 #include <shogun/lib/config.h>
14 #include <shogun/base/SGObject.h>
15 #include <shogun/io/SGIO.h>
16 #include <shogun/base/Parallel.h>
17 #include <shogun/base/init.h>
18 #include <shogun/base/Version.h>
19 #include <shogun/base/Parameter.h>
21 #include <shogun/base/DynArray.h>
22 #include <shogun/lib/Map.h>
24 
25 #include "class_list.h"
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 
30 namespace shogun
31 {
32  class CMath;
33  class Parallel;
34  class IO;
35  class Version;
36 
37  extern Parallel* sg_parallel;
38  extern SGIO* sg_io;
39  extern Version* sg_version;
40 
41  template<> void CSGObject::set_generic<bool>()
42  {
43  m_generic = PT_BOOL;
44  }
45 
46  template<> void CSGObject::set_generic<char>()
47  {
48  m_generic = PT_CHAR;
49  }
50 
51  template<> void CSGObject::set_generic<int8_t>()
52  {
53  m_generic = PT_INT8;
54  }
55 
56  template<> void CSGObject::set_generic<uint8_t>()
57  {
58  m_generic = PT_UINT8;
59  }
60 
61  template<> void CSGObject::set_generic<int16_t>()
62  {
63  m_generic = PT_INT16;
64  }
65 
66  template<> void CSGObject::set_generic<uint16_t>()
67  {
68  m_generic = PT_UINT16;
69  }
70 
71  template<> void CSGObject::set_generic<int32_t>()
72  {
73  m_generic = PT_INT32;
74  }
75 
76  template<> void CSGObject::set_generic<uint32_t>()
77  {
78  m_generic = PT_UINT32;
79  }
80 
81  template<> void CSGObject::set_generic<int64_t>()
82  {
83  m_generic = PT_INT64;
84  }
85 
86  template<> void CSGObject::set_generic<uint64_t>()
87  {
88  m_generic = PT_UINT64;
89  }
90 
91  template<> void CSGObject::set_generic<float32_t>()
92  {
93  m_generic = PT_FLOAT32;
94  }
95 
96  template<> void CSGObject::set_generic<float64_t>()
97  {
98  m_generic = PT_FLOAT64;
99  }
100 
101  template<> void CSGObject::set_generic<floatmax_t>()
102  {
103  m_generic = PT_FLOATMAX;
104  }
105 
106  template<> void CSGObject::set_generic<CSGObject*>()
107  {
108  m_generic = PT_SGOBJECT;
109  }
110 
111  template<> void CSGObject::set_generic<complex128_t>()
112  {
113  m_generic = PT_COMPLEX128;
114  }
115 
116 } /* namespace shogun */
117 
118 using namespace shogun;
119 
121 : SGRefObject()
122 {
123  init();
124  set_global_objects();
125 }
126 
128 :SGRefObject(orig), io(orig.io), parallel(orig.parallel), version(orig.version)
129 {
130  init();
131  set_global_objects();
132 }
133 
135 {
136  unset_global_objects();
137  delete m_parameters;
139  delete m_gradient_parameters;
140  delete m_parameter_map;
141 }
142 
143 void CSGObject::set_global_objects()
144 {
145  if (!sg_io || !sg_parallel || !sg_version)
146  {
147  fprintf(stderr, "call init_shogun() before using the library, dying.\n");
148  exit(1);
149  }
150 
151  SG_REF(sg_io);
154 
155  io=sg_io;
158 }
159 
160 void CSGObject::unset_global_objects()
161 {
162  SG_UNREF(version);
164  SG_UNREF(io);
165 }
166 
168 {
169  SG_REF(new_io);
170  SG_UNREF(sg_io);
171  sg_io=new_io;
172 }
173 
175 {
176  SG_REF(sg_io);
177  return sg_io;
178 }
179 
181 {
182  SG_REF(new_parallel);
184  sg_parallel=new_parallel;
185 }
186 
188 {
189  SG_DEBUG("entering\n")
190 
191  uint32_t carry=0;
192  uint32_t length=0;
193 
194  get_parameter_incremental_hash(m_hash, carry, length);
196 
197  SG_DEBUG("leaving\n")
198 }
199 
201 {
202  SG_DEBUG("entering\n")
203 
204  uint32_t hash=0;
205  uint32_t carry=0;
206  uint32_t length=0;
207 
208  get_parameter_incremental_hash(hash, carry, length);
209  hash=CHash::FinalizeIncrementalMurmurHash3(hash, carry, length);
210 
211  SG_DEBUG("leaving\n")
212  return (m_hash!=hash);
213 }
214 
216 {
218  return sg_parallel;
219 }
220 
222 {
223  SG_REF(new_version);
225  sg_version=new_version;
226 }
227 
229 {
231  return sg_version;
232 }
233 
234 bool CSGObject::is_generic(EPrimitiveType* generic) const
235 {
236  *generic = m_generic;
237 
238  return m_generic != PT_NOT_GENERIC;
239 }
240 
242 {
243  m_generic = PT_NOT_GENERIC;
244 }
245 
246 void CSGObject::print_serializable(const char* prefix)
247 {
248  SG_PRINT("\n%s\n================================================================================\n", get_name())
249  m_parameters->print(prefix);
250 }
251 
253  const char* prefix, int32_t param_version)
254 {
255  SG_DEBUG("START SAVING CSGObject '%s'\n", get_name())
256  try
257  {
259  }
260  catch (ShogunException& e)
261  {
262  SG_SWARNING("%s%s::save_serializable_pre(): ShogunException: "
263  "%s\n", prefix, get_name(),
265  return false;
266  }
267 
268  if (!m_save_pre_called)
269  {
270  SG_SWARNING("%s%s::save_serializable_pre(): Implementation "
271  "error: BASE_CLASS::LOAD_SERIALIZABLE_PRE() not "
272  "called!\n", prefix, get_name());
273  return false;
274  }
275 
276  /* save parameter version */
277  if (!save_parameter_version(file, prefix, param_version))
278  return false;
279 
280  if (!m_parameters->save(file, prefix))
281  return false;
282 
283  try
284  {
286  }
287  catch (ShogunException& e)
288  {
289  SG_SWARNING("%s%s::save_serializable_post(): ShogunException: "
290  "%s\n", prefix, get_name(),
292  return false;
293  }
294 
295  if (!m_save_post_called)
296  {
297  SG_SWARNING("%s%s::save_serializable_post(): Implementation "
298  "error: BASE_CLASS::LOAD_SERIALIZABLE_POST() not "
299  "called!\n", prefix, get_name());
300  return false;
301  }
302 
303  if (prefix == NULL || *prefix == '\0')
304  file->close();
305 
306  SG_DEBUG("DONE SAVING CSGObject '%s' (%p)\n", get_name(), this)
307 
308  return true;
309 }
310 
312  const char* prefix, int32_t param_version)
313 {
314  SG_DEBUG("START LOADING CSGObject '%s'\n", get_name())
315  try
316  {
318  }
319  catch (ShogunException& e)
320  {
321  SG_SWARNING("%s%s::load_serializable_pre(): ShogunException: "
322  "%s\n", prefix, get_name(),
324  return false;
325  }
326  if (!m_load_pre_called)
327  {
328  SG_SWARNING("%s%s::load_serializable_pre(): Implementation "
329  "error: BASE_CLASS::LOAD_SERIALIZABLE_PRE() not "
330  "called!\n", prefix, get_name());
331  return false;
332  }
333 
334  /* try to load version of parameters */
335  int32_t file_version=load_parameter_version(file, prefix);
336  SG_DEBUG("file_version=%d, current_version=%d\n", file_version, param_version)
337 
338  if (file_version<0)
339  {
340  SG_WARNING("%s%s::load_serializable(): File contains no parameter "
341  "version. Seems like your file is from the days before this "
342  "was introduced. Ignore warning or serialize with this version "
343  "of shogun to get rid of above and this warnings.\n",
344  prefix, get_name());
345  }
346 
347  if (file_version>param_version)
348  {
349  if (param_version==Version::get_version_parameter())
350  {
351  SG_WARNING("%s%s::load_serializable(): parameter version of file "
352  "larger than the one of shogun. Try with a more recent"
353  "version of shogun.\n", prefix, get_name());
354  }
355  else
356  {
357  SG_WARNING("%s%s::load_serializable(): parameter version of file "
358  "larger than the current. This is probably an implementation"
359  " error.\n", prefix, get_name());
360  }
361  return false;
362  }
363 
364  if (file_version==param_version)
365  {
366  /* load normally if file has current version */
367  SG_DEBUG("loading normally\n")
368 
369  /* load all parameters, except new ones */
370  for (int32_t i=0; i<m_parameters->get_num_parameters(); i++)
371  {
373 
374  /* skip new parameters */
375  if (is_param_new(SGParamInfo(current, param_version)))
376  continue;
377 
378  if (!current->load(file, prefix))
379  return false;
380  }
381  }
382  else
383  {
384  /* load all parameters from file, mappings to current version */
385  DynArray<TParameter*>* param_base=load_all_file_parameters(file_version,
386  param_version, file, prefix);
387 
388  /* create an array of param infos from current parameters */
389  DynArray<const SGParamInfo*>* param_infos=
391  for (index_t i=0; i<m_parameters->get_num_parameters(); ++i)
392  {
394 
395  /* skip new parameters */
396  if (is_param_new(SGParamInfo(current, param_version)))
397  continue;
398 
399  param_infos->append_element(
400  new SGParamInfo(current, param_version));
401  }
402 
403  /* map all parameters, result may be empty if input is */
404  map_parameters(param_base, file_version, param_infos);
405  SG_DEBUG("mapping is done!\n")
406 
407  /* this is assumed now, mapping worked or no parameters in base */
408  ASSERT(file_version==param_version || !param_base->get_num_elements())
409 
410  /* delete above created param infos */
411  for (index_t i=0; i<param_infos->get_num_elements(); ++i)
412  delete param_infos->get_element(i);
413 
414  delete param_infos;
415 
416  /* replace parameters by loaded and mapped */
417  SG_DEBUG("replacing parameter data by loaded/mapped values\n")
418  for (index_t i=0; i<m_parameters->get_num_parameters(); ++i)
419  {
421  char* s=SG_MALLOC(char, 200);
422  current->m_datatype.to_string(s, 200);
423  SG_DEBUG("processing \"%s\": %s\n", current->m_name, s)
424  SG_FREE(s);
425 
426  /* skip new parameters */
427  if (is_param_new(SGParamInfo(current, param_version)))
428  {
429  SG_DEBUG("%s is new, skipping\n", current->m_name)
430  continue;
431  }
432 
433  /* search for current parameter in mapped ones */
434  index_t index=CMath::binary_search(param_base->get_array(),
435  param_base->get_num_elements(), current);
436 
437  TParameter* migrated=param_base->get_element(index);
438 
439  /* now copy data from migrated TParameter instance
440  * (this automatically deletes the old data allocations) */
441  SG_DEBUG("copying migrated data into parameter\n")
442  current->copy_data(migrated);
443  }
444 
445  /* delete the migrated parameter data base */
446  SG_DEBUG("deleting old parameter base\n")
447  for (index_t i=0; i<param_base->get_num_elements(); ++i)
448  {
449  TParameter* current=param_base->get_element(i);
450  SG_DEBUG("deleting old \"%s\"\n", current->m_name)
451  delete current;
452  }
453  delete param_base;
454  }
455 
456  try
457  {
459  }
460  catch (ShogunException& e)
461  {
462  SG_SWARNING("%s%s::load_serializable_post(): ShogunException: "
463  "%s\n", prefix, get_name(),
465  return false;
466  }
467 
468  if (!m_load_post_called)
469  {
470  SG_SWARNING("%s%s::load_serializable_post(): Implementation "
471  "error: BASE_CLASS::LOAD_SERIALIZABLE_POST() not "
472  "called!\n", prefix, get_name());
473  return false;
474  }
475  SG_DEBUG("DONE LOADING CSGObject '%s' (%p)\n", get_name(), this)
476 
477  return true;
478 }
479 
481  const SGParamInfo* param_info, int32_t file_version,
482  CSerializableFile* file, const char* prefix)
483 {
484  /* ensure that recursion works */
485  SG_SDEBUG("entering %s::load_file_parameters\n", get_name())
486  if (file_version>param_info->m_param_version)
487  {
488  SG_SERROR("parameter version of \"%s\" in file (%d) is more recent than"
489  " provided %d!\n", param_info->m_name, file_version,
490  param_info->m_param_version);
491  }
492 
493  DynArray<TParameter*>* result_array=new DynArray<TParameter*>();
494 
495  /* do mapping */
496  char* s=param_info->to_string();
497  SG_SDEBUG("try to get mapping for: %s\n", s)
498  SG_FREE(s);
499 
500  /* mapping has only be deleted if was created here (no mapping was found) */
501  bool free_mapped=false;
502  DynArray<const SGParamInfo*>* mapped=m_parameter_map->get(param_info);
503  if (!mapped)
504  {
505  /* since a new mapped array will be created, set deletion flag */
506  free_mapped=true;
507  mapped=new DynArray<const SGParamInfo*>();
508 
509  /* if no mapping was found, nothing has changed. Simply create new param
510  * info with decreased version */
511  SG_SDEBUG("no mapping found\n")
512  if (file_version<param_info->m_param_version)
513  {
514  /* create new array and put param info with decreased version in */
515  mapped->append_element(new SGParamInfo(param_info->m_name,
516  param_info->m_ctype, param_info->m_stype,
517  param_info->m_ptype, param_info->m_param_version-1));
518 
519  SG_SDEBUG("using:\n")
520  for (index_t i=0; i<mapped->get_num_elements(); ++i)
521  {
522  s=mapped->get_element(i)->to_string();
523  SG_SDEBUG("\t%s\n", s)
524  SG_FREE(s);
525  }
526  }
527  else
528  {
529  /* create new array and put original param info in */
530  SG_SDEBUG("reached file version\n")
531  mapped->append_element(param_info->duplicate());
532  }
533  }
534  else
535  {
536  SG_SDEBUG("found:\n")
537  for (index_t i=0; i<mapped->get_num_elements(); ++i)
538  {
539  s=mapped->get_element(i)->to_string();
540  SG_SDEBUG("\t%s\n", s)
541  SG_FREE(s);
542  }
543  }
544 
545 
546  /* case file version same as provided version.
547  * means that parameters have to be loaded from file, recursion stops */
548  if (file_version==param_info->m_param_version)
549  {
550  SG_SDEBUG("recursion stop, loading from file\n")
551  /* load all parameters in mapping from file */
552  for (index_t i=0; i<mapped->get_num_elements(); ++i)
553  {
554  const SGParamInfo* current=mapped->get_element(i);
555  s=current->to_string();
556  SG_SDEBUG("loading %s\n", s)
557  SG_FREE(s);
558 
559  TParameter* loaded;
560  /* allocate memory for length and matrix/vector
561  * This has to be done because this stuff normally is in the class
562  * variables which do not exist in this case. Deletion is handled
563  * via the allocated_from_scratch flag of TParameter */
564 
565  /* create type and copy lengths, empty data for now */
566  TSGDataType type(current->m_ctype, current->m_stype,
567  current->m_ptype);
568  loaded=new TParameter(&type, NULL, current->m_name, "");
569 
570  /* allocate data/length variables for the TParameter, lengths are not
571  * important now, so set to one */
572  SGVector<index_t> dims(2);
573  dims[0]=1;
574  dims[1]=1;
575  loaded->allocate_data_from_scratch(dims);
576 
577  /* tell instance to load data from file */
578  if (!loaded->load(file, prefix))
579  {
580  s=param_info->to_string();
581  SG_ERROR("Could not load %s. The reason for this might be wrong "
582  "parameter mappings\n", s);
583  SG_FREE(s);
584  }
585 
586  SG_DEBUG("loaded lengths: y=%d, x=%d\n",
587  loaded->m_datatype.m_length_y ? *loaded->m_datatype.m_length_y : -1,
588  loaded->m_datatype.m_length_x ? *loaded->m_datatype.m_length_x : -1);
589 
590  /* append new TParameter to result array */
591  result_array->append_element(loaded);
592  }
593  SG_SDEBUG("done loading from file\n")
594  }
595  /* recursion with mapped type, a mapping exists in this case (ensured by
596  * above assert) */
597  else
598  {
599  /* for all elements in mapping, do recursion */
600  for (index_t i=0; i<mapped->get_num_elements(); ++i)
601  {
602  const SGParamInfo* current=mapped->get_element(i);
603  s=current->to_string();
604  SG_SDEBUG("starting recursion over %s\n", s)
605 
606  /* recursively get all file parameters for this parameter */
607  DynArray<TParameter*>* recursion_array=
608  load_file_parameters(current, file_version, file, prefix);
609 
610  SG_SDEBUG("recursion over %s done\n", s)
611  SG_FREE(s);
612 
613  /* append all recursion data to current array */
614  SG_SDEBUG("appending all results to current result\n")
615  for (index_t j=0; j<recursion_array->get_num_elements(); ++j)
616  result_array->append_element(recursion_array->get_element(j));
617 
618  /* clean up */
619  delete recursion_array;
620  }
621  }
622 
623  SG_SDEBUG("cleaning up old mapping \n")
624 
625 
626  /* clean up mapping */
627  if (free_mapped)
628  {
629  for (index_t i=0; i<mapped->get_num_elements(); ++i)
630  delete mapped->get_element(i);
631 
632  delete mapped;
633  }
634 
635  SG_SDEBUG("leaving %s::load_file_parameters\n", get_name())
636  return result_array;
637 }
638 
640  int32_t current_version, CSerializableFile* file, const char* prefix)
641 {
643 
644  for (index_t i=0; i<m_parameters->get_num_parameters(); ++i)
645  {
647 
648  /* extract current parameter info */
649  const SGParamInfo* info=new SGParamInfo(current, current_version);
650 
651  /* skip new parameters */
652  if (is_param_new(*info))
653  {
654  delete info;
655  continue;
656  }
657 
658  /* in the other case, load parameters data from file */
659  DynArray<TParameter*>* temp=load_file_parameters(info, file_version,
660  file, prefix);
661 
662  /* and append them all to array */
663  for (index_t j=0; j<temp->get_num_elements(); ++j)
664  result->append_element(temp->get_element(j));
665 
666  /* clean up */
667  delete temp;
668  delete info;
669  }
670 
671  /* sort array before returning */
672  CMath::qsort(result->get_array(), result->get_num_elements());
673 
674  return result;
675 }
676 
678  int32_t& base_version, DynArray<const SGParamInfo*>* target_param_infos)
679 {
680  SG_DEBUG("entering %s::map_parameters\n", get_name())
681  /* NOTE: currently the migration is done step by step over every version */
682 
683  if (!target_param_infos->get_num_elements())
684  {
685  SG_DEBUG("no target parameter infos\n")
686  SG_DEBUG("leaving %s::map_parameters\n", get_name())
687  return;
688  }
689 
690  /* map all target parameter infos once */
691  DynArray<const SGParamInfo*>* mapped_infos=
694  for (index_t i=0; i<target_param_infos->get_num_elements(); ++i)
695  {
696  const SGParamInfo* current=target_param_infos->get_element(i);
697 
698  char* s=current->to_string();
699  SG_DEBUG("trying to get parameter mapping for %s\n", s)
700  SG_FREE(s);
701 
703 
704  if (mapped)
705  {
706  mapped_infos->append_element(mapped->get_element(0));
707  for (index_t j=0; j<mapped->get_num_elements(); ++j)
708  {
709  s=mapped->get_element(j)->to_string();
710  SG_DEBUG("found mapping: %s\n", s)
711  SG_FREE(s);
712  }
713  }
714  else
715  {
716  /* these have to be deleted above */
717  SGParamInfo* no_change=new SGParamInfo(*current);
718  no_change->m_param_version--;
719  s=no_change->to_string();
720  SG_DEBUG("no mapping found, using %s\n", s)
721  SG_FREE(s);
722  mapped_infos->append_element(no_change);
723  to_delete->append_element(no_change);
724  }
725  }
726 
727  /* assert that at least one mapping exists */
728  ASSERT(mapped_infos->get_num_elements())
729  int32_t mapped_version=mapped_infos->get_element(0)->m_param_version;
730 
731  /* assert that all param versions are equal for now (if not empty param) */
732  for (index_t i=1; i<mapped_infos->get_num_elements(); ++i)
733  {
734  ASSERT(mapped_infos->get_element(i)->m_param_version==mapped_version ||
735  *mapped_infos->get_element(i)==SGParamInfo());
736  }
737 
738  /* recursion, after this call, base is at version of mapped infos */
739  if (mapped_version>base_version)
740  map_parameters(param_base, base_version, mapped_infos);
741 
742  /* delete mapped parameter infos array */
743  delete mapped_infos;
744 
745  /* delete newly created parameter infos which have to name or type change */
746  for (index_t i=0; i<to_delete->get_num_elements(); ++i)
747  delete to_delete->get_element(i);
748 
749  delete to_delete;
750 
751  ASSERT(base_version==mapped_version)
752 
753  /* do migration of one version step, create new base */
755  for (index_t i=0; i<target_param_infos->get_num_elements(); ++i)
756  {
757  char* s=target_param_infos->get_element(i)->to_string();
758  SG_DEBUG("migrating one step to target: %s\n", s)
759  SG_FREE(s);
760  TParameter* p=migrate(param_base, target_param_infos->get_element(i));
761  new_base->append_element(p);
762  }
763 
764  /* replace base by new base, delete old base, if it was created in migrate */
765  SG_DEBUG("deleting parameters base version %d\n", base_version)
766  for (index_t i=0; i<param_base->get_num_elements(); ++i)
767  delete param_base->get_element(i);
768 
769  SG_DEBUG("replacing old parameter base\n")
770  *param_base=*new_base;
771  base_version=mapped_version+1;
772 
773  SG_DEBUG("new parameter base of size %d:\n", param_base->get_num_elements())
774  for (index_t i=0; i<param_base->get_num_elements(); ++i)
775  {
776  TParameter* current=param_base->get_element(i);
777  TSGDataType type=current->m_datatype;
778  if (type.m_ptype==PT_SGOBJECT)
779  {
780  if (type.m_ctype==CT_SCALAR)
781  {
782  CSGObject* object=*(CSGObject**)current->m_parameter;
783  SG_DEBUG("(%d:) \"%s\": sgobject \"%s\" at %p\n", i,
784  current->m_name, object ? object->get_name() : "",
785  object);
786  }
787  else
788  {
789  index_t len=1;
790  len*=type.m_length_x ? *type.m_length_x : 1;
791  len*=type.m_length_y ? *type.m_length_y : 1;
792  CSGObject** array=*(CSGObject***)current->m_parameter;
793  for (index_t j=0; j<len; ++j)
794  {
795  CSGObject* object=array[j];
796  SG_DEBUG("(%d:) \"%s\": sgobject \"%s\" at %p\n", i,
797  current->m_name, object ? object->get_name() : "",
798  object);
799  }
800  }
801  }
802  else
803  {
804  char* s=SG_MALLOC(char, 200);
805  current->m_datatype.to_string(s, 200);
806  SG_DEBUG("(%d:) \"%s\": type: %s at %p\n", i, current->m_name, s,
807  current->m_parameter);
808  SG_FREE(s);
809  }
810  }
811 
812  /* because content was copied, new base may be deleted */
813  delete new_base;
814 
815  /* sort the just created new base */
816  SG_DEBUG("sorting base\n")
817  CMath::qsort(param_base->get_array(), param_base->get_num_elements());
818 
819  /* at this point the param_base is at the same version as the version of
820  * the provided parameter infos */
821  SG_DEBUG("leaving %s::map_parameters\n", get_name())
822 }
823 
825  const SGParamInfo* target, TParameter*& replacement,
826  TParameter*& to_migrate, char* old_name)
827 {
828  SG_DEBUG("CSGObject::entering CSGObject::one_to_one_migration_prepare() for "
829  "\"%s\"\n", target->m_name);
830 
831  /* generate type of target structure */
832  TSGDataType type(target->m_ctype, target->m_stype, target->m_ptype);
833 
834  /* first find index of needed data.
835  * in this case, element in base with same name or old name */
836  char* name=target->m_name;
837  if (old_name)
838  name=old_name;
839 
840  /* dummy for searching, search and save result in to_migrate parameter */
841  TParameter* t=new TParameter(&type, NULL, name, "");
842  index_t i=CMath::binary_search(param_base->get_array(),
843  param_base->get_num_elements(), t);
844  delete t;
845 
846  /* assert that something is found */
847  ASSERT(i>=0)
848  to_migrate=param_base->get_element(i);
849 
850  /* result structure, data NULL for now */
851  replacement=new TParameter(&type, NULL, target->m_name,
852  to_migrate->m_description);
853 
854  SGVector<index_t> dims(2);
855  dims[0]=1;
856  dims[1]=1;
857  /* allocate content to write into, lengths are needed for this */
858  if (to_migrate->m_datatype.m_length_x)
859  dims[0]=*to_migrate->m_datatype.m_length_x;
860 
861  if (to_migrate->m_datatype.m_length_y)
862  dims[1]=*to_migrate->m_datatype.m_length_y;
863 
864  replacement->allocate_data_from_scratch(dims);
865 
866  /* in case of sgobject, copy pointer data and SG_REF */
867  if (to_migrate->m_datatype.m_ptype==PT_SGOBJECT)
868  {
869  /* note that the memory is already allocated before the migrate call */
870  CSGObject* object=*((CSGObject**)to_migrate->m_parameter);
871  *((CSGObject**)replacement->m_parameter)=object;
872  SG_REF(object);
873  SG_DEBUG("copied and SG_REF sgobject pointer for \"%s\" at %p\n",
874  object->get_name(), object);
875  }
876 
877  /* tell the old TParameter to delete its data on deletion */
878  to_migrate->m_delete_data=true;
879 
880  SG_DEBUG("CSGObject::leaving CSGObject::one_to_one_migration_prepare() for "
881  "\"%s\"\n", target->m_name);
882 }
883 
885  const SGParamInfo* target)
886 {
887  SG_DEBUG("entering %s::migrate\n", get_name())
888  /* this is only executed, iff there was no migration method which handled
889  * migration to the provided target. In this case, it is assumed that the
890  * parameter simply has not changed. Verify this here and return copy of
891  * data in case its true.
892  * If not, throw an exception -- parameter migration HAS to be implemented
893  * by hand everytime, a parameter changes type or name. */
894 
895  TParameter* result=NULL;
896 
897  /* first find index of needed data.
898  * in this case, element in base with same name */
899  /* type is also needed */
900  TSGDataType type(target->m_ctype, target->m_stype,
901  target->m_ptype);
902 
903  /* dummy for searching, search and save result */
904  TParameter* t=new TParameter(&type, NULL, target->m_name, "");
905  index_t i=CMath::binary_search(param_base->get_array(),
906  param_base->get_num_elements(), t);
907  delete t;
908 
909  /* check if name change occurred while no migration method was specified */
910  if (i<0)
911  {
912  SG_ERROR("Name change for parameter that has to be mapped to \"%s\","
913  " and to no migration method available\n", target->m_name);
914  }
915 
916  TParameter* to_migrate=param_base->get_element(i);
917 
918  /* check if element in base is equal to target one */
919  if (*target==SGParamInfo(to_migrate, target->m_param_version))
920  {
921  char* s=SG_MALLOC(char, 200);
922  to_migrate->m_datatype.to_string(s, 200);
923  SG_DEBUG("nothing changed, using old data: %s\n", s)
924  SG_FREE(s);
925  result=new TParameter(&to_migrate->m_datatype, NULL, to_migrate->m_name,
926  to_migrate->m_description);
927 
928  SGVector<index_t> dims(2);
929  dims[0]=1;
930  dims[1]=1;
931  if (to_migrate->m_datatype.m_length_x)
932  dims[0]=*to_migrate->m_datatype.m_length_x;
933 
934  if (to_migrate->m_datatype.m_length_y)
935  dims[1]=*to_migrate->m_datatype.m_length_y;
936 
937  /* allocate lengths and evtl scalar data but not non-scalar data (no
938  * new_cont call */
939  result->allocate_data_from_scratch(dims, false);
940 
941  /* now use old data */
942  if (to_migrate->m_datatype.m_ctype==CT_SCALAR &&
943  to_migrate->m_datatype.m_ptype!=PT_SGOBJECT)
944  {
945  /* copy data */
946  SG_DEBUG("copying scalar data\n")
947  memcpy(result->m_parameter,to_migrate->m_parameter,
948  to_migrate->m_datatype.get_size());
949  }
950  else
951  {
952  /* copy content of pointer */
953  SG_DEBUG("copying content of poitner for non-scalar data\n")
954  *(void**)result->m_parameter=*(void**)(to_migrate->m_parameter);
955  }
956  }
957  else
958  {
959  char* s=target->to_string();
960  SG_ERROR("No migration method available for %s!\n", s)
961  SG_FREE(s);
962  }
963 
964  SG_DEBUG("leaving %s::migrate\n", get_name())
965 
966  return result;
967 }
968 
969 bool CSGObject::save_parameter_version(CSerializableFile* file,
970  const char* prefix, int32_t param_version)
971 {
972  TSGDataType t(CT_SCALAR, ST_NONE, PT_INT32);
973  TParameter p(&t, &param_version, "version_parameter",
974  "Version of parameters of this object");
975  return p.save(file, prefix);
976 }
977 
978 int32_t CSGObject::load_parameter_version(CSerializableFile* file,
979  const char* prefix)
980 {
981  TSGDataType t(CT_SCALAR, ST_NONE, PT_INT32);
982  int32_t v;
983  TParameter tp(&t, &v, "version_parameter", "");
984  if (tp.load(file, prefix))
985  return v;
986  else
987  return -1;
988 }
989 
991 {
992  m_load_pre_called = true;
993 }
994 
996 {
997  m_load_post_called = true;
998 }
999 
1001 {
1002  m_save_pre_called = true;
1003 }
1004 
1006 {
1007  m_save_post_called = true;
1008 }
1009 
1010 #ifdef TRACE_MEMORY_ALLOCS
1011 #include <shogun/lib/Map.h>
1012 extern CMap<void*, shogun::MemoryBlock>* sg_mallocs;
1013 #endif
1014 
1015 void CSGObject::init()
1016 {
1017 #ifdef TRACE_MEMORY_ALLOCS
1018  if (sg_mallocs)
1019  {
1020  int32_t idx=sg_mallocs->index_of(this);
1021  if (idx>-1)
1022  {
1023  MemoryBlock* b=sg_mallocs->get_element_ptr(idx);
1024  b->set_sgobject();
1025  }
1026  }
1027 #endif
1028 
1029  io = NULL;
1030  parallel = NULL;
1031  version = NULL;
1032  m_parameters = new Parameter();
1036  m_generic = PT_NOT_GENERIC;
1037  m_load_pre_called = false;
1038  m_load_post_called = false;
1039  m_hash = 0;
1040 }
1041 
1043 {
1044  SG_PRINT("parameters available for model selection for %s:\n", get_name())
1045 
1047 
1048  if (!num_param)
1049  SG_PRINT("\tnone\n")
1050 
1051  for (index_t i=0; i<num_param; i++)
1052  {
1054  index_t l=200;
1055  char* type=SG_MALLOC(char, l);
1056  if (type)
1057  {
1058  current->m_datatype.to_string(type, l);
1059  SG_PRINT("\t%s (%s): %s\n", current->m_name, current->m_description,
1060  type);
1061  SG_FREE(type);
1062  }
1063  }
1064 }
1065 
1067 {
1069 
1070  SGStringList<char> result(num_param, -1);
1071 
1072  index_t max_string_length=-1;
1073 
1074  for (index_t i=0; i<num_param; i++)
1075  {
1077  index_t len=strlen(name);
1078  // +1 to have a zero terminated string
1079  result.strings[i]=SGString<char>(name, len+1);
1080 
1081  if (len>max_string_length)
1082  max_string_length=len;
1083  }
1084 
1085  result.max_string_length=max_string_length;
1086 
1087  return result;
1088 }
1089 
1090 char* CSGObject::get_modsel_param_descr(const char* param_name)
1091 {
1092  index_t index=get_modsel_param_index(param_name);
1093 
1094  if (index<0)
1095  {
1096  SG_ERROR("There is no model selection parameter called \"%s\" for %s",
1097  param_name, get_name());
1098  }
1099 
1101 }
1102 
1104 {
1105  /* use fact that names extracted from below method are in same order than
1106  * in m_model_selection_parameters variable */
1108 
1109  /* search for parameter with provided name */
1110  index_t index=-1;
1111  for (index_t i=0; i<names.num_strings; i++)
1112  {
1114  if (!strcmp(param_name, current->m_name))
1115  {
1116  index=i;
1117  break;
1118  }
1119  }
1120 
1121  return index;
1122 }
1123 
1124 bool CSGObject::is_param_new(const SGParamInfo param_info) const
1125 {
1126  /* check if parameter is new in this version (has empty mapping) */
1127  DynArray<const SGParamInfo*>* value=m_parameter_map->get(&param_info);
1128  bool result=value && *value->get_element(0) == SGParamInfo();
1129 
1130  return result;
1131 }
1132 
1133 void CSGObject::get_parameter_incremental_hash(uint32_t& hash, uint32_t& carry,
1134  uint32_t& total_length)
1135 {
1136  for (index_t i=0; i<m_parameters->get_num_parameters(); i++)
1137  {
1139 
1140  SG_DEBUG("Updating hash for parameter %s.%s\n", get_name(), p->m_name);
1141 
1142  if (p->m_datatype.m_ptype == PT_SGOBJECT)
1143  {
1144  if (p->m_datatype.m_ctype == CT_SCALAR)
1145  {
1146  CSGObject* child = *((CSGObject**)(p->m_parameter));
1147 
1148  if (child)
1149  {
1150  child->get_parameter_incremental_hash(hash, carry,
1151  total_length);
1152  }
1153  }
1154  else if (p->m_datatype.m_ctype==CT_VECTOR ||
1155  p->m_datatype.m_ctype==CT_SGVECTOR)
1156  {
1157  CSGObject** child=(*(CSGObject***)(p->m_parameter));
1158 
1159  for (index_t j=0; j<*(p->m_datatype.m_length_y); j++)
1160  {
1161  if (child[j])
1162  {
1163  child[j]->get_parameter_incremental_hash(hash, carry,
1164  total_length);
1165  }
1166  }
1167  }
1168  }
1169  else
1170  p->get_incremental_hash(hash, carry, total_length);
1171  }
1172 }
1173 
1175 {
1176  for (index_t i=0; i<m_gradient_parameters->get_num_parameters(); i++)
1177  {
1179  dict->add(p, this);
1180  }
1181 
1183  {
1185  CSGObject* child=*(CSGObject**)(p->m_parameter);
1186 
1187  if ((p->m_datatype.m_ptype == PT_SGOBJECT) &&
1188  (p->m_datatype.m_ctype == CT_SCALAR) && child)
1189  {
1191  }
1192  }
1193 }
1194 
1195 bool CSGObject::equals(CSGObject* other, float64_t accuracy, bool tolerant)
1196 {
1197  SG_DEBUG("entering %s::equals()\n", get_name());
1198 
1199  if (other==this)
1200  {
1201  SG_DEBUG("leaving %s::equals(): other object is me\n", get_name());
1202  return true;
1203  }
1204 
1205  if (!other)
1206  {
1207  SG_DEBUG("leaving %s::equals(): other object is NULL\n", get_name());
1208  return false;
1209  }
1210 
1211  SG_DEBUG("comparing \"%s\" to \"%s\"\n", get_name(), other->get_name());
1212 
1213  /* a crude type check based on the get_name */
1214  if (strcmp(other->get_name(), get_name()))
1215  {
1216  SG_INFO("leaving %s::equals(): name of other object differs\n", get_name());
1217  return false;
1218  }
1219 
1220  /* should not be necessary but just ot be sure that type has not changed.
1221  * Will assume that parameters are in same order with same name from here */
1223  {
1224  SG_INFO("leaving %s::equals(): number of parameters of other object "
1225  "differs\n", get_name());
1226  return false;
1227  }
1228 
1229  for (index_t i=0; i<m_parameters->get_num_parameters(); ++i)
1230  {
1231  SG_DEBUG("comparing parameter %d\n", i);
1232 
1233  TParameter* this_param=m_parameters->get_parameter(i);
1234  TParameter* other_param=other->m_parameters->get_parameter(i);
1235 
1236  /* some checks to make sure parameters have same order and names and
1237  * are not NULL. Should never be the case but check anyway. */
1238  if (!this_param && !other_param)
1239  continue;
1240 
1241  if (!this_param && other_param)
1242  {
1243  SG_DEBUG("leaving %s::equals(): parameter %d is NULL where other's "
1244  "parameter \"%s\" is not\n", get_name(), other_param->m_name);
1245  return false;
1246  }
1247 
1248  if (this_param && !other_param)
1249  {
1250  SG_DEBUG("leaving %s::equals(): parameter %d is \"%s\" where other's "
1251  "parameter is NULL\n", get_name(), this_param->m_name);
1252  return false;
1253  }
1254 
1255  SG_DEBUG("comparing parameter \"%s\" to other's \"%s\"\n",
1256  this_param->m_name, other_param->m_name);
1257 
1258  /* hard-wired exception for DynamicObjectArray parameter num_elements */
1259  if (!strcmp("DynamicObjectArray", get_name()) &&
1260  !strcmp(this_param->m_name, "num_elements") &&
1261  !strcmp(other_param->m_name, "num_elements"))
1262  {
1263  SG_DEBUG("Ignoring DynamicObjectArray::num_elements field\n");
1264  continue;
1265  }
1266 
1267  /* hard-wired exception for DynamicArray parameter num_elements */
1268  if (!strcmp("DynamicArray", get_name()) &&
1269  !strcmp(this_param->m_name, "num_elements") &&
1270  !strcmp(other_param->m_name, "num_elements"))
1271  {
1272  SG_DEBUG("Ignoring DynamicArray::num_elements field\n");
1273  continue;
1274  }
1275 
1276  /* use equals method of TParameter from here */
1277  if (!this_param->equals(other_param, accuracy, tolerant))
1278  {
1279  SG_INFO("leaving %s::equals(): parameters at position %d with name"
1280  " \"%s\" differs from other object parameter with name "
1281  "\"%s\"\n",
1282  get_name(), i, this_param->m_name, other_param->m_name);
1283  return false;
1284  }
1285  }
1286 
1287  SG_DEBUG("leaving %s::equals(): object are equal\n", get_name());
1288  return true;
1289 }
1290 
1292 {
1293  SG_DEBUG("entering %s::clone()\n", get_name());
1294 
1295  SG_DEBUG("constructing an empty instance of %s\n", get_name());
1296  CSGObject* copy=new_sgserializable(get_name(), this->m_generic);
1297 
1298  SG_REF(copy);
1299 
1300  REQUIRE(copy, "Could not create empty instance of \"%s\". The reason for "
1301  "this usually is that get_name() of the class returns something "
1302  "wrong, or that a class has a wrongly set generic type.\n",
1303  get_name());
1304 
1305  for (index_t i=0; i<m_parameters->get_num_parameters(); ++i)
1306  {
1307  SG_DEBUG("cloning parameter \"%s\" at index %d\n",
1309 
1311  {
1312  SG_DEBUG("leaving %s::clone(): Clone failed. Returning NULL\n",
1313  get_name());
1314  return NULL;
1315  }
1316  }
1317 
1318  SG_DEBUG("leaving %s::clone(): Clone successful\n", get_name());
1319  return copy;
1320 }
virtual const char * get_name() const =0
EStructType m_stype
Definition: ParameterMap.h:93
SGStringList< char > get_modelsel_names()
Definition: SGObject.cpp:1066
#define SG_INFO(...)
Definition: SGIO.h:120
T get_element(int32_t index) const
Definition: DynArray.h:140
Parallel * get_global_parallel()
Definition: SGObject.cpp:215
virtual bool save_serializable(CSerializableFile *file, const char *prefix="", int32_t param_version=Version::get_version_parameter())
Definition: SGObject.cpp:252
virtual void update_parameter_hash()
Definition: SGObject.cpp:187
Class that holds informations about a certain parameter of an CSGObject. Contains name...
Definition: ParameterMap.h:28
Class SGRefObject is a reference count based memory management class.
Definition: SGRefObject.h:46
ParameterMap * m_parameter_map
Definition: SGObject.h:491
SGString< T > * strings
Definition: SGStringList.h:86
virtual TParameter * migrate(DynArray< TParameter * > *param_base, const SGParamInfo *target)
Definition: SGObject.cpp:884
bool append_element(T element)
Definition: DynArray.h:242
int32_t index_t
Definition: common.h:60
virtual int32_t get_num_parameters()
Definition: Parameter.h:247
virtual CSGObject * clone()
Definition: SGObject.cpp:1291
Class ShogunException defines an exception which is thrown whenever an error inside of shogun occurs...
#define SG_SWARNING(...)
Definition: SGIO.h:180
#define SG_UNREF(x)
Definition: SGRefObject.h:35
void unset_generic()
Definition: SGObject.cpp:241
static int32_t binary_search(T *output, int32_t size, T elem)
Definition: Math.h:1171
TParameter * get_parameter(int32_t idx)
Definition: Parameter.h:280
DynArray< const SGParamInfo * > * get(const SGParamInfo) const
Version * get_global_version()
Definition: SGObject.cpp:228
index_t * m_length_x
Definition: DataType.h:79
parameter struct
Definition: Parameter.h:26
virtual void save_serializable_pre()
Definition: SGObject.cpp:1000
#define SG_ERROR(...)
Definition: SGIO.h:131
#define REQUIRE(x,...)
Definition: SGIO.h:208
virtual bool is_generic(EPrimitiveType *generic) const
Definition: SGObject.cpp:234
Parameter * m_parameters
Definition: SGObject.h:482
virtual void print(const char *prefix="")
Definition: Parameter.cpp:2787
static uint32_t FinalizeIncrementalMurmurHash3(uint32_t h, uint32_t carry, uint32_t total_length)
Definition: Hash.cpp:375
int32_t get_num_elements() const
Definition: DynArray.h:128
static int32_t get_version_parameter()
Definition: Version.cpp:104
Parallel * parallel
Definition: SGObject.h:476
SGParamInfo * duplicate() const
Implements a map of ParameterMapElement instances Maps one key to a set of values.
Definition: ParameterMap.h:161
Datatypes that shogun supports.
Definition: DataType.h:67
Version * sg_version
Definition: init.cpp:29
static void qsort(T *output, int32_t size)
Definition: Math.h:775
char * get_modsel_param_descr(const char *param_name)
Definition: SGObject.cpp:1090
bool equals(TParameter *other, float64_t accuracy=0.0, bool tolerant=false)
Definition: Parameter.cpp:3136
TSGDataType m_datatype
Definition: Parameter.h:159
EContainerType m_ctype
Definition: ParameterMap.h:90
#define SG_PRINT(...)
Definition: SGIO.h:139
DynArray< TParameter * > * load_file_parameters(const SGParamInfo *param_info, int32_t file_version, CSerializableFile *file, const char *prefix="")
Definition: SGObject.cpp:480
Parallel * sg_parallel
Definition: init.cpp:27
Parameter class.
Definition: Parameter.h:219
#define ASSERT(x)
Definition: SGIO.h:203
Class SGObject is the base class of all shogun objects.
Definition: SGObject.h:102
virtual ~CSGObject()
Definition: SGObject.cpp:134
SGIO * sg_io
Definition: init.cpp:28
void build_gradient_parameter_dictionary(CMap< TParameter *, CSGObject * > *dict)
Definition: SGObject.cpp:1174
Template Dynamic array class that creates an array that can be used like a list or an array...
Definition: DynArray.h:30
double float64_t
Definition: common.h:48
virtual bool load_serializable(CSerializableFile *file, const char *prefix="", int32_t param_version=Version::get_version_parameter())
Definition: SGObject.cpp:311
DynArray< TParameter * > * load_all_file_parameters(int32_t file_version, int32_t current_version, CSerializableFile *file, const char *prefix="")
Definition: SGObject.cpp:639
Version * version
Definition: SGObject.h:479
virtual bool save(CSerializableFile *file, const char *prefix="")
Definition: Parameter.cpp:2794
#define SG_REF(x)
Definition: SGRefObject.h:34
the class CMap, a map based on the hash-table. w: http://en.wikipedia.org/wiki/Hash_table ...
Definition: SGObject.h:40
virtual void save_serializable_post()
Definition: SGObject.cpp:1005
void print_modsel_params()
Definition: SGObject.cpp:1042
CSGObject * new_sgserializable(const char *sgserializable_name, EPrimitiveType generic)
EPrimitiveType m_ptype
Definition: ParameterMap.h:96
Class Version provides version information.
Definition: Version.h:32
Parameter * m_model_selection_parameters
Definition: SGObject.h:485
void get_incremental_hash(uint32_t &hash, uint32_t &carry, uint32_t &total_length)
Definition: Parameter.cpp:2450
virtual bool equals(CSGObject *other, float64_t accuracy=0.0, bool tolerant=false)
Definition: SGObject.cpp:1195
index_t * m_length_y
Definition: DataType.h:77
void set_global_parallel(Parallel *parallel)
Definition: SGObject.cpp:180
void to_string(char *dest, size_t n) const
Definition: DataType.cpp:144
virtual void load_serializable_pre()
Definition: SGObject.cpp:990
virtual void load_serializable_post()
Definition: SGObject.cpp:995
EContainerType m_ctype
Definition: DataType.h:70
Class Parallel provides helper functions for multithreading.
Definition: Parallel.h:27
#define SG_DEBUG(...)
Definition: SGIO.h:109
int32_t index_of(const K &key)
Definition: Map.h:152
virtual void one_to_one_migration_prepare(DynArray< TParameter * > *param_base, const SGParamInfo *target, TParameter *&replacement, TParameter *&to_migrate, char *old_name=NULL)
Definition: SGObject.cpp:824
const char * get_exception_string()
bool load(CSerializableFile *file, const char *prefix="")
Definition: Parameter.cpp:2639
int32_t add(const K &key, const T &data)
Definition: Map.h:99
#define SG_SDEBUG(...)
Definition: SGIO.h:170
SGIO * get_global_io()
Definition: SGObject.cpp:174
#define PT_NOT_GENERIC
Definition: DataType.h:20
#define SG_SERROR(...)
Definition: SGIO.h:181
void map_parameters(DynArray< TParameter * > *param_base, int32_t &base_version, DynArray< const SGParamInfo * > *target_param_infos)
Definition: SGObject.cpp:677
index_t get_modsel_param_index(const char *param_name)
Definition: SGObject.cpp:1103
T * get_array() const
Definition: DynArray.h:370
void set_global_io(SGIO *io)
Definition: SGObject.cpp:167
uint32_t m_hash
Definition: SGObject.h:494
bool copy(TParameter *target)
Definition: Parameter.cpp:3944
void copy_data(const TParameter *source)
Definition: Parameter.cpp:3076
char * to_string() const
Class which collects generic mathematical functions.
Definition: Math.h:133
char * m_description
Definition: Parameter.h:165
EPrimitiveType m_ptype
Definition: DataType.h:74
#define SG_WARNING(...)
Definition: SGIO.h:130
Class SGIO, used to do input output operations throughout shogun.
Definition: SGIO.h:245
Parameter * m_gradient_parameters
Definition: SGObject.h:488
virtual void print_serializable(const char *prefix="")
Definition: SGObject.cpp:246
virtual bool parameter_hash_changed()
Definition: SGObject.cpp:200
void set_global_version(Version *version)
Definition: SGObject.cpp:221
void allocate_data_from_scratch(SGVector< index_t > dims, bool new_cont_call=true)
Definition: Parameter.cpp:2987
template class SGStringList
Definition: SGObject.h:44

SHOGUN Machine Learning Toolbox - Documentation