diff --git a/src/shogun/features/CombinedFeatures.cpp b/src/shogun/features/CombinedFeatures.cpp index ecd6437d201..949f2090d7a 100644 --- a/src/shogun/features/CombinedFeatures.cpp +++ b/src/shogun/features/CombinedFeatures.cpp @@ -22,17 +22,17 @@ CCombinedFeatures::CCombinedFeatures() { init(); - feature_list=new CList(true); + feature_array = new CDynamicObjectArray(); num_vec=0; } -CCombinedFeatures::CCombinedFeatures(const CCombinedFeatures & orig) +CCombinedFeatures::CCombinedFeatures(const CCombinedFeatures& orig) : CFeatures(0) { init(); - feature_list=new CList(true); - //todo copy features + feature_array=new CDynamicObjectArray(); + //TODO copy features num_vec=orig.num_vec; } @@ -43,36 +43,38 @@ CFeatures* CCombinedFeatures::duplicate() const CCombinedFeatures::~CCombinedFeatures() { - SG_UNREF(feature_list); + SG_UNREF(feature_array); } +//TODO remove from hierarchy in future patch int32_t CCombinedFeatures::get_size() const { - CFeatures* f=(CFeatures*) feature_list - ->get_current_element(); - if (f) - { - int32_t s=f->get_size(); - SG_UNREF(f) - return s; - } - else + if (feature_array->get_num_elements()==0) return 0; + CFeatures* f = (CFeatures*) feature_array->get_element(0); + if (!f) + return 0; + int32_t size = f->get_size(); + SG_UNREF(f); + return size; } + +CFeatures* CCombinedFeatures::get_feature_obj(int32_t idx) +{ + return (CFeatures*) feature_array->get_element(idx); +} + void CCombinedFeatures::list_feature_objs() { SG_INFO("BEGIN COMBINED FEATURES LIST - ") this->list_feature_obj(); - CListElement* current = NULL ; - CFeatures* f=get_first_feature_obj(current); - - while (f) + for (index_t f_idx=0; f_idxlist_feature_obj(); SG_UNREF(f); - f=get_next_feature_obj(current); } SG_INFO("END COMBINED FEATURES LIST - ") @@ -82,37 +84,29 @@ bool CCombinedFeatures::check_feature_obj_compatibility(CCombinedFeatures* comb_ { bool result=false; - if (comb_feat && (this->get_num_feature_obj() == comb_feat->get_num_feature_obj()) ) + if ( (comb_feat) && (this->get_num_feature_obj() == comb_feat->get_num_feature_obj()) ) { - CFeatures* f1=this->get_first_feature_obj(); - CFeatures* f2=comb_feat->get_first_feature_obj(); - - if (f1 && f2 && f1->check_feature_compatibility(f2)) + for (index_t f_idx=0; f_idxget_next_feature_obj()) != NULL ) && - ( (f2=comb_feat->get_next_feature_obj()) != NULL) ) + CFeatures* f1=this->get_feature_obj(f_idx); + CFeatures* f2=comb_feat->get_feature_obj(f_idx); + + if ( ! (f1 && f2 && f1->check_feature_compatibility(f2)) ) { - if (!f1->check_feature_compatibility(f2)) - { - SG_UNREF(f1); - SG_UNREF(f2); - SG_INFO("not compatible, combfeat\n") - comb_feat->list_feature_objs(); - SG_INFO("vs this\n") - this->list_feature_objs(); - return false; - } SG_UNREF(f1); SG_UNREF(f2); + SG_INFO("not compatible, combfeat\n") + comb_feat->list_feature_objs(); + SG_INFO("vs this\n") + this->list_feature_objs(); + return false; } - - SG_DEBUG("features are compatible\n") - result=true; + + SG_UNREF(f1); + SG_UNREF(f2); } - else - SG_WARNING("first 2 features not compatible\n") + SG_DEBUG("features are compatible\n") + result=true; } else { @@ -128,30 +122,15 @@ bool CCombinedFeatures::check_feature_obj_compatibility(CCombinedFeatures* comb_ CFeatures* CCombinedFeatures::get_first_feature_obj() { - return (CFeatures*) feature_list->get_first_element(); -} - -CFeatures* CCombinedFeatures::get_first_feature_obj(CListElement*& current) -{ - return (CFeatures*) feature_list->get_first_element(current); -} - -CFeatures* CCombinedFeatures::get_next_feature_obj() -{ - return (CFeatures*) feature_list->get_next_element(); -} - -CFeatures* CCombinedFeatures::get_next_feature_obj(CListElement*& current) -{ - return (CFeatures*) feature_list->get_next_element(current); + return get_feature_obj(0); } CFeatures* CCombinedFeatures::get_last_feature_obj() { - return (CFeatures*) feature_list->get_last_element(); + return get_feature_obj(get_num_feature_obj()-1); } -bool CCombinedFeatures::insert_feature_obj(CFeatures* obj) +bool CCombinedFeatures::insert_feature_obj(CFeatures* obj, int32_t idx) { ASSERT(obj) int32_t n=obj->get_num_vectors(); @@ -163,47 +142,30 @@ bool CCombinedFeatures::insert_feature_obj(CFeatures* obj) } num_vec=n; - return feature_list->insert_element(obj); + return feature_array->insert_element(obj, idx); } bool CCombinedFeatures::append_feature_obj(CFeatures* obj) { - ASSERT(obj) - int32_t n=obj->get_num_vectors(); - - if (get_num_vectors()>0 && n!=get_num_vectors()) - { - SG_ERROR("Number of feature vectors does not match (expected %d, " - "obj has %d)\n", get_num_vectors(), n); - } - - num_vec=n; - return feature_list->append_element(obj); + return insert_feature_obj(obj, get_num_feature_obj()); } -bool CCombinedFeatures::delete_feature_obj() +bool CCombinedFeatures::delete_feature_obj(int32_t idx) { - CFeatures* f=(CFeatures*)feature_list->delete_element(); - if (f) - { - SG_UNREF(f); - return true; - } - else - return false; + return feature_array->delete_element(idx); } int32_t CCombinedFeatures::get_num_feature_obj() { - return feature_list->get_num_elements(); + return feature_array->get_num_elements(); } void CCombinedFeatures::init() { m_parameters->add(&num_vec, "num_vec", "Number of vectors."); - m_parameters->add((CSGObject**) &feature_list, - "feature_list", "Feature list."); + m_parameters->add((CSGObject**) &feature_array, + "feature_array", "Feature array."); } CFeatures* CCombinedFeatures::create_merged_copy(CFeatures* other) @@ -236,16 +198,15 @@ CFeatures* CCombinedFeatures::create_merged_copy(CFeatures* other) } CCombinedFeatures* result=new CCombinedFeatures(); - CFeatures* current_this=get_first_feature_obj(); - CFeatures* current_other=casted->get_first_feature_obj(); - while (current_this) + for (index_t f_idx=0; f_idxget_feature_obj(f_idx); + result->append_feature_obj( current_this->create_merged_copy(current_other)); SG_UNREF(current_this); SG_UNREF(current_other); - current_this=get_next_feature_obj(); - current_other=get_next_feature_obj(); } SG_DEBUG("leaving %s::create_merged_copy()\n", get_name()) @@ -257,9 +218,10 @@ void CCombinedFeatures::add_subset(SGVector subset) SG_DEBUG("entering %s::add_subset()\n", get_name()) CSet* processed=new CSet(); - CFeatures* current=get_first_feature_obj(); - while (current) - { + for (index_t f_idx=0; f_idxcontains(current)) { /* remember that subset was added here */ @@ -269,7 +231,6 @@ void CCombinedFeatures::add_subset(SGVector subset) current->get_name(), current); } SG_UNREF(current); - current=get_next_feature_obj(); } /* also add subset to local stack to have it for easy access */ @@ -285,9 +246,9 @@ void CCombinedFeatures::remove_subset() SG_DEBUG("entering %s::remove_subset()\n", get_name()) CSet* processed=new CSet(); - CFeatures* current=get_first_feature_obj(); - while (current) + for (index_t f_idx=0; f_idxcontains(current)) { /* remember that subset was added here */ @@ -297,7 +258,6 @@ void CCombinedFeatures::remove_subset() current->get_name(), current); } SG_UNREF(current); - current=get_next_feature_obj(); } /* also remove subset from local stack to have it for easy access */ @@ -313,9 +273,9 @@ void CCombinedFeatures::remove_all_subsets() SG_DEBUG("entering %s::remove_all_subsets()\n", get_name()) CSet* processed=new CSet(); - CFeatures* current=get_first_feature_obj(); - while (current) + for (index_t f_idx=0; f_idxcontains(current)) { /* remember that subset was added here */ @@ -325,7 +285,6 @@ void CCombinedFeatures::remove_all_subsets() current->get_name(), current); } SG_UNREF(current); - current=get_next_feature_obj(); } /* also remove subsets from local stack to have it for easy access */ @@ -343,9 +302,10 @@ CFeatures* CCombinedFeatures::copy_subset(SGVector indices) /* map to only copy same feature objects once */ CMap* processed=new CMap(); - CFeatures* current=get_first_feature_obj(); - while (current) + for (index_t f_idx=0; f_idx indices) SG_UNREF(new_element); SG_UNREF(current); - current=get_next_feature_obj(); } SG_UNREF(processed); diff --git a/src/shogun/features/CombinedFeatures.h b/src/shogun/features/CombinedFeatures.h index f75eb0abbc1..2ca9d2104d7 100644 --- a/src/shogun/features/CombinedFeatures.h +++ b/src/shogun/features/CombinedFeatures.h @@ -14,13 +14,12 @@ #define _CCOMBINEDFEATURES__H__ #include -#include +#include namespace shogun { -class CFeatures; -class CList; -class CListElement; +class CFeatures; +class CDynamicObjectArray; /** @brief The class CombinedFeatures is used to combine a number of of feature objects * into a single CombinedFeatures object. @@ -78,7 +77,7 @@ class CCombinedFeatures : public CFeatures return m_subset_stack->has_subsets() ? m_subset_stack->get_size() : num_vec; } - + /** get memory footprint of one feature * * @return memory footprint of one feature @@ -100,26 +99,13 @@ class CCombinedFeatures : public CFeatures * @return first feature object */ CFeatures* get_first_feature_obj(); - - /** get first feature object - * - * @param current list of features - * @return first feature object - */ - CFeatures* get_first_feature_obj(CListElement*& current); - - /** get next feature object - * - * @return next feature object - */ - CFeatures* get_next_feature_obj(); - - /** get next feature object - * - * @param current list of features - * @return next feature object - */ - CFeatures* get_next_feature_obj(CListElement*& current); + + /** get feature object at index idx + * + * @param idx index of feature object + * @return the feature object at index idx + */ + CFeatures* get_feature_obj(int32_t idx); /** get last feature object * @@ -127,25 +113,28 @@ class CCombinedFeatures : public CFeatures */ CFeatures* get_last_feature_obj(); - /** insert feature object + /** insert feature object at index idx * * @param obj feature object to insert + * @param idx the index where to insert the feature object * @return if inserting was successful */ - bool insert_feature_obj(CFeatures* obj); + bool insert_feature_obj(CFeatures* obj, int32_t idx); - /** append feature object + /** append feature object to the end of this CombinedFeatures object array + * convience method for insert_feature_obj(obj, get_num_feature_obj()) * * @param obj feature object to append * @return if appending was successful */ bool append_feature_obj(CFeatures* obj); - /** delete feature object + /** delete feature object at position idx * + * @param idx the index of the feature object to delete * @return if deleting was successful */ - bool delete_feature_obj(); + bool delete_feature_obj(int32_t idx); /** get number of feature objects * @@ -204,8 +193,8 @@ class CCombinedFeatures : public CFeatures void init(); protected: - /** feature list */ - CList* feature_list; + /* feature array */ + CDynamicObjectArray* feature_array; /** number of vectors * must match between sub features diff --git a/src/shogun/kernel/CombinedKernel.cpp b/src/shogun/kernel/CombinedKernel.cpp index 838b9f7a0ac..ecfcd2ef59e 100644 --- a/src/shogun/kernel/CombinedKernel.cpp +++ b/src/shogun/kernel/CombinedKernel.cpp @@ -101,16 +101,15 @@ bool CCombinedKernel::init(CFeatures* l, CFeatures* r) CKernel* k=NULL; bool result=true; - - CListElement* lfc = NULL; - CListElement* rfc = NULL; - lf=((CCombinedFeatures*) l)->get_first_feature_obj(lfc); - rf=((CCombinedFeatures*) r)->get_first_feature_obj(rfc); + index_t f_idx = 0; SG_DEBUG("Starting for loop for kernels\n") for (index_t k_idx=0; k_idxget_feature_obj(f_idx); + rf = ((CCombinedFeatures*) r)->get_feature_obj(f_idx); + f_idx++; // skip over features - the custom kernel does not need any if (k->get_kernel_type() != K_CUSTOM) @@ -124,12 +123,7 @@ bool CCombinedKernel::init(CFeatures* l, CFeatures* r) } SG_DEBUG("Initializing 0x%p - \"%s\"\n", this, k->get_name()) - result=k->init(lf,rf); - SG_UNREF(lf); - SG_UNREF(rf); - - lf=((CCombinedFeatures*) l)->get_next_feature_obj(lfc) ; - rf=((CCombinedFeatures*) r)->get_next_feature_obj(rfc) ; + result=k->init(lf,rf); } else { @@ -143,7 +137,8 @@ bool CCombinedKernel::init(CFeatures* l, CFeatures* r) } SG_UNREF(k); - k = NULL; + SG_UNREF(lf); + SG_UNREF(rf); } if (!result) @@ -156,13 +151,9 @@ bool CCombinedKernel::init(CFeatures* l, CFeatures* r) return false; } - if ((lf!=NULL) || (rf!=NULL) || (k!=NULL)) - { - SG_UNREF(lf); - SG_UNREF(rf); - SG_UNREF(k); + if ( (f_idx!=((CCombinedFeatures*) l)->get_num_feature_obj()) || + (f_idx!=((CCombinedFeatures*) r)->get_num_feature_obj()) ) SG_ERROR("CombinedKernel: Number of features/kernels does not match - bailing out\n") - } init_normalizer(); initialized=true; diff --git a/src/shogun/kernel/ProductKernel.cpp b/src/shogun/kernel/ProductKernel.cpp index abe0c1f04e4..ace6b47bab5 100644 --- a/src/shogun/kernel/ProductKernel.cpp +++ b/src/shogun/kernel/ProductKernel.cpp @@ -45,18 +45,19 @@ bool CProductKernel::init(CFeatures* l, CFeatures* r) bool result=true; - CListElement* lfc = NULL; - CListElement* rfc = NULL; - lf=((CCombinedFeatures*) l)->get_first_feature_obj(lfc); - rf=((CCombinedFeatures*) r)->get_first_feature_obj(rfc); CListElement* current = NULL; k=get_first_kernel(current); + + index_t f_idx=0; while ( result && k ) { // skip over features - the custom kernel does not need any if (k->get_kernel_type() != K_CUSTOM) { + lf=((CCombinedFeatures*) l)->get_feature_obj(f_idx); + rf=((CCombinedFeatures*) r)->get_feature_obj(f_idx); + f_idx++; if (!lf || !rf) { SG_UNREF(lf); @@ -67,11 +68,6 @@ bool CProductKernel::init(CFeatures* l, CFeatures* r) SG_DEBUG("Initializing 0x%p - \"%s\"\n", this, k->get_name()) result=k->init(lf,rf); - SG_UNREF(lf); - SG_UNREF(rf); - - lf=((CCombinedFeatures*) l)->get_next_feature_obj(lfc) ; - rf=((CCombinedFeatures*) r)->get_next_feature_obj(rfc) ; } else { @@ -85,6 +81,8 @@ bool CProductKernel::init(CFeatures* l, CFeatures* r) } SG_UNREF(k); + SG_UNREF(lf); + SG_UNREF(rf); k=get_next_kernel(current) ; } @@ -98,10 +96,9 @@ bool CProductKernel::init(CFeatures* l, CFeatures* r) return false; } - if ((lf!=NULL) || (rf!=NULL) || (k!=NULL)) + if ( (f_idx!=((CCombinedFeatures*) l)->get_num_feature_obj()) || + (f_idx!=((CCombinedFeatures*) r)->get_num_feature_obj()) ) { - SG_UNREF(lf); - SG_UNREF(rf); SG_UNREF(k); SG_ERROR("ProductKernel: Number of features/kernels does not match - bailing out\n") } diff --git a/src/shogun/ui/GUIFeatures.cpp b/src/shogun/ui/GUIFeatures.cpp index 8ef46157175..4e8698954e6 100644 --- a/src/shogun/ui/GUIFeatures.cpp +++ b/src/shogun/ui/GUIFeatures.cpp @@ -280,7 +280,7 @@ bool CGUIFeatures::set_convert_features(CFeatures* features, char* target) if (features_prev->get_feature_class()==C_COMBINED) { CCombinedFeatures* combined=(CCombinedFeatures*) features_prev; - combined->delete_feature_obj(); + combined->delete_feature_obj(combined->get_num_feature_obj()-1); combined->append_feature_obj(features); combined->list_feature_objs(); } @@ -695,7 +695,7 @@ bool CGUIFeatures::del_last_feature_obj(char* target) else SG_ERROR("Unknown target %s, neither TRAIN nor TEST.\n", target) - if (!cf->delete_feature_obj()) + if (!cf->delete_feature_obj(cf->get_num_feature_obj()-1)) SG_ERROR("No features available to delete.\n") return false; diff --git a/src/shogun/ui/GUIPreprocessor.cpp b/src/shogun/ui/GUIPreprocessor.cpp index cece7ec98f0..a53323009c3 100644 --- a/src/shogun/ui/GUIPreprocessor.cpp +++ b/src/shogun/ui/GUIPreprocessor.cpp @@ -162,32 +162,32 @@ bool CGUIPreprocessor::attach_preproc(char* target, bool do_force) { if (((CCombinedFeatures*) f_train)->check_feature_obj_compatibility((CCombinedFeatures*) f_test)) { - //preprocess the last test feature obj - CFeatures* te_feat=((CCombinedFeatures*) f_test)->get_first_feature_obj(); - CFeatures* tr_feat=((CCombinedFeatures*) f_train)->get_first_feature_obj(); - + int32_t num_combined=((CCombinedFeatures*) f_test)->get_num_feature_obj(); ASSERT(((CCombinedFeatures*) f_train)->get_num_feature_obj()==num_combined) - if (!(num_combined && tr_feat && te_feat)) + if (!num_combined) SG_ERROR("One of the combined features has no sub-features ?!\n") - + + //preprocess the last test feature obj SG_INFO("BEGIN PREPROCESSING COMBINED FEATURES (%d sub-featureobjects).\n", num_combined) + index_t f_idx = 0; + for (; f_idxget_feature_obj(f_idx); + CFeatures* tr_feat=((CCombinedFeatures*) f_train)->get_feature_obj(f_idx); + + if (!(te_feat && tr_feat)) + break; - int32_t n=0; - while (nlist_feature_obj(); SG_INFO("TEST ") te_feat->list_feature_obj(); - preprocess_features(tr_feat, te_feat, do_force); - tr_feat=((CCombinedFeatures*) f_train)->get_next_feature_obj(); - te_feat=((CCombinedFeatures*) f_test)->get_next_feature_obj(); - n++; + preprocess_features(tr_feat, te_feat, do_force); } - ASSERT(n==num_combined) + ASSERT(f_idx==num_combined) result=true; SG_INFO("END PREPROCESSING COMBINED FEATURES\n") }