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