Skip to content

Commit

Permalink
Merge pull request #359 from karlnapf/master
Browse files Browse the repository at this point in the history
finally - migration is complete :)
  • Loading branch information
Soeren Sonnenburg committed Jan 27, 2012
2 parents a79affd + 5a3483b commit 5c6dc6d
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 12 deletions.
1 change: 1 addition & 0 deletions examples/undocumented/libshogun/Makefile
Expand Up @@ -38,6 +38,7 @@ TARGETS = basic_minimal classifier_libsvm classifier_minimal_svm \
base_map_parameters \
base_migration_type_conversion \
base_migration_dropping_and_new \
base_migration_multiple_dependencies \
splitting_stratified_crossvalidation \
mathematics_arpack \
library_fibonacci_heap \
Expand Down
@@ -0,0 +1,176 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Written (W) 2012 Heiko Strathmann
* Copyright (C) 2012 Berlin Institute of Technology and Max-Planck-Society
*/

#include <shogun/base/init.h>
#include <shogun/base/Parameter.h>
#include <shogun/io/SerializableAsciiFile.h>
#include <shogun/base/ParameterMap.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
fprintf(target, "%s", str);
}

class CTestClassOld : public CSGObject
{
public:
CTestClassOld()
{
m_number_1=1;
m_number_2=2;
m_parameters->add(&m_number_1, "m_number_1", "");
m_parameters->add(&m_number_2, "m_number_2", "");
}

int32_t m_number_1;
int32_t m_number_2;

virtual const char* get_name() const { return "TestClassOld"; }
};

class CTestClassNew : public CSGObject
{
public:
CTestClassNew()
{
m_number=0;
m_parameters->add(&m_number, "m_number", "");

/* number_1 in old version will become new, merged number */
m_parameter_map->put(
new SGParamInfo("m_number", CT_SCALAR, ST_NONE, PT_INT32, 1),
new SGParamInfo("m_number_1", CT_SCALAR, ST_NONE, PT_INT32, 0)
);

/* Note that here, two mappings for one parameter are added. This means
* that m_number both depends on m_number_1 and m_number_2 */
m_parameter_map->put(
new SGParamInfo("m_number", CT_SCALAR, ST_NONE, PT_INT32, 1),
new SGParamInfo("m_number_2", CT_SCALAR, ST_NONE, PT_INT32, 0)
);

/* note that dropped parameters need not be considered, just ignored */

/* needed if more than one element */
m_parameter_map->finalize_map();
}

int32_t m_number;
int32_t m_number_new;

virtual const char* get_name() const { return "TestClassNew"; }

virtual TParameter* migrate(DynArray<TParameter*>* param_base,
const SGParamInfo* target)
{
TParameter* result=NULL;

if (*target==SGParamInfo("m_number", CT_SCALAR, ST_NONE, PT_INT32, 1))
{
/* one to one migration may not be used here because two parameters
* are merged into one parameter. Here the new parameter will
* contain the sum of the two old ones. */

/* generate type of target structure */
TSGDataType type(target->m_ctype, target->m_stype, target->m_ptype);

/* find elements that are needed for migration, in this case the
* two numbers of the base */
char* name_1=(char*) "m_number_1";
char* name_2=(char*) "m_number_2";

/* dummy elements for searching */
TParameter* t_1=new TParameter(&type, NULL, name_1, "");
TParameter* t_2=new TParameter(&type, NULL, name_2, "");
index_t i_1=CMath::binary_search(param_base->get_array(),
param_base->get_num_elements(), t_1);
index_t i_2=CMath::binary_search(param_base->get_array(),
param_base->get_num_elements(), t_2);

delete t_1;
delete t_2;

/* gather search results and tell them that they are to be deleted
* because they will be replaced */
ASSERT(i_1>=0 && i_2>=0);
TParameter* to_migrate_1=param_base->get_element(i_1);
TParameter* to_migrate_2=param_base->get_element(i_2);
to_migrate_1->m_delete_data=true;
to_migrate_2->m_delete_data=true;

/* create result structure and allocate data for it */
result=new TParameter(&type, NULL, target->m_name,
"New description");

/* scalar value has length one */
result->allocate_data_from_scratch(1, 1);

/* merged element contains sum of both to be merged elements */
*((int32_t*)result->m_parameter)=
*((int32_t*)to_migrate_1->m_parameter)+
*((int32_t*)to_migrate_2->m_parameter);
}

if (result)
return result;
else
return CSGObject::migrate(param_base, target);
}
};

void test_migration()
{
const char* filename="test.txt";

/* create one instance of each class */
CTestClassOld* old_instance=new CTestClassOld();
CTestClassNew* new_instance=new CTestClassNew();

CSerializableAsciiFile* file;

/* serialize int instance, use custom parameter version */
file=new CSerializableAsciiFile(filename, 'w');
old_instance->save_serializable(file, "", 0);
file->close();
SG_UNREF(file);

/* de-serialize float instance, use custom parameter version */
file=new CSerializableAsciiFile(filename, 'r');
new_instance->load_serializable(file, "", 1);
file->close();
SG_UNREF(file);

/* check that merged number is sum old to be merged ones */
SG_SPRINT("checking \"m_number\":\n");
SG_SPRINT("\t%d==%d+%d\n", new_instance->m_number, old_instance->m_number_1,
old_instance->m_number_2);
ASSERT(new_instance->m_number==old_instance->m_number_1+
old_instance->m_number_2);

SG_UNREF(old_instance);
SG_UNREF(new_instance);
SG_UNREF(file);
}

int main(int argc, char **argv)
{
init_shogun(&print_message, &print_message, &print_message);

/* this is a more complex example, where a parameter is based on two
* old parameter */
test_migration();

exit_shogun();

return 0;
}

24 changes: 12 additions & 12 deletions src/shogun/base/ParameterMap.cpp
Expand Up @@ -301,16 +301,16 @@ void ParameterMap::finalize_map()
m_map_elements.get_num_elements());

// SG_SPRINT("map elements before finalize\n");
for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
{
ParameterMapElement* current=m_map_elements[i];
// for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
// {
// ParameterMapElement* current=m_map_elements[i];
// SG_SPRINT("element %d:\n", i);
// SG_SPRINT("\tkey: ");
current->m_key->print_param_info();
// current->m_key->print_param_info();
// SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements());
for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
current->m_values->get_element(j)->print_param_info("\t\t");
}
// for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
// current->m_values->get_element(j)->print_param_info("\t\t");
// }

/* clear old multi elements. These were copies. */
for (index_t i=0; i<m_multi_map_elements.get_num_elements(); ++i)
Expand All @@ -323,9 +323,9 @@ void ParameterMap::finalize_map()
* add all values of same key to ONE map element of hidden structure */
DynArray<const SGParamInfo*>* values=new DynArray<const SGParamInfo*>();
const SGParamInfo* current_key=m_map_elements[0]->m_key;
char* s=current_key->to_string();
// char* s=current_key->to_string();
// SG_SPRINT("current key: %s\n", s);
SG_FREE(s);
// SG_FREE(s);
for (index_t i=0; i<m_map_elements.get_num_elements(); ++i)
{
const ParameterMapElement* current=m_map_elements[i];
Expand All @@ -334,9 +334,9 @@ void ParameterMap::finalize_map()
/* create new values array to add and update key */
values=new DynArray<const SGParamInfo*>();
current_key=current->m_key;
s=current_key->to_string();
// s=current_key->to_string();
// SG_SPRINT("new current key: %s\n", s);
SG_FREE(s);
// SG_FREE(s);
}

/* add to values array */
Expand Down Expand Up @@ -373,7 +373,7 @@ void ParameterMap::print_map()
ParameterMapElement* current=m_multi_map_elements[i];
// SG_SPRINT("element %d:\n", i);
// SG_SPRINT("\tkey: ");
current->m_key->print_param_info();
// current->m_key->print_param_info();
// SG_SPRINT("\t%d values:\n", current->m_values->get_num_elements());
for (index_t j=0; j<current->m_values->get_num_elements(); ++j)
current->m_values->get_element(j)->print_param_info("\t\t");
Expand Down

0 comments on commit 5c6dc6d

Please sign in to comment.