ModelSelectionParameters.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/ModelSelectionParameters.h>
00012 #include <shogun/modelselection/ParameterCombination.h>
00013 #include <shogun/lib/DataType.h>
00014 #include <shogun/base/Parameter.h>
00015 #include <shogun/base/DynArray.h>
00016 
00017 using namespace shogun;
00018 
00019 CModelSelectionParameters::CModelSelectionParameters()
00020 {
00021     init();
00022 }
00023 
00024 CModelSelectionParameters::CModelSelectionParameters(const char* node_name)
00025 {
00026     init();
00027 
00028     m_node_name=node_name;
00029 }
00030 
00031 CModelSelectionParameters::CModelSelectionParameters(const char* node_name,
00032         CSGObject* sgobject)
00033 {
00034     init();
00035 
00036     m_node_name=node_name;
00037     m_sgobject=sgobject;
00038     SG_REF(sgobject);
00039 }
00040 
00041 void CModelSelectionParameters::init()
00042 {
00043     m_node_name=NULL;
00044     m_sgobject=NULL;
00045     m_child_nodes=new CDynamicObjectArray<CModelSelectionParameters>();
00046     SG_REF(m_child_nodes);
00047     m_value_type=MSPT_NONE;
00048 
00049     m_parameters->add((char*)m_node_name, "node_name", "Name of node");
00050     m_parameters->add((CSGObject**)&m_sgobject, "sgobject",
00051             "CSGObject of this node");
00052     m_parameters->add((CSGObject**)m_child_nodes, "child nodes",
00053             "children of this node");
00054 //  m_parameters->add(&m_value_type, "value_type",
00055 //              "type of the values of this node");
00056 }
00057 
00058 CModelSelectionParameters::~CModelSelectionParameters()
00059 {
00060     SG_UNREF(m_child_nodes);
00061     SG_UNREF(m_sgobject);
00062 
00063     delete_values();
00064 }
00065 
00066 void CModelSelectionParameters::append_child(CModelSelectionParameters* child)
00067 {
00068     /* only possible if there are no values set */
00069     if (m_values.vector)
00070         SG_ERROR("not possible to append child: there already is a range\n");
00071 
00072     /* do a basic check if the add is possible */
00073     if (m_sgobject)
00074     {
00075         /* (does this node's CSGObject contain a parameter with the name of the
00076          * child?) to prevent problems when trying to set parameters that do not
00077          * exist */
00078         if (child->m_node_name)
00079         {
00080             if (!m_sgobject->m_parameters->contains_parameter(child->m_node_name))
00081             {
00082                 SG_ERROR("Not possible to add child, node with CSGObject \"%s\""
00083                         " does not contain a parameter called \"%s\"\n",
00084                         m_sgobject->get_name(), child->m_node_name);
00085             }
00086         }
00087         else
00088         {
00089             SG_ERROR("Not possible to add child which has no name.\n");
00090         }
00091     }
00092 
00093     m_child_nodes->append_element(child);
00094 }
00095 
00096 void CModelSelectionParameters::set_values(SGVector<void> values)
00097 {
00098     /* possibly delete old range values */
00099     delete_values();
00100     m_values=values;
00101 }
00102 
00103 void CModelSelectionParameters::build_values(float64_t min, float64_t max,
00104         ERangeType type, float64_t step, float64_t type_base)
00105 {
00106     build_values(MSPT_FLOAT64, (void*)&min, (void*)&max, type, (void*)&step,
00107             (void*)&type_base);
00108 }
00109 
00110 void CModelSelectionParameters::build_values(int32_t min, int32_t max,
00111         ERangeType type, int32_t step, int32_t type_base)
00112 {
00113     build_values(MSPT_INT32, (void*)&min, (void*)&max, type, (void*)&step,
00114             (void*)&type_base);
00115 }
00116 
00117 void CModelSelectionParameters::build_values(EMSParamType value_type, void* min,
00118         void* max, ERangeType type, void* step, void* type_base)
00119 {
00120     if (m_sgobject || has_children())
00121     {
00122         SG_ERROR("unable to set range for an CSGObject model selection "
00123                 "parameter\n");
00124     }
00125 
00126     /* possibly delete old range values */
00127     delete_values();
00128 
00129     /* save new type */
00130     m_value_type=value_type;
00131 
00132     if (value_type==MSPT_FLOAT64)
00133     {
00134         SGVector<float64_t> values=create_range_array<float64_t>(
00135                 *((float64_t*)min),
00136                 *((float64_t*)max),
00137                 type,
00138                 *((float64_t*)step),
00139                 *((float64_t*)type_base));
00140 
00141         m_values.vector=(void*)values.vector;
00142         m_values.vlen=values.vlen;
00143     }
00144     else if (value_type==MSPT_INT32)
00145     {
00146         SGVector<int32_t> values=create_range_array<int32_t>(
00147                 *((int32_t*)min),
00148                 *((int32_t*)max),
00149                 type,
00150                 *((int32_t*)step),
00151                 *((int32_t*)type_base));
00152 
00153         m_values.vector=(void*)values.vector;
00154         m_values.vlen=values.vlen;
00155     }
00156     else if (value_type==MSPT_NONE)
00157     {
00158         SG_ERROR("Value node has no type!\n");
00159     }
00160     else
00161     {
00162         SG_ERROR("Unknown type for model selection parameter!\n");
00163     }
00164 }
00165 
00166 CDynamicObjectArray<CParameterCombination>* CModelSelectionParameters::get_combinations()
00167 {
00168     CDynamicObjectArray<CParameterCombination>* result=new CDynamicObjectArray<
00169             CParameterCombination>();
00170 
00171     /* value case: node with values and no children.
00172      * build trees of Parameter instances which each contain one value
00173      */
00174     if (m_values.vector)
00175     {
00176         for (index_t i=0; i<m_values.vlen; ++i)
00177         {
00178             /* create tree with only one parameter element */
00179             Parameter* p=new Parameter();
00180 
00181             switch (m_value_type)
00182             {
00183             case MSPT_FLOAT64:
00184                 p->add(&((float64_t*)m_values.vector)[i], m_node_name);
00185                 break;
00186             case MSPT_INT32:
00187                 p->add(&((int32_t*)m_values.vector)[i], m_node_name);;
00188                 break;
00189             case MSPT_NONE:
00190                 SG_ERROR("Value node has no type!\n");
00191                 break;
00192             default:
00193                 SG_ERROR("Unknown type for model selection parameter!\n");
00194                 break;
00195             }
00196 
00197             result->append_element(new CParameterCombination(p));
00198         }
00199     }
00200     /* two cases here, similar
00201      * -case CSGObject:
00202      * -case root node (no name, no values, but children
00203      * build all permutations of the result trees of children with values and
00204      * combine them iteratively children which are something different
00205      */
00206     else if ((m_sgobject && m_node_name) ||
00207             (!m_node_name && !m_sgobject))
00208     {
00209         /* only consider combinations if this node has children */
00210         if (m_child_nodes->get_num_elements())
00211         {
00212             /* split value and non-value child combinations */
00213             CDynamicObjectArray<CModelSelectionParameters> value_children;
00214             CDynamicObjectArray<CModelSelectionParameters> non_value_children;
00215 
00216             for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00217             {
00218                 CModelSelectionParameters* current=m_child_nodes->get_element(i);
00219 
00220                 /* split children with values and children with other */
00221                 if (current->m_values.vector)
00222                     value_children.append_element(current);
00223                 else
00224                     non_value_children.append_element(current);
00225 
00226                 SG_UNREF(current);
00227             }
00228 
00229             /* extract all tree sets of all value children */
00230             CDynamicObjectArray<CDynamicObjectArray<CParameterCombination> > value_node_sets;
00231             for (index_t i=0; i<value_children.get_num_elements(); ++i)
00232             {
00233                 /* recursively get all combinations in a new array */
00234                 CModelSelectionParameters* value_child=
00235                         value_children.get_element(i);
00236                 value_node_sets.append_element(value_child->get_combinations());
00237                 SG_UNREF(value_child);
00238             }
00239 
00240             /* build product of all these tree sets */
00241 
00242             /* new root node is needed for new trees, depends on current case */
00243             CParameterCombination* new_root=NULL;
00244             if (m_sgobject)
00245             {
00246                 Parameter* p=new Parameter();
00247                 p->add(&m_sgobject, m_node_name);
00248                 new_root=new CParameterCombination(p);
00249             }
00250             else
00251                 new_root=new CParameterCombination();
00252 
00253             SG_REF(new_root);
00254 
00255             CDynamicObjectArray<CParameterCombination>* value_combinations=
00256                     CParameterCombination::leaf_sets_multiplication(value_node_sets,
00257                             new_root);
00258 
00259             SG_UNREF(new_root);
00260 
00261             /* if there are no non-value sets, just use the above result */
00262             if (!non_value_children.get_num_elements())
00263                 *result=*value_combinations;
00264             /* in the other case, the non-values have also to be treated, but
00265              * combined iteratively */
00266             else
00267             {
00268                 /* extract all tree sets of non-value nodes */
00269                 CDynamicObjectArray<CDynamicObjectArray<CParameterCombination> >
00270                         non_value_combinations;
00271                 for (index_t i=0; i<non_value_children.get_num_elements(); ++i)
00272                 {
00273                     /* recursively get all combinations in a new array */
00274                     CModelSelectionParameters* non_value_child=
00275                             non_value_children.get_element(i);
00276                     non_value_combinations.append_element(
00277                             non_value_child->get_combinations());
00278                     SG_UNREF(non_value_child);
00279                 }
00280 
00281                 /* combine combinations of value and non-value nodes */
00282 
00283                 /* if there are only non-value children, nothing is combined */
00284                 if (!value_combinations->get_num_elements())
00285                 {
00286                     /* non-value children are only pasted together. However, the
00287                      * new root node is to put as root in front of all trees.
00288                      * If there were value children before, this is done by
00289                      * value_node_sets_multiplication. In this case it has to be done
00290                      * by hand. */
00291 
00292                     for (index_t j=0;
00293                             j<non_value_combinations.get_num_elements(); ++j)
00294                     {
00295                         CDynamicObjectArray<CParameterCombination>* current_non_value_set=
00296                                 non_value_combinations.get_element(j);
00297 
00298                         for (index_t k=0; k
00299                                 <current_non_value_set->get_num_elements(); ++k)
00300                         {
00301                             CParameterCombination* current_non_value_tree=
00302                                     current_non_value_set->get_element(k);
00303 
00304                             /* append new root with rest of tree to current
00305                              * tree. re-use of new_root variable, safe here */
00306                             new_root=new CParameterCombination();
00307                             new_root->append_child(current_non_value_tree);
00308                             result->append_element(new_root);
00309 
00310                             SG_UNREF(current_non_value_tree);
00311                         }
00312 
00313                         SG_UNREF(current_non_value_set);
00314                     }
00315                 }
00316                 else
00317                 {
00318                     for (index_t i=0; i<value_combinations->get_num_elements(); ++i)
00319                     {
00320                         CParameterCombination* current_value_tree=
00321                                 value_combinations->get_element(i);
00322 
00323                         for (index_t j=0; j
00324                                 <non_value_combinations.get_num_elements(); ++j)
00325                         {
00326                             CDynamicObjectArray<CParameterCombination> * current_non_value_set=
00327                                     non_value_combinations.get_element(j);
00328 
00329                             for (index_t k=0; k
00330                                     <current_non_value_set->get_num_elements(); ++k)
00331                             {
00332                                 CParameterCombination* current_non_value_tree=
00333                                         current_non_value_set->get_element(k);
00334 
00335                                 /* copy the current trees and append non-value
00336                                  * tree to value tree. Note that the root in the
00337                                  * non-value tree is already the current
00338                                  * CSGObject and therefore the non-value tree
00339                                  * copy may just be appended as child */
00340                                 CParameterCombination* value_copy=
00341                                         current_value_tree->copy_tree();
00342                                 CParameterCombination* non_value_copy=
00343                                         current_non_value_tree->copy_tree();
00344 
00345                                 value_copy->append_child(non_value_copy);
00346                                 result->append_element(value_copy);
00347 
00348                                 SG_UNREF(current_non_value_tree);
00349                             }
00350 
00351                             SG_UNREF(current_non_value_set);
00352                         }
00353 
00354                         SG_UNREF(current_value_tree);
00355                     }
00356                 }
00357             }
00358 
00359             SG_UNREF(value_combinations);
00360         }
00361         else
00362         {
00363             /* if there are no children of a sgobject or root node, result is
00364              * only one element (sgobject node) or empty (root node)
00365              */
00366             if (m_sgobject)
00367             {
00368                 Parameter* p=new Parameter();
00369                 p->add(&m_sgobject, m_node_name);
00370                 result->append_element(new CParameterCombination(p));
00371             }
00372         }
00373 
00374     }
00375     else
00376         SG_ERROR("Illegal CModelSelectionParameters node type.\n");
00377 
00378     return result;
00379 }
00380 
00381 void CModelSelectionParameters::print_tree(int prefix_num)
00382 {
00383     /* prefix is enlarged */
00384     char* prefix=SG_MALLOC(char, prefix_num+1);
00385     for (index_t i=0; i<prefix_num; ++i)
00386         prefix[i]='\t';
00387 
00388     prefix[prefix_num]='\0';
00389 
00390     if (has_children())
00391     {
00392         if (m_sgobject)
00393             SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name());
00394         else
00395             SG_PRINT("%s%s with\n", prefix, m_node_name ? m_node_name : "root");
00396 
00397         /* now recursively print successors */
00398 
00399         /* cast safe because only CModelSelectionParameters are added to list */
00400         for (index_t i=0; i<m_child_nodes->get_num_elements(); ++i)
00401         {
00402             CModelSelectionParameters* child=m_child_nodes->get_element(i);
00403             child->print_tree(prefix_num+1);
00404             SG_UNREF(child);
00405         }
00406     }
00407     else
00408     {
00409         /* has to be a node with name and a numeric range or a single sg_object
00410          * without children*/
00411         if (m_sgobject)
00412         {
00413             SG_PRINT("%s%s:\"%s\"\n", prefix, m_node_name, m_sgobject->get_name());
00414         }
00415         else
00416         {
00417 
00418             if (m_values.vector)
00419             {
00420                 /* value node */
00421                 SG_PRINT("%s%s with values: ", prefix, m_node_name);
00422 
00423                 switch (m_value_type)
00424                 {
00425                 case MSPT_FLOAT64:
00426                     CMath::display_vector((float64_t*)m_values.vector, m_values.vlen);
00427                     break;
00428                 case MSPT_INT32:
00429                     CMath::display_vector((int32_t*)m_values.vector, m_values.vlen);;
00430                     break;
00431                 case MSPT_NONE:
00432                     SG_ERROR("Value node has no type!\n");
00433                     break;
00434                 default:
00435                     SG_ERROR("Unknown type for model selection parameter!\n");
00436                     break;
00437                 }
00438             }
00439             else
00440                 SG_PRINT("root\n");
00441         }
00442     }
00443 
00444     SG_FREE(prefix);
00445 }
00446 
00447 void CModelSelectionParameters::delete_values()
00448 {
00449     if (m_values.vector)
00450     {
00451         switch (m_value_type)
00452         {
00453         case MSPT_FLOAT64:
00454             SG_FREE((float64_t*) m_values.vector);
00455             break;
00456         case MSPT_INT32:
00457             SG_FREE((int32_t*) m_values.vector);
00458             break;
00459         case MSPT_NONE:
00460             SG_ERROR("Value node has no type!\n");
00461             break;
00462         default:
00463             SG_ERROR("Unknown type for model selection parameter!\n");
00464             break;
00465         }
00466     }
00467 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation