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

SHOGUN Machine Learning Toolbox - Documentation