PLearn 0.1
HyperSetOption.cc
Go to the documentation of this file.
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines