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

SHOGUN Machine Learning Toolbox - Documentation