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

SHOGUN Machine Learning Toolbox - Documentation