PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // HyperSetOption.cc 00004 // 00005 // Copyright (C) 2003-2004 ApSTAT Technologies Inc. 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 // Author: Pascal Vincent 00036 00037 /* ******************************************************* 00038 * $Id: HyperSetOption.cc 7338 2007-05-25 15:37:15Z tihocan $ 00039 ******************************************************* */ 00040 00043 #include "HyperSetOption.h" 00044 #include "HyperLearner.h" 00045 00046 #define PL_LOG_MODULE_NAME "HyperSetOption" 00047 #include <plearn/io/pl_log.h> 00048 00049 namespace PLearn { 00050 using namespace std; 00051 00052 PLEARN_IMPLEMENT_OBJECT( 00053 HyperSetOption, 00054 "HyperCommand to set an object option during HyperOptimization.", 00055 "" 00056 ); 00057 00059 // HyperSetOption // 00061 HyperSetOption::HyperSetOption(): 00062 call_build(false) 00063 {} 00064 00066 // declareOptions // 00068 void HyperSetOption::declareOptions(OptionList& ol) 00069 { 00070 // TODO Deprecated 'option_name' and 'option_value'. 00071 00072 declareOption(ol, "option_name", &HyperSetOption::option_name, 00073 OptionBase::buildoption, 00074 "Name of a single option to set."); 00075 00076 declareOption(ol, "option_value", &HyperSetOption::option_value, 00077 OptionBase::buildoption, 00078 "Value 'option_name' should be set to."); 00079 00080 declareOption(ol, "options", &HyperSetOption::options, 00081 OptionBase::buildoption, 00082 "List of pairs \"optionname\":\"optionvalue\" to set."); 00083 00084 declareOption(ol, "call_build", &HyperSetOption::call_build, 00085 OptionBase::buildoption, 00086 "If set to 1, then the learner and its sub-objects will be re-built\n" 00087 "if (and only if) one of their options has been changed, or an\n" 00088 "option of one of their sub-objects has been changed."); 00089 00090 // Now call the parent class' declareOptions 00091 inherited::declareOptions(ol); 00092 } 00093 00095 // build_ // 00097 void HyperSetOption::build_() 00098 { 00099 } 00100 00102 // build // 00104 void HyperSetOption::build() 00105 { 00106 inherited::build(); 00107 build_(); 00108 } 00109 00111 // makeDeepCopyFromShallowCopy // 00113 void HyperSetOption::makeDeepCopyFromShallowCopy(CopiesMap& copies) 00114 { 00115 inherited::makeDeepCopyFromShallowCopy(copies); 00116 deepCopyField(options, copies); 00117 } 00118 00120 // optimize // 00122 Vec HyperSetOption::optimize() 00123 { 00124 TVec<string> names, values; 00125 if (option_name != "") { 00126 names.push_back(option_name); 00127 values.push_back(option_value); 00128 } 00129 for (int i=0; i<options.size(); ++i) { 00130 names.push_back(options[i].first); 00131 values.push_back(options[i].second); 00132 } 00133 hlearner->setLearnerOptions(names, values); 00134 00135 if (call_build && !names.isEmpty()) { 00136 // Call build on all objects affected by the changes. 00137 // We need to ensure this is done in the correct order. 00138 // Map each object that needs to be built to its parent. 00139 map<Object*, Object*> parent; 00140 // Map each object that needs to be built to the number of its children 00141 // that have to be built first. 00142 map<Object*, int> n_children_must_build; 00143 // Build the above maps. 00144 for (int i = 0; i < names.length(); i++) { 00145 string option = names[i]; 00146 Object* object = hlearner->getLearner(); 00147 Object* previous_object = NULL; 00148 while (true) { 00149 // Update maps if necessary. 00150 if (parent.find(object) == parent.end()) { 00151 parent[object] = previous_object; 00152 if (previous_object) 00153 n_children_must_build[previous_object]++; 00154 } 00155 if (n_children_must_build.find(object) == 00156 n_children_must_build.end()) 00157 n_children_must_build[object] = 0; 00158 // Continue to next object. 00159 size_t dot_pos = option.find('.'); 00160 if (dot_pos == string::npos) 00161 break; 00162 size_t bracket_pos = option.find(']'); 00163 bool indexed_object = (dot_pos == bracket_pos + 1); 00164 string sub_object_opt; 00165 int index = -1; 00166 if (indexed_object) { 00167 size_t left_bracket_pos = option.find('['); 00168 sub_object_opt = option.substr(0, left_bracket_pos); 00169 index = toint(option.substr(left_bracket_pos + 1, 00170 bracket_pos)); 00171 PLCHECK( index >= 0 ); 00172 } else { 00173 sub_object_opt = option.substr(0, dot_pos); 00174 } 00175 OptionList& options = object->getOptionList(); 00176 bool found = false; 00177 for (OptionList::iterator it = options.begin(); 00178 it != options.end(); ++it) 00179 { 00180 if ((*it)->optionname() == sub_object_opt) { 00181 previous_object = object; 00182 if (indexed_object) { 00183 object = (*it)->getIndexedObject(object, index); 00184 } else { 00185 object = (*it)->getAsObject(object); 00186 } 00187 found = true; 00188 break; 00189 } 00190 } 00191 if (!found) 00192 PLERROR("In HyperSetOption::optimize - Could not find " 00193 "option '%s' in an object of class '%s'", 00194 sub_object_opt.c_str(), 00195 object->classname().c_str()); 00196 option = option.substr(dot_pos + 1); 00197 } 00198 } 00199 // Build objects in the correct order. 00200 bool finished = false; 00201 size_t count_builds = 0; 00202 while (!finished) { 00203 finished = true; 00204 map<Object*, int>::iterator it = n_children_must_build.begin(); 00205 for (; it != n_children_must_build.end(); it++) { 00206 if (it->second == 0) { 00207 // This object is ready to be built. 00208 DBG_MODULE_LOG << "Building a " << it->first->classname() 00209 << endl; 00210 it->first->build(); 00211 it->second = -1; 00212 finished = false; 00213 Object* parent_obj = parent[it->first]; 00214 if (parent_obj) { 00215 PLASSERT( n_children_must_build.find(parent_obj) != 00216 n_children_must_build.end() ); 00217 n_children_must_build[parent_obj]--; 00218 } 00219 count_builds++; 00220 } 00221 } 00222 } 00223 PLASSERT( count_builds == n_children_must_build.size() ); 00224 DBG_MODULE_LOG << "All necessary builds performed" << endl; 00225 } 00226 00227 return Vec(); 00228 } 00229 00231 // getResultNames // 00233 TVec<string> HyperSetOption::getResultNames() const 00234 { 00235 return TVec<string>(); 00236 } 00237 00238 00239 } // end of namespace PLearn 00240 00241 00242 /* 00243 Local Variables: 00244 mode:c++ 00245 c-basic-offset:4 00246 c-file-style:"stroustrup" 00247 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00248 indent-tabs-mode:nil 00249 fill-column:79 00250 End: 00251 */ 00252 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :