SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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_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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation