# PyEO.h

    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 #ifndef PYEO_H
    00022 #define PYEO_H
    00023
    00024
    00025 #include <string>
    00026 #include <vector>
    00027 #include <exception>
    00028 #include <boost/python.hpp>
    00029
    00030 #include <EO.h>
    00031 struct index_error : public std::exception {
    00032     index_error(std::string w) : what(w) {};
    00033     virtual ~index_error() throw() {}
    00034     std::string what;
    00035 };
    00036
    00037 class PyFitness : public boost::python::object
    00038 {
    00039     public :
    00040
    00041     typedef PyFitness fitness_traits; // it's its own traits class :-)
    00042
    00043     PyFitness() : boost::python::object() {}
    00044
    00045     template <class T>
    00046     PyFitness(const T& o) : boost::python::object(o) {}
    00047
    00048     static unsigned nObjectives() { return objective_info.size(); }
    00049     static double tol() { return 1e-6; }
    00050     static bool maximizing(int which) { return objective_info[which] > 0; }
    00051
    00052     static void setObjectivesSize(int sz) { objective_info.resize(sz, 0); }
    00053     static void setObjectivesValue(unsigned which, int value)
    00054     {
    00055         if (which >= objective_info.size())
    00056         {
    00057             throw index_error("Too few elements allocated, resize objectives first");
    00058         }
    00059
    00060         objective_info[which] = value;
    00061     }
    00062
    00063     static std::vector<int> objective_info;
    00064
    00065     bool dominates(const PyFitness& oth) const;
    00066
    00067     double operator[](int i) const
    00068     {
    00069         boost::python::extract<double> x(object::operator[](i));
    00070
    00071         if (!x.check())
    00072             throw std::runtime_error("PyFitness: does not contain doubles");
    00073         return x();
    00074     }
    00075
    00076     bool operator<(const PyFitness& other) const
    00077     {
    00078         if (objective_info.size() == 0)
    00079         {
    00080             const object& self = *this;
    00081             const object& oth = other;
    00082             return self < oth;
    00083         }
    00084         // otherwise use objective_info
    00085
    00086         for (unsigned i = 0; i < objective_info.size(); ++i)
    00087         {
    00088             double a = objective_info[i] * operator[](i);
    00089             double b = objective_info[i] * other[i];
    00090
    00091             if ( fabs(a - b) > tol())
    00092             {
    00093                 if (a < b)
    00094                     return true;
    00095                 return false;
    00096             }
    00097         }
    00098
    00099         return false;
    00100     }
    00101
    00102     bool operator>(const PyFitness& other) const
    00103     {
    00104         return other.operator<(*this);
    00105     }
    00106
    00107     void printOn(std::ostream& os) const { const boost::python::object& o = *this; boost::python::api::operator<<(os,o); }
    00108     friend std::ostream& operator<<(std::ostream& os, const PyFitness& p) { p.printOn(os); return os;  }
    00109     friend std::istream& operator>>(std::istream& is, PyFitness& p) { boost::python::object o; is >> o; p = o; return is; }
    00110 };
    00111
    00112 struct PyEO : public EO< PyFitness  >
    00113 {
    00114     typedef PyFitness Fitness;
    00115
    00116     boost::python::object getFitness() const { return invalid()? Fitness(): fitness(); }
    00117     void setFitness(boost::python::object f) { if (f == Fitness()) invalidate(); else fitness(f); }
    00118
    00119     boost::python::object getGenome() const { return genome; }
    00120     void setGenome(boost::python::object g) { genome = g; }
    00121     boost::python::object genome;
    00122
    00123     std::string to_string() const
    00124     {
    00125         std::string result;
    00126         result += boost::python::extract<const char*>(boost::python::str(getFitness()));
    00127         result += ' ';
    00128         result += boost::python::extract<const char*>(boost::python::str(genome));
    00129         return result;
    00130     }
    00131
    00132     bool operator<(const PyEO& other) const { return EO<Fitness>::operator<(other); }
    00133     bool operator>(const PyEO& other) const { return EO<Fitness>::operator>(other); }
    00134
    00135 };
    00136
    00137 std::ostream& operator<<(std::ostream& os, const PyEO& _eo);
    00138
    00139 struct PyEO_pickle_suite : boost::python::pickle_suite
    00140 {
    00141     typedef PyEO::Fitness Fitness;
    00142
    00143     static
    00144     boost::python::tuple getstate(const PyEO& _eo)
    00145     {
    00146         return boost::python::make_tuple(_eo.getFitness(), _eo.genome);
    00147     }
    00148     static
    00149     void setstate(PyEO& _eo, boost::python::tuple pickled)
    00150     {
    00151         _eo.setFitness( Fitness(pickled[0]) );
    00152         _eo.genome = pickled[1];
    00153     }
    00154 };
    00155
    00156 #endif