ParameterCombination.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2011 Heiko Strathmann
00008  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
00009  */
00010 
00011 #include <shogun/modelselection/ParameterCombination.h>
00012 #include <shogun/base/Parameter.h>
00013 #include <shogun/machine/Machine.h>
00014 
00015 using namespace shogun;
00016 
00017 CParameterCombination::CParameterCombination()
00018 {
00019     init();
00020 }
00021 
00022 CParameterCombination::CParameterCombination(Parameter* param)
00023 {
00024     init();
00025 
00026     m_param=param;
00027 }
00028 
00029 void CParameterCombination::init()
00030 {
00031     m_param=NULL;
00032     m_child_nodes=new CDynamicObjectArray<CParameterCombination> ();
00033     SG_REF(m_child_nodes);
00034 
00035     m_parameters->add((CSGObject**)m_child_nodes, "child nodes",
00036             "children of this node");
00037 }
00038 
00039 CParameterCombination::~CParameterCombination()
00040 {
00041     delete m_param;
00042     SG_UNREF(m_child_nodes);
00043 }
00044 
00045 void CParameterCombination::append_child(CParameterCombination* child)
00046 {
00047     m_child_nodes->append_element(child);
00048 }
00049 
00050 void CParameterCombination::print_tree(int prefix_num) const
00051 {
00052     /* prefix is enlarged */
00053     char* prefix=SG_MALLOC(char, prefix_num+1);
00054     for (index_t i=0; i<prefix_num; ++i)
00055         prefix[i]='\t';
00056 
00057     prefix[prefix_num]='\0';
00058 
00059     /* cases:
00060      * -node with a Parameter instance and a possible children
00061      * -root node with children
00062      */
00063 
00064     if (m_param)
00065     {
00066         SG_SPRINT("%s", prefix);
00067         for (index_t i=0; i<m_param->get_num_parameters(); ++i)
00068         {
00069             /* distinction between sgobject and values */
00070             if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_SGOBJECT)
00071             {
00072                 TParameter* param=m_param->get_parameter(i);
00073                 CSGObject* current_sgobject=*((CSGObject**) param->m_parameter);
00074                 SG_SPRINT("\"%s\":%s at %p ", param->m_name,
00075                         current_sgobject->get_name(), current_sgobject);
00076             }
00077             else
00078             {
00079                 SG_SPRINT("\"%s\"=", m_param->get_parameter(i)->m_name);
00080                 void* param=m_param->get_parameter(i)->m_parameter;
00081 
00082                 if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_FLOAT64)
00083                     SG_SPRINT("%f ", *((float64_t*)param));
00084                 else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_INT32)
00085                     SG_SPRINT("%i ", *((int32_t*)param));
00086                 else if (m_param->get_parameter(i)->m_datatype.m_ptype==PT_BOOL)
00087                     SG_SPRINT("%s ", *((bool*)param ? "true" : "false"));
00088                 else
00089                     SG_NOTIMPLEMENTED;
00090             }
00091 
00092         }
00093 
00094     }
00095     else
00096         SG_SPRINT("%sroot", prefix);
00097 
00098     SG_SPRINT("\n");
00099 
00100     for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00101     {
00102         CParameterCombination* child=m_child_nodes->get_element(i);
00103         child->print_tree(prefix_num+1);
00104         SG_UNREF(child);
00105     }
00106 
00107     SG_FREE(prefix);
00108 }
00109 
00110 DynArray<Parameter*>* CParameterCombination::parameter_set_multiplication(
00111         const DynArray<Parameter*>& set_1, const DynArray<Parameter*>& set_2)
00112 {
00113     DynArray<Parameter*>* result=new DynArray<Parameter*>();
00114 
00115     for (index_t i=0; i<set_1.get_num_elements(); ++i)
00116     {
00117         for (index_t j=0; j<set_2.get_num_elements(); ++j)
00118         {
00119             Parameter* p=new Parameter();
00120             p->add_parameters(set_1[i]);
00121             p->add_parameters(set_2[j]);
00122             result->append_element(p);
00123         }
00124     }
00125 
00126     return result;
00127 }
00128 
00129 CDynamicObjectArray<CParameterCombination>* CParameterCombination::leaf_sets_multiplication(
00130         const CDynamicObjectArray<CDynamicObjectArray<CParameterCombination> >& sets,
00131         const CParameterCombination* new_root)
00132 {
00133     CDynamicObjectArray<CParameterCombination>* result=new CDynamicObjectArray<
00134             CParameterCombination>();
00135 
00136     /* check marginal cases */
00137     if (sets.get_num_elements()==1)
00138     {
00139         CDynamicObjectArray<CParameterCombination>* current_set=
00140                 sets.get_element(0);
00141 
00142         /* just use the only element into result array.
00143          * put root node before all combinations*/
00144         *result=*current_set;
00145 
00146         SG_UNREF(current_set);
00147 
00148         for (index_t i=0; i<result->get_num_elements(); ++i)
00149         {
00150             /* put new root as root into the tree and replace tree */
00151             CParameterCombination* current=result->get_element(i);
00152             CParameterCombination* root=new_root->copy_tree();
00153             root->append_child(current);
00154             result->set_element(root, i);
00155             SG_UNREF(current);
00156         }
00157     }
00158     else if (sets.get_num_elements()>1)
00159     {
00160         /* now the case where at least two sets are given */
00161 
00162         /* first, extract Parameter instances of given sets */
00163         DynArray<DynArray<Parameter*>*> param_sets;
00164 
00165         for (index_t set_nr=0; set_nr<sets.get_num_elements(); ++set_nr)
00166         {
00167             CDynamicObjectArray<CParameterCombination>* current_set=
00168                     sets.get_element(set_nr);
00169             DynArray<Parameter*>* new_param_set=new DynArray<Parameter*> ();
00170             param_sets.append_element(new_param_set);
00171 
00172             for (index_t i=0; i<current_set->get_num_elements(); ++i)
00173             {
00174                 CParameterCombination* current_node=current_set->get_element(i);
00175 
00176                 if (current_node->m_child_nodes->get_num_elements())
00177                 {
00178                     SG_SERROR("leaf sets multiplication only possible if all "
00179                             "trees are leafs");
00180                 }
00181 
00182                 Parameter* current_param=current_node->m_param;
00183 
00184                 if (current_param)
00185                     new_param_set->append_element(current_param);
00186                 else
00187                 {
00188                     SG_SERROR("leaf sets multiplication only possible if all "
00189                             "leafs have non-NULL Parameter instances\n");
00190                 }
00191 
00192                 SG_UNREF(current_node);
00193             }
00194 
00195             SG_UNREF(current_set);
00196         }
00197 
00198         /* second, build products of all parameter sets */
00199         DynArray<Parameter*>* param_product=parameter_set_multiplication(
00200                 *param_sets[0], *param_sets[1]);
00201 
00202         delete param_sets[0];
00203         delete param_sets[1];
00204 
00205         /* build product of all remaining sets and collect results. delete all
00206          * parameter instances of interim products*/
00207         for (index_t i=2; i<param_sets.get_num_elements(); ++i)
00208         {
00209             DynArray<Parameter*>* old_temp_result=param_product;
00210             param_product=parameter_set_multiplication(*param_product,
00211                     *param_sets[i]);
00212 
00213             /* delete interim result parameter instances */
00214             for (index_t j=0; j<old_temp_result->get_num_elements(); ++j)
00215                 delete old_temp_result->get_element(j);
00216 
00217             /* and dyn arrays of interim result and of param_sets */
00218             delete old_temp_result;
00219             delete param_sets[i];
00220         }
00221 
00222         /* at this point there is only one DynArray instance remaining:
00223          * param_product. contains all combinations of parameters of all given
00224          * sets */
00225 
00226         /* third, build tree sets with the given root and the parameter product
00227          * elements */
00228         for (index_t i=0; i<param_product->get_num_elements(); ++i)
00229         {
00230             /* build parameter node from parameter product to append to root */
00231             CParameterCombination* param_node=new CParameterCombination(
00232                     param_product->get_element(i));
00233 
00234             /* copy new root node, has to be a new one each time */
00235             CParameterCombination* root=new_root->copy_tree();
00236 
00237             /* append both and add them to result set */
00238             root->append_child(param_node);
00239             result->append_element(root);
00240         }
00241 
00242         /* this is not needed anymore, because the Parameter instances are now
00243          * in the resulting tree sets */
00244         delete param_product;
00245     }
00246 
00247     return result;
00248 }
00249 
00250 CParameterCombination* CParameterCombination::copy_tree() const
00251 {
00252     CParameterCombination* copy=new CParameterCombination();
00253 
00254     /* but build new Parameter instance */
00255 
00256     /* only call add_parameters() argument is non-null */
00257     if (m_param)
00258     {
00259         copy->m_param=new Parameter();
00260         copy->m_param->add_parameters(m_param);
00261     } else
00262         copy->m_param=NULL;
00263 
00264     /* recursively copy all children */
00265     for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00266     {
00267         CParameterCombination* child=m_child_nodes->get_element(i);
00268         copy->m_child_nodes->append_element(child->copy_tree());
00269         SG_UNREF(child);
00270     }
00271 
00272     return copy;
00273 }
00274 
00275 void CParameterCombination::apply_to_machine(CMachine* machine) const
00276 {
00277     apply_to_modsel_parameter(machine->m_model_selection_parameters);
00278 }
00279 
00280 void CParameterCombination::apply_to_modsel_parameter(
00281         Parameter* parameter) const
00282 {
00283     /* case root node */
00284     if (!m_param)
00285     {
00286         /* iterate over all children and recursively set parameters from
00287          * their values to the current parameter input (its just handed one
00288          * recursion level downwards) */
00289         for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00290         {
00291             CParameterCombination* child=m_child_nodes->get_element(i);
00292             child->apply_to_modsel_parameter(parameter);
00293             SG_UNREF(child);
00294         }
00295     }
00296     /* case parameter node */
00297     else if (m_param)
00298     {
00299         /* set parameters */
00300         parameter->set_from_parameters(m_param);
00301 
00302         /* does this node has sub parameters? */
00303         if (has_children())
00304         {
00305             /* if a parameter node has children, it has to have ONE CSGObject as
00306              * parameter */
00307             if (m_param->get_num_parameters()>1 ||
00308                     m_param->get_parameter(0)->m_datatype.m_ptype!=PT_SGOBJECT)
00309             {
00310                 SG_SERROR("invalid CParameterCombination node type, has children"
00311                         " and more than one parameter or is not a "
00312                         "CSGObject.\n");
00313             }
00314 
00315             /* cast is now safe */
00316             CSGObject* current_sgobject=
00317                     *((CSGObject**)(m_param->get_parameter(0)->m_parameter));
00318 
00319             /* iterate over all children and recursively set parameters from
00320              * their values */
00321             for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00322             {
00323                 CParameterCombination* child=m_child_nodes->get_element(i);
00324                 child->apply_to_modsel_parameter(
00325                         current_sgobject->m_model_selection_parameters);
00326                 SG_UNREF(child);
00327             }
00328         }
00329     }
00330     else
00331         SG_SERROR("CParameterCombination node has illegal type.\n");
00332 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation