SHOGUN
v2.0.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) 1999-2009 Soeren Sonnenburg 00008 * Written (W) 1999-2008 Gunnar Raetsch 00009 * Written (W) 2012 Heiko Strathmann 00010 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00011 */ 00012 00013 #include <shogun/features/CombinedFeatures.h> 00014 #include <shogun/io/SGIO.h> 00015 #include <shogun/lib/Set.h> 00016 #include <shogun/lib/Map.h> 00017 00018 using namespace shogun; 00019 00020 CCombinedFeatures::CCombinedFeatures() 00021 : CFeatures(0) 00022 { 00023 init(); 00024 00025 feature_list=new CList(true); 00026 num_vec=0; 00027 } 00028 00029 CCombinedFeatures::CCombinedFeatures(const CCombinedFeatures & orig) 00030 : CFeatures(0) 00031 { 00032 init(); 00033 00034 feature_list=new CList(true); 00035 //todo copy features 00036 num_vec=orig.num_vec; 00037 } 00038 00039 CFeatures* CCombinedFeatures::duplicate() const 00040 { 00041 return new CCombinedFeatures(*this); 00042 } 00043 00044 CCombinedFeatures::~CCombinedFeatures() 00045 { 00046 SG_UNREF(feature_list); 00047 } 00048 00049 int32_t CCombinedFeatures::get_size() const 00050 { 00051 CFeatures* f=(CFeatures*) feature_list 00052 ->get_current_element(); 00053 if (f) 00054 { 00055 int32_t s=f->get_size(); 00056 SG_UNREF(f) 00057 return s; 00058 } 00059 else 00060 return 0; 00061 } 00062 00063 void CCombinedFeatures::list_feature_objs() 00064 { 00065 SG_INFO( "BEGIN COMBINED FEATURES LIST - "); 00066 this->list_feature_obj(); 00067 00068 CListElement* current = NULL ; 00069 CFeatures* f=get_first_feature_obj(current); 00070 00071 while (f) 00072 { 00073 f->list_feature_obj(); 00074 SG_UNREF(f); 00075 f=get_next_feature_obj(current); 00076 } 00077 00078 SG_INFO( "END COMBINED FEATURES LIST - "); 00079 } 00080 00081 bool CCombinedFeatures::check_feature_obj_compatibility(CCombinedFeatures* comb_feat) 00082 { 00083 bool result=false; 00084 00085 if (comb_feat && (this->get_num_feature_obj() == comb_feat->get_num_feature_obj()) ) 00086 { 00087 CFeatures* f1=this->get_first_feature_obj(); 00088 CFeatures* f2=comb_feat->get_first_feature_obj(); 00089 00090 if (f1 && f2 && f1->check_feature_compatibility(f2)) 00091 { 00092 SG_UNREF(f1); 00093 SG_UNREF(f2); 00094 while( ( (f1=this->get_next_feature_obj()) != NULL ) && 00095 ( (f2=comb_feat->get_next_feature_obj()) != NULL) ) 00096 { 00097 if (!f1->check_feature_compatibility(f2)) 00098 { 00099 SG_UNREF(f1); 00100 SG_UNREF(f2); 00101 SG_INFO( "not compatible, combfeat\n"); 00102 comb_feat->list_feature_objs(); 00103 SG_INFO( "vs this\n"); 00104 this->list_feature_objs(); 00105 return false; 00106 } 00107 SG_UNREF(f1); 00108 SG_UNREF(f2); 00109 } 00110 00111 SG_DEBUG( "features are compatible\n"); 00112 result=true; 00113 } 00114 else 00115 SG_WARNING( "first 2 features not compatible\n"); 00116 } 00117 else 00118 { 00119 SG_WARNING( "number of features in combined feature objects differs (%d != %d)\n", this->get_num_feature_obj(), comb_feat->get_num_feature_obj()); 00120 SG_INFO( "compare\n"); 00121 comb_feat->list_feature_objs(); 00122 SG_INFO( "vs this\n"); 00123 this->list_feature_objs(); 00124 } 00125 00126 return result; 00127 } 00128 00129 CFeatures* CCombinedFeatures::get_first_feature_obj() 00130 { 00131 return (CFeatures*) feature_list->get_first_element(); 00132 } 00133 00134 CFeatures* CCombinedFeatures::get_first_feature_obj(CListElement*& current) 00135 { 00136 return (CFeatures*) feature_list->get_first_element(current); 00137 } 00138 00139 CFeatures* CCombinedFeatures::get_next_feature_obj() 00140 { 00141 return (CFeatures*) feature_list->get_next_element(); 00142 } 00143 00144 CFeatures* CCombinedFeatures::get_next_feature_obj(CListElement*& current) 00145 { 00146 return (CFeatures*) feature_list->get_next_element(current); 00147 } 00148 00149 CFeatures* CCombinedFeatures::get_last_feature_obj() 00150 { 00151 return (CFeatures*) feature_list->get_last_element(); 00152 } 00153 00154 bool CCombinedFeatures::insert_feature_obj(CFeatures* obj) 00155 { 00156 ASSERT(obj); 00157 int32_t n=obj->get_num_vectors(); 00158 00159 if (get_num_vectors()>0 && n!=get_num_vectors()) 00160 { 00161 SG_ERROR("Number of feature vectors does not match (expected %d, " 00162 "obj has %d)\n", get_num_vectors(), n); 00163 } 00164 00165 num_vec=n; 00166 return feature_list->insert_element(obj); 00167 } 00168 00169 bool CCombinedFeatures::append_feature_obj(CFeatures* obj) 00170 { 00171 ASSERT(obj); 00172 int32_t n=obj->get_num_vectors(); 00173 00174 if (get_num_vectors()>0 && n!=get_num_vectors()) 00175 { 00176 SG_ERROR("Number of feature vectors does not match (expected %d, " 00177 "obj has %d)\n", get_num_vectors(), n); 00178 } 00179 00180 num_vec=n; 00181 return feature_list->append_element(obj); 00182 } 00183 00184 bool CCombinedFeatures::delete_feature_obj() 00185 { 00186 CFeatures* f=(CFeatures*)feature_list->delete_element(); 00187 if (f) 00188 { 00189 SG_UNREF(f); 00190 return true; 00191 } 00192 else 00193 return false; 00194 } 00195 00196 int32_t CCombinedFeatures::get_num_feature_obj() 00197 { 00198 return feature_list->get_num_elements(); 00199 } 00200 00201 void CCombinedFeatures::init() 00202 { 00203 m_parameters->add(&num_vec, "num_vec", 00204 "Number of vectors."); 00205 m_parameters->add((CSGObject**) &feature_list, 00206 "feature_list", "Feature list."); 00207 } 00208 00209 CFeatures* CCombinedFeatures::create_merged_copy(CFeatures* other) 00210 { 00211 /* TODO, if all features are the same, only one copy should be created 00212 * in memory */ 00213 SG_WARNING("Heiko Strathmann: FIXME, unefficient!\n"); 00214 00215 SG_DEBUG("entering %s::create_merged_copy()\n", get_name()); 00216 if (get_feature_type()!=other->get_feature_type() || 00217 get_feature_class()!=other->get_feature_class() || 00218 strcmp(get_name(), other->get_name())) 00219 { 00220 SG_ERROR("%s::create_merged_copy(): Features are of different type!\n", 00221 get_name()); 00222 } 00223 00224 CCombinedFeatures* casted=dynamic_cast<CCombinedFeatures*>(other); 00225 00226 if (!casted) 00227 { 00228 SG_ERROR("%s::create_merged_copy(): Could not cast object of %s to " 00229 "same type as %s\n",get_name(), other->get_name(), get_name()); 00230 } 00231 00232 if (get_num_feature_obj()!=casted->get_num_feature_obj()) 00233 { 00234 SG_ERROR("%s::create_merged_copy(): Only possible if both instances " 00235 "have the same number of sub-feature-objects\n", get_name()); 00236 } 00237 00238 CCombinedFeatures* result=new CCombinedFeatures(); 00239 CFeatures* current_this=get_first_feature_obj(); 00240 CFeatures* current_other=casted->get_first_feature_obj(); 00241 while (current_this) 00242 { 00243 result->append_feature_obj( 00244 current_this->create_merged_copy(current_other)); 00245 SG_UNREF(current_this); 00246 SG_UNREF(current_other); 00247 current_this=get_next_feature_obj(); 00248 current_other=get_next_feature_obj(); 00249 } 00250 00251 SG_DEBUG("leaving %s::create_merged_copy()\n", get_name()); 00252 return result; 00253 } 00254 00255 void CCombinedFeatures::add_subset(SGVector<index_t> subset) 00256 { 00257 SG_DEBUG("entering %s::add_subset()\n", get_name()); 00258 CSet<CFeatures*>* processed=new CSet<CFeatures*>(); 00259 00260 CFeatures* current=get_first_feature_obj(); 00261 while (current) 00262 { 00263 if (!processed->contains(current)) 00264 { 00265 /* remember that subset was added here */ 00266 current->add_subset(subset); 00267 processed->add(current); 00268 SG_DEBUG("adding subset to %s at %p\n", 00269 current->get_name(), current); 00270 } 00271 SG_UNREF(current); 00272 current=get_next_feature_obj(); 00273 } 00274 00275 /* also add subset to local stack to have it for easy access */ 00276 m_subset_stack->add_subset(subset); 00277 00278 subset_changed_post(); 00279 SG_UNREF(processed); 00280 SG_DEBUG("leaving %s::add_subset()\n", get_name()); 00281 } 00282 00283 void CCombinedFeatures::remove_subset() 00284 { 00285 SG_DEBUG("entering %s::remove_subset()\n", get_name()); 00286 CSet<CFeatures*>* processed=new CSet<CFeatures*>(); 00287 00288 CFeatures* current=get_first_feature_obj(); 00289 while (current) 00290 { 00291 if (!processed->contains(current)) 00292 { 00293 /* remember that subset was added here */ 00294 current->remove_subset(); 00295 processed->add(current); 00296 SG_DEBUG("removing subset from %s at %p\n", 00297 current->get_name(), current); 00298 } 00299 SG_UNREF(current); 00300 current=get_next_feature_obj(); 00301 } 00302 00303 /* also remove subset from local stack to have it for easy access */ 00304 m_subset_stack->remove_subset(); 00305 00306 subset_changed_post(); 00307 SG_UNREF(processed); 00308 SG_DEBUG("leaving %s::remove_subset()\n", get_name()); 00309 } 00310 00311 void CCombinedFeatures::remove_all_subsets() 00312 { 00313 SG_DEBUG("entering %s::remove_all_subsets()\n", get_name()); 00314 CSet<CFeatures*>* processed=new CSet<CFeatures*>(); 00315 00316 CFeatures* current=get_first_feature_obj(); 00317 while (current) 00318 { 00319 if (!processed->contains(current)) 00320 { 00321 /* remember that subset was added here */ 00322 current->remove_all_subsets(); 00323 processed->add(current); 00324 SG_DEBUG("removing all subsets from %s at %p\n", 00325 current->get_name(), current); 00326 } 00327 SG_UNREF(current); 00328 current=get_next_feature_obj(); 00329 } 00330 00331 /* also remove subsets from local stack to have it for easy access */ 00332 m_subset_stack->remove_all_subsets(); 00333 00334 subset_changed_post(); 00335 SG_UNREF(processed); 00336 SG_DEBUG("leaving %s::remove_all_subsets()\n", get_name()); 00337 } 00338 00339 CFeatures* CCombinedFeatures::copy_subset(SGVector<index_t> indices) 00340 { 00341 /* this is returned with the results of copy_subset of sub-features */ 00342 CCombinedFeatures* result=new CCombinedFeatures(); 00343 00344 /* map to only copy same feature objects once */ 00345 CMap<CFeatures*, CFeatures*>* processed=new CMap<CFeatures*, CFeatures*>(); 00346 CFeatures* current=get_first_feature_obj(); 00347 while (current) 00348 { 00349 CFeatures* new_element=NULL; 00350 00351 /* only copy if not done yet, otherwise, use old copy */ 00352 if (!processed->contains(current)) 00353 { 00354 new_element=current->copy_subset(indices); 00355 processed->add(current, new_element); 00356 } 00357 else 00358 { 00359 new_element=processed->get_element(current); 00360 00361 /* has to be SG_REF'ed since it will be unrefed afterwards */ 00362 SG_REF(new_element); 00363 } 00364 00365 /* add to result */ 00366 result->append_feature_obj(new_element); 00367 00368 /* clean up: copy_subset of SG_REF has to be undone */ 00369 SG_UNREF(new_element); 00370 00371 SG_UNREF(current); 00372 current=get_next_feature_obj(); 00373 } 00374 00375 SG_UNREF(processed); 00376 00377 SG_REF(result); 00378 return result; 00379 }