EvolvingObjects
PyEO.cpp
00001 /*
00002     PyEO
00003 
00004     Copyright (C) 2003 Maarten Keijzer
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 */
00020 
00021 #include <sstream>
00022 
00023 #include "PyEO.h"
00024 #include <eoPop.h>
00025 
00026 using namespace std;
00027 //using namespace boost::python;
00028 
00029 // static member, needs to be instantiated somewhere
00030 std::vector<int> PyFitness::objective_info;
00031 
00032 bool PyFitness::dominates(const PyFitness& oth) const
00033 {
00034     bool dom = false;
00035 
00036     for (unsigned i = 0; i < nObjectives(); ++i)
00037         {
00038             int objective = objective_info[i];
00039 
00040             if (objective == 0) // ignore
00041                 continue;
00042 
00043             bool maxim = objective > 0;
00044 
00045             double aval = maxim? (*this)[i] : -(*this)[i];
00046             double bval = maxim? oth[i] : -oth[i];
00047 
00048             if (fabs(aval - bval) > tol())
00049                 {
00050                     if (aval < bval)
00051                         {
00052                             return false; // cannot dominate
00053                         }
00054                     // else aval < bval
00055                     dom = true; // for the moment: goto next objective
00056                 }
00057             //else they're equal in this objective, goto next
00058         }
00059 
00060     return dom;
00061 }
00062 
00063 bool dominates(const PyEO& a, const PyEO& b)
00064 {
00065     return PyFitness(a.fitness()).dominates(b.fitness());
00066 }
00067 
00068 ostream& operator<<(ostream& os, const PyEO& _eo)
00069 {
00070     os << _eo.to_string();
00071     return os;
00072 }
00073 
00074 struct pyPop_pickle_suite : boost::python::pickle_suite
00075 {
00076     static boost::python::tuple getstate(const eoPop<PyEO>& _pop)
00077     {
00078         boost::python::list entries;
00079         for (unsigned i = 0; i != _pop.size(); ++i)
00080             entries.append( PyEO_pickle_suite::getstate(_pop[i]) );
00081 
00082         return boost::python::make_tuple(boost::python::object(_pop.size()), entries);
00083     }
00084 
00085     static void setstate( eoPop<PyEO>& _pop, boost::python::tuple pickled)
00086     {
00087         int sz = boost::python::extract<int>(pickled[0]);
00088         boost::python::list entries = boost::python::list(pickled[1]);
00089         _pop.resize(sz);
00090         for (unsigned i = 0; i != _pop.size(); ++i)
00091             {
00092                 PyEO_pickle_suite::setstate(_pop[i], boost::python::tuple(entries[i]) );
00093             }
00094     }
00095 };
00096 
00097 
00098 template <class T>
00099 boost::python::str to_string(T& _p)
00100 {
00101     std::ostringstream os;
00102     _p.printOn(os);
00103     return boost::python::str(os.str().c_str());
00104 }
00105 
00106 void pop_sort(eoPop<PyEO>& pop) { pop.sort(); }
00107 void pop_shuffle(eoPop<PyEO>& pop) { pop.shuffle(); }
00108 
00109 void translate_index_error(index_error const& e)
00110 {
00111     PyErr_SetString(PyExc_IndexError, e.what.c_str());
00112 }
00113 
00114 PyEO& pop_getitem(eoPop<PyEO>& pop, boost::python::object key)
00115 {
00116     boost::python::extract<int> x(key);
00117     if (!x.check())
00118         throw index_error("Slicing not allowed");
00119 
00120     int i = x();
00121 
00122     if (static_cast<unsigned>(i) >= pop.size())
00123         {
00124             throw index_error("Index out of bounds");
00125         }
00126     return pop[i];
00127 }
00128 
00129 void pop_setitem(eoPop<PyEO>& pop, boost::python::object key, PyEO& value)
00130 {
00131     boost::python::extract<int> x(key);
00132     if (!x.check())
00133         throw index_error("Slicing not allowed");
00134 
00135     int i = x();
00136 
00137     if (static_cast<unsigned>(i) >= pop.size())
00138         {
00139             throw index_error("Index out of bounds");
00140         }
00141 
00142     pop[i] = value;
00143 }
00144 
00145 void pop_push_back(eoPop<PyEO>& pop, PyEO& p) { pop.push_back(p); }
00146 void pop_resize(   eoPop<PyEO>& pop, unsigned i) { pop.resize(i); }
00147 int pop_size(   eoPop<PyEO>& pop) { return pop.size(); }
00148 
00149 extern void abstract1();
00150 extern void algos();
00151 extern void random_numbers();
00152 extern void geneticOps();
00153 extern void selectOne();
00154 extern void continuators();
00155 extern void reduce();
00156 extern void replacement();
00157 extern void selectors();
00158 extern void breeders();
00159 extern void mergers();
00160 extern void valueParam();
00161 extern void perf2worth();
00162 extern void monitors();
00163 extern void statistics();
00164 
00165 BOOST_PYTHON_MODULE(libPyEO)
00166 {
00167     using namespace boost::python;
00168 
00169     boost::python::register_exception_translator<index_error>(&translate_index_error);
00170 
00171     boost::python::class_<PyEO>("EO")
00172         .add_property("fitness", &PyEO::getFitness, &PyEO::setFitness)
00173         .add_property("genome", &PyEO::getGenome, &PyEO::setGenome)
00174         .def_pickle(PyEO_pickle_suite())
00175         .def("invalidate", &PyEO::invalidate)
00176         .def("invalid", &PyEO::invalid)
00177         .def("__str__", &PyEO::to_string)
00178         ;
00179 
00180     boost::python::class_<eoPop<PyEO> >("eoPop", init<>() )
00181         .def( init< unsigned, eoInit<PyEO>& >()[with_custodian_and_ward<1,3>()] )
00182         .def("append", &eoPop<PyEO>::append, "docstring?")
00183         .def("__str__", to_string<eoPop<PyEO> >)
00184         .def("__len__", pop_size)
00185         .def("sort",    pop_sort )
00186         .def("shuffle", pop_shuffle)
00187         .def("__getitem__", pop_getitem, return_internal_reference<>() )
00188         .def("__setitem__", pop_setitem)
00189         .def("best", &eoPop<PyEO>::best_element, return_internal_reference<>() )
00190         .def("push_back", pop_push_back)
00191         .def("resize",    pop_resize)
00192         .def_pickle(pyPop_pickle_suite())
00193         ;
00194 
00195 
00196     // Other definitions in different compilation units,
00197     // this to avoid having g++ to choke on the load
00198     random_numbers();
00199     valueParam();
00200     abstract1();
00201     geneticOps();
00202     selectOne();
00203     selectors();
00204     perf2worth();
00205     monitors();
00206     statistics();
00207     continuators();
00208     reduce();
00209     replacement();
00210     breeders();
00211     mergers();
00212     algos();
00213 
00214     // The traits class
00215     class_<PyFitness>("PyFitness");
00216 
00217     def("nObjectives", &PyFitness::nObjectives);
00218     def("tol", &PyFitness::tol);
00219     def("maximizing", &PyFitness::maximizing);
00220     def("setObjectivesSize", &PyFitness::setObjectivesSize);
00221     def("setObjectivesValue", &PyFitness::setObjectivesValue);
00222     def("dominates", dominates);
00223 }
00224 
00225 
00226 // to avoid having to build with libeo.a
00227 ostream & operator << ( ostream& _os, const eoPrintable& _o )
00228 {
00229     _o.printOn(_os);
00230     return _os;
00231 };
 All Classes Namespaces Files Functions Variables Typedefs Friends