SHOGUN
v1.1.0
|
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 }