CombinedFeatures.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) 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation