EvolvingObjects
|
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 };