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

SHOGUN Machine Learning Toolbox - Documentation