# 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
    00027 using namespace std;
    00028 //using namespace boost::python;
    00029
    00030 // static member, needs to be instantiated somewhere
    00031 std::vector<int> PyFitness::objective_info;
    00032
    00033 bool PyFitness::dominates(const PyFitness& oth) const
    00034 {
    00035     bool dom = false;
    00036
    00037     for (unsigned i = 0; i < nObjectives(); ++i)
    00038     {
    00039       int objective = objective_info[i];
    00040
    00041       if (objective == 0) // ignore
    00042           continue;
    00043
    00044       bool maxim = objective > 0;
    00045
    00046       double aval = maxim? (*this)[i] : -(*this)[i];
    00047       double bval = maxim? oth[i] : -oth[i];
    00048
    00049       if (fabs(aval - bval) > tol())
    00050       {
    00051         if (aval < bval)
    00052         {
    00053           return false; // cannot dominate
    00054         }
    00055         // else aval < bval
    00056         dom = true; // for the moment: goto next objective
    00057       }
    00058       //else they're equal in this objective, goto next
    00059     }
    00060
    00061     return dom;
    00062 }
    00063
    00064 bool dominates(const PyEO& a, const PyEO& b)
    00065 {
    00066     return PyFitness(a.fitness()).dominates(b.fitness());
    00067 }
    00068
    00069 ostream& operator<<(ostream& os, const PyEO& _eo)
    00070 {
    00071     os << _eo.to_string();
    00072     return os;
    00073 }
    00074
    00075 struct pyPop_pickle_suite : boost::python::pickle_suite
    00076 {
    00077     static boost::python::tuple getstate(const eoPop<PyEO>& _pop)
    00078     {
    00079         boost::python::list entries;
    00080         for (unsigned i = 0; i != _pop.size(); ++i)
    00081             entries.append( PyEO_pickle_suite::getstate(_pop[i]) );
    00082
    00083         return boost::python::make_tuple(boost::python::object(_pop.size()), entries);
    00084     }
    00085
    00086     static void setstate( eoPop<PyEO>& _pop, boost::python::tuple pickled)
    00087     {
    00088         int sz = boost::python::extract<int>(pickled[0]);
    00089         boost::python::list entries = boost::python::list(pickled[1]);
    00090         _pop.resize(sz);
    00091         for (unsigned i = 0; i != _pop.size(); ++i)
    00092         {
    00093             PyEO_pickle_suite::setstate(_pop[i], boost::python::tuple(entries[i]) );
    00094         }
    00095     }
    00096 };
    00097
    00098
    00099 template <class T>
    00100 boost::python::str to_string(T& _p)
    00101 {
    00102     std::ostringstream os;
    00103     _p.printOn(os);
    00104     return boost::python::str(os.str().c_str());
    00105 }
    00106
    00107 void pop_sort(eoPop<PyEO>& pop) { pop.sort(); }
    00108 void pop_shuffle(eoPop<PyEO>& pop) { pop.shuffle(); }
    00109
    00110 void translate_index_error(index_error const& e)
    00111 {
    00112         PyErr_SetString(PyExc_IndexError, e.what.c_str());
    00113 }
    00114
    00115 PyEO& pop_getitem(eoPop<PyEO>& pop, boost::python::object key)
    00116 {
    00117     boost::python::extract<int> x(key);
    00118     if (!x.check())
    00119         throw index_error("Slicing not allowed");
    00120
    00121     int i = x();
    00122
    00123     if (static_cast<unsigned>(i) >= pop.size())
    00124     {
    00125         throw index_error("Index out of bounds");
    00126     }
    00127     return pop[i];
    00128 }
    00129
    00130 void pop_setitem(eoPop<PyEO>& pop, boost::python::object key, PyEO& value)
    00131 {
    00132     boost::python::extract<int> x(key);
    00133     if (!x.check())
    00134         throw index_error("Slicing not allowed");
    00135
    00136     int i = x();
    00137
    00138     if (static_cast<unsigned>(i) >= pop.size())
    00139     {
    00140         throw index_error("Index out of bounds");
    00141     }
    00142
    00143     pop[i] = value;
    00144 }
    00145
    00146 void pop_push_back(eoPop<PyEO>& pop, PyEO& p) { pop.push_back(p); }
    00147 void pop_resize(   eoPop<PyEO>& pop, unsigned i) { pop.resize(i); }
    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(PyEO)
    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)
    00183         .def("__str__", to_string<eoPop<PyEO> >)
    00184         .def("__len__", &eoPop<PyEO>::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             _o.printOn(_os);
    00229                     return _os;
    00230 };