diff --git a/eo/src/pyeo/Makefile b/eo/src/pyeo/Makefile index 6a823a5d..3e179937 100644 --- a/eo/src/pyeo/Makefile +++ b/eo/src/pyeo/Makefile @@ -26,24 +26,25 @@ CXX = g++ #-3.2 CXXFLAGS = #-g #-DNDEBUG -CPPFLAGS = -Wall -O2 +CPPFLAGS = -Wall -O2 #-g #-O2 LDFLAGS = COMPILE = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c LINK = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -INC=-I/usr/include/python2.2 -I/usr/include/stlport -I.. -ftemplate-depth-50 +INC=-I/usr/include/python2.2 -I.. -ftemplate-depth-50 -I/usr/include/stlport OBJECTS=eoFunctorStore.o PyEO.o abstract1.o algos.o \ random_numbers.o geneticOps.o selectOne.o continuators.o\ reduce.o replacement.o selectors.o breeders.o\ - mergers.o valueParam.o perf2worth.o + mergers.o valueParam.o perf2worth.o monitors.o\ + statistics.o -all: PyEO.so +all: PyEO/PyEO.so clean: rm *.so *.o test/*.pyc -PyEO.so: $(OBJECTS) - $(LINK) -o PyEO.so $(OBJECTS) -lboost_python -lpython2.2 -shared -lstlport +PyEO/PyEO.so: $(OBJECTS) + $(LINK) -o PyEO/PyEO.so $(OBJECTS) -lboost_python -lpython2.2 -shared -lstlport eoFunctorStore.o: ../eoFunctorStore.h ../eoFunctorStore.cpp $(COMPILE) -o eoFunctorStore.o ../eoFunctorStore.cpp $(INC) diff --git a/eo/src/pyeo/Makefile.rpm b/eo/src/pyeo/Makefile.rpm index 28b4210d..dccf30ee 100644 --- a/eo/src/pyeo/Makefile.rpm +++ b/eo/src/pyeo/Makefile.rpm @@ -11,7 +11,8 @@ INC=-I/usr/include/python2.2 -I/usr/include/stlport -I.. -ftemplate-depth-50 OBJECTS=eoFunctorStore.o PyEO.o abstract1.o algos.o \ random_numbers.o geneticOps.o selectOne.o continuators.o\ reduce.o replacement.o selectors.o breeders.o\ - mergers.o valueParam.o perf2worth.o + mergers.o valueParam.o perf2worth.o monitors.o\ + statistics.o all: PyEO.so diff --git a/eo/src/pyeo/PyEO.cpp b/eo/src/pyeo/PyEO.cpp index 4c45145a..085eb728 100644 --- a/eo/src/pyeo/PyEO.cpp +++ b/eo/src/pyeo/PyEO.cpp @@ -156,6 +156,8 @@ extern void breeders(); extern void mergers(); extern void valueParam(); extern void perf2worth(); +extern void monitors(); +extern void statistics(); BOOST_PYTHON_MODULE(PyEO) { @@ -170,7 +172,7 @@ BOOST_PYTHON_MODULE(PyEO) .def("__str__", &PyEO::to_string) ; - class_ >("Pop", init<>() ) + class_ >("eoPop", init<>() ) .def( init< unsigned, eoInit& >() ) .def("append", &eoPop::append) .def("__str__", to_string >) @@ -195,6 +197,8 @@ BOOST_PYTHON_MODULE(PyEO) selectOne(); selectors(); perf2worth(); + monitors(); + statistics(); continuators(); reduce(); replacement(); diff --git a/eo/src/pyeo/PyEO.h b/eo/src/pyeo/PyEO.h index 79fcee3f..cf9a4933 100644 --- a/eo/src/pyeo/PyEO.h +++ b/eo/src/pyeo/PyEO.h @@ -23,6 +23,7 @@ #include +#include #include #include diff --git a/eo/src/pyeo/PyEO/__init__.py b/eo/src/pyeo/PyEO/__init__.py new file mode 100644 index 00000000..4e5e7d0e --- /dev/null +++ b/eo/src/pyeo/PyEO/__init__.py @@ -0,0 +1,87 @@ + +from PyEO import * + +try: + import Gnuplot +except ImportError: + print "Python support for Gnuplot not found" +else: + + class eoGnuplot1DMonitor(eoMonitor): + def __init__(self): + eoMonitor.__init__(self) + self.values = [] + self.indices = [] + self.g = Gnuplot.Gnuplot() + self.g.reset(); + + + def handleParam(self, i, param): + param = float(param) + + while len(self.values) <= i: + self.values.append( [] ) + + self.values[i].append(param) + + def __call__(self): + + l = len(self) + + if l > 3 or l == 0: + print 'Can only handle 1 to 3 params currently' + + i = 0 + for param in self: + self.handleParam(i,param) + i += 1 + + self.indices.append( len(self.indices) ) + + + data1 = Gnuplot.Data(self.indices, self.values[0], with = 'lines') + + if l == 1: + self.g.plot(data1) + else: + data2 = Gnuplot.Data(self.indices, self.values[1], with = 'lines') + + if l == 2: + self.g.plot(data1, data2) + else: + data3 = Gnuplot.Data(self.indices, self.values[2], with = 'lines') + + self.g.plot(data1, data2, data3) + +def SeperatedVolumeMonitor(eoMonitor): + def __init__(self, file): + eoMonitor.__init__(self) + self.file = file + self.initialized = None; + + def __call__(self): + pass + +class eoStat(eoStatBase, eoValueParamPy): + def __init__(self): + eoStatBase.__init__(self) + eoValueParamPy.__init__(self) + +class eoSortedStat(eoSortedStatBase, eoValueParamPy): + def __init__(self): + eoSortedStatBase.__init__(self) + eoValueParamPy.__init__(self) + +class eoAverageStat(eoStat): + def __call__(self, pop): + sum = 0.0; + for indy in pop: + sum += indy.fitness + + sum /= len(pop) + self.object = sum + +class eoBestFitnessStat(eoSortedStat): + + def __call__(self, pop): + self.object = pop[0].fitness diff --git a/eo/src/pyeo/continuators.cpp b/eo/src/pyeo/continuators.cpp index 620ae420..a7231a87 100644 --- a/eo/src/pyeo/continuators.cpp +++ b/eo/src/pyeo/continuators.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "PyEO.h" #include "def_abstract_functor.h" @@ -31,6 +33,8 @@ #define DEF2(x, i1) class_, bases > >(#x, init() ).def("__call__", &eoContinue::operator()) #define DEF3(x, i1, i2) class_, bases > >(#x, init() ).def("__call__", &eoContinue::operator()) +void add_checkpoint(); + void continuators() { /* Counters, wrappers etc */ @@ -60,4 +64,23 @@ void continuators() DEF2(eoFitContinue, object); // object is the fitness type DEF3(eoSteadyFitContinue, unsigned long, unsigned long); + + add_checkpoint(); +} + +void addContinue(eoCheckPoint& c, eoContinue& cc) { c.add(cc); } +void addMonitor(eoCheckPoint& c, eoMonitor& m) { c.add(m);} +void addStat(eoCheckPoint& c, eoStatBase& s) { c.add(s);} +void addSortedStat(eoCheckPoint& c, eoSortedStatBase& s) { c.add(s);} + +void add_checkpoint() +{ + class_, bases< eoContinue > >("eoCheckPoint", + init&>()) + .def("add", addContinue) + .def("add", addMonitor, with_custodian_and_ward<1,2>() ) + .def("add", addStat) + .def("add", addSortedStat) + .def("__call__", &eoCheckPoint::operator()) + ; } diff --git a/eo/src/pyeo/monitors.cpp b/eo/src/pyeo/monitors.cpp index 0a44521f..0b0e1734 100644 --- a/eo/src/pyeo/monitors.cpp +++ b/eo/src/pyeo/monitors.cpp @@ -18,11 +18,53 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include "PyEO.h" +class MonitorWrapper : public eoMonitor +{ + public: + PyObject* self; + list objects; + + MonitorWrapper(PyObject* p) :self(p) {} + + eoMonitor& operator()() + { + call_method(self, "__call__"); + return *this; + } + + std::string getString(int i) + { + if (static_cast(i) >= vec.size()) + { + throw index_error("Index out of bounds"); + } + + return vec[i]->getValue(); + } + + unsigned size() { return vec.size(); } +}; + void monitors() { - + /** + * Change of interface: I encountered some difficulties with + * transferring eoParams from and to Python, so now we can + * only get at the strings contained in the eoParams. + * sorry + */ + + class_("eoMonitor", init<>()) + .def("lastCall", &eoMonitor::lastCall) + .def("add", &eoMonitor::add) + .def("__call__", &MonitorWrapper::operator(), return_internal_reference<1>() ) + .def("__getitem__", &MonitorWrapper::getString, + "Returns the string value of the indexed Parameter") + .def("__len__", &MonitorWrapper::size) + ; } diff --git a/eo/src/pyeo/perf2worth.cpp b/eo/src/pyeo/perf2worth.cpp index 7c4da9af..6bf21614 100644 --- a/eo/src/pyeo/perf2worth.cpp +++ b/eo/src/pyeo/perf2worth.cpp @@ -57,12 +57,17 @@ struct CachedPerf2WorthWrapper : public eoPerf2WorthCached void perf2worth() { - numeric::array::set_module_and_type("Numeric", "ArrayType"); + //numeric::array::set_module_and_type("Numeric", "ArrayType"); - class_, Perf2WorthWrapper, boost::noncopyable>("eoPerf2Worth", init<>()) - .def("__call__", &Perf2WorthWrapper::operator()) - .def("sort_pop", &eoPerf2Worth::sort_pop) - .def("value", get_worths) + class_< + eoPerf2Worth, + Perf2WorthWrapper, + bases< eoValueParam > >, + boost::noncopyable>("eoPerf2Worth", init<>()) + + .def("__call__", &Perf2WorthWrapper::operator()) + .def("sort_pop", &eoPerf2Worth::sort_pop) + //.def("value", get_worths) ; class_, CachedPerf2WorthWrapper, bases >, boost::noncopyable> diff --git a/eo/src/pyeo/statistics.cpp b/eo/src/pyeo/statistics.cpp new file mode 100644 index 00000000..7ffac706 --- /dev/null +++ b/eo/src/pyeo/statistics.cpp @@ -0,0 +1,61 @@ +#include + +#include "PyEO.h" +#include "valueParam.h" + +class StatBaseWrapper : public eoStatBase +{ + public: + PyObject* self; + StatBaseWrapper(PyObject* p) : self(p) {} + + void operator()(const eoPop& pop) + { + call_method(self, "__call__", boost::ref(pop)); + } +}; + +class SortedStatBaseWrapper : public eoSortedStatBase +{ + public: + PyObject* self; + SortedStatBaseWrapper(PyObject* p) : self(p) {} + + void operator()(const std::vector& pop) + { + call_method(self, "__call__", boost::ref(pop)); + } +}; + +typedef std::vector eoPopView; + +const PyEO& popview_getitem(const std::vector& pop, int it) +{ + unsigned item = unsigned(it); + if (item > pop.size()) + throw index_error("too much"); + + return *pop[item]; +} + +void statistics() +{ + class_, StatBaseWrapper, boost::noncopyable> + ("eoStatBase", init<>()) + .def("lastCall", &eoStatBase::lastCall) + .def("__call__", &StatBaseWrapper::operator()) + ; + + class_< eoPopView >("eoPopView") + .def("__getitem__", popview_getitem, return_internal_reference<>() ) + .def("__len__", &eoPopView::size) + ; + + class_, SortedStatBaseWrapper, boost::noncopyable> + ("eoSortedStatBase", init<>()) + .def("lastCall", &eoSortedStatBase::lastCall) + .def("__call__", &SortedStatBaseWrapper::operator()) + ; + + +} diff --git a/eo/src/pyeo/test/maxone.py b/eo/src/pyeo/test/maxone.py index f95bc0a7..c2b6a0cf 100644 --- a/eo/src/pyeo/test/maxone.py +++ b/eo/src/pyeo/test/maxone.py @@ -8,10 +8,20 @@ print 'done' from copy import copy - +class MinimFit(float): + def __cmp__(self, other): + if other == None: # I seem to be getting None's, don't know why + return 1 + return float.__cmp__(other, self) + class EvalFunc(eoEvalFunc): def __call__(self, eo): eo.fitness = reduce(lambda x,y: x+y, eo.genome, 0) + +class MinEvalFunc(eoEvalFunc): + def __call__(self, eo): + f = reduce(lambda x,y: x+y, eo.genome, 0 ) + eo.fitness = MinimFit(f) class Init(eoInit): def __init__(self, genome_length = 10): @@ -68,7 +78,7 @@ if __name__ == '__main__': print print - pop = Pop(1, init) + pop = eoPop(1, init) pop[0] = eo; diff --git a/eo/src/pyeo/test/run_tests.sh b/eo/src/pyeo/test/run_tests.sh index dbeb34dc..f3901050 100755 --- a/eo/src/pyeo/test/run_tests.sh +++ b/eo/src/pyeo/test/run_tests.sh @@ -2,7 +2,8 @@ for i in *.py do - python $i + python $i > /dev/null + done diff --git a/eo/src/pyeo/test/test_breeders.py b/eo/src/pyeo/test/test_breeders.py index 3e022981..ae77a849 100644 --- a/eo/src/pyeo/test/test_breeders.py +++ b/eo/src/pyeo/test/test_breeders.py @@ -10,10 +10,10 @@ class TestSGA(unittest.TestCase): def runtest(self, breed): - pop = Pop(50, init) + pop = eoPop(50, init) for indy in pop: evaluate(indy) - newpop = Pop(); + newpop = eoPop(); breed(pop,newpop) @@ -33,5 +33,9 @@ class TestSGA(unittest.TestCase): self.runtest(breed) +def suite(): + return unittest.makeSuite(TestSGA,'test') + + if __name__=='__main__': unittest.main() diff --git a/eo/src/pyeo/test/test_mo.py b/eo/src/pyeo/test/test_mo.py index 11a02c03..d224fcfd 100644 --- a/eo/src/pyeo/test/test_mo.py +++ b/eo/src/pyeo/test/test_mo.py @@ -1,7 +1,115 @@ from maxone import * +from math import exp import unittest -class TestSGA(unittest.TestCase): + +class MyInit(eoInit): + def __call__(self, eo): + eo.genome = [rng().normal(), rng().normal(), rng().normal()]; + +class MyMutate(eoMonOp): + def __call__(self, eo): + + std = 0.05 + eo.genome = copy(eo.genome) + + eo.genome[0] += rng().normal() * std + eo.genome[1] += rng().normal() * std + eo.genome[2] += rng().normal() * std + return 1 + +class AnEval(eoEvalFunc): + def __init__(self): + eoEvalFunc.__init__(self) + + setObjectivesSize(2); + setObjectivesValue(0,1); + setObjectivesValue(1,1); + + def __call__(self, eo): + x = abs(eo.genome[0]) + y = abs(eo.genome[1]) + z = abs(eo.genome[2]) + + eo.fitness = [ x / (x+y+z), y /(x+y+z) ] + +import Gnuplot + +g = Gnuplot.Gnuplot() +g.reset() + +def do_plot(pop): + l1 = [] + l2 = [] + + for indy in pop: + l1.append(indy.fitness[0]) + l2.append(indy.fitness[1]) + + d = Gnuplot.Data(l1,l2, with = 'points') + + d2 = Gnuplot.Data([0,1],[1,0], with='lines') + + g.plot(d,d2) + + + +class NSGA_II(eoAlgo): + def __init__(self, ngens): + + self.cont = eoGenContinue(ngens); + + self.selectOne = eoDetTournamentSelect(2); + self.evaluate = AnEval() + self.mutate = MyMutate() + self.init = MyInit() + + self.seq = eoProportionalOp() + self.seq.add(self.mutate, 1.0) + + self.perf2worth = eoNDSorting_II() + + def __call__(self, pop): + + sz = len(pop) + i = 0 + while self.cont(pop): + newpop = eoPop() + populator = eoSelectivePopulator(pop, newpop, self.selectOne); + + while len(newpop) < sz: + self.seq(populator) + + for indy in newpop: + self.evaluate(indy) + pop.push_back(indy) + + self.perf2worth(pop) + self.perf2worth.sort_pop(pop) + + #print pop[0].fitness, pop[0].genome + pop.resize(sz) + + #worth = self.perf2worth.getValue() + #print worth[0], worth[sz-1] + + i += 1 + if i%100 == 0: + pass #do_plot(pop) + + worths = self.perf2worth.getValue() + + w0 = int(worths[0]-0.001) + + for i in range(len(pop)): + if worths[i] <= w0: + break; + + print pop[i].genome + print pop[i].fitness + + +class TestNSGA_II(unittest.TestCase): def testIndividuals(self): setObjectivesSize(2); @@ -26,12 +134,11 @@ class TestSGA(unittest.TestCase): self.failUnlessEqual(dominates(eo2, eo2), 0) def testNDSorting(self): - setObjectivesSize(2); setObjectivesValue(0,-1) setObjectivesValue(1,-1); - pop = Pop() + pop = eoPop() pop.resize(6) pop[5].fitness = [0.15,0.87] @@ -50,10 +157,20 @@ class TestSGA(unittest.TestCase): print indy.fitness - worths = srt.value() + worths = srt.getValue() print worths print type(worths) + def testNSGA_II(self): + + init = MyInit(); + evaluate = AnEval(); + pop = eoPop(25, init) + for indy in pop: evaluate(indy) + + nsga = NSGA_II(50) + nsga(pop) + if __name__=='__main__': unittest.main() diff --git a/eo/src/pyeo/test/test_pickling.py b/eo/src/pyeo/test/test_pickling.py index 8645d061..fcaf0553 100644 --- a/eo/src/pyeo/test/test_pickling.py +++ b/eo/src/pyeo/test/test_pickling.py @@ -48,7 +48,7 @@ class TestPickling(unittest.TestCase): def testPop(self): - pop = Pop(40, init) + pop = eoPop(40, init) for indy in pop: evaluate(indy) diff --git a/eo/src/pyeo/test/test_populator.py b/eo/src/pyeo/test/test_populator.py index 78846b93..a6743fda 100644 --- a/eo/src/pyeo/test/test_populator.py +++ b/eo/src/pyeo/test/test_populator.py @@ -22,7 +22,7 @@ class Xover(Crossover): class TestPopulator(unittest.TestCase): def make_pop(self): - pop = Pop(20, init) + pop = eoPop(20, init) for indy in pop: evaluate(indy) return pop @@ -57,7 +57,7 @@ class TestPopulator(unittest.TestCase): seq.add(xover, 0.8) pop = self.make_pop(); - offspring = Pop() + offspring = eoPop() sel = eoDetTournamentSelect(2) diff --git a/eo/src/pyeo/test/test_reduce.py b/eo/src/pyeo/test/test_reduce.py index d0fcd864..2ca99dc5 100644 --- a/eo/src/pyeo/test/test_reduce.py +++ b/eo/src/pyeo/test/test_reduce.py @@ -4,7 +4,7 @@ import unittest class TestReduce(unittest.TestCase): def run_test(self, ReduceClass, Arg = None): - pop = Pop(10, init) + pop = eoPop(10, init) for indy in pop: evaluate(indy) if Arg: diff --git a/eo/src/pyeo/test/test_selectone.py b/eo/src/pyeo/test/test_selectone.py index b756753c..1a25bc7f 100644 --- a/eo/src/pyeo/test/test_selectone.py +++ b/eo/src/pyeo/test/test_selectone.py @@ -9,7 +9,7 @@ class TestSGA(unittest.TestCase): def __init__(self, a): unittest.TestCase.__init__(self, a) - self.pop = Pop(4, Init()) + self.pop = eoPop(4, Init()) for i in range(len(self.pop)): self.pop[i].fitness = i; diff --git a/eo/src/pyeo/test/test_sga.py b/eo/src/pyeo/test/test_sga.py index b31a5fae..b84afe75 100644 --- a/eo/src/pyeo/test/test_sga.py +++ b/eo/src/pyeo/test/test_sga.py @@ -3,23 +3,42 @@ import unittest class TestSGA(unittest.TestCase): - def test(self): - evaluate = EvalFunc() + def dotestSGA(self, evaluate): init = Init(20) mutate = Mutate() xover = Crossover() - pop = Pop(50, init) + pop = eoPop(50, init) for indy in pop: evaluate(indy) select = eoDetTournamentSelect(3); - cont = eoGenContinue(20); - + cont1 = eoGenContinue(20); + + cont = eoCheckPoint(cont1) + + mon = eoGnuplot1DMonitor() + + avg = eoAverageStat() + bst = eoBestFitnessStat() + mon.add(avg) + mon.add(bst) + + # add it to the checkpoint + cont.add(avg) + #cont.add(mon) + cont.add(bst) + sga = eoSGA(select, xover, 0.6, mutate, 0.4, evaluate, cont); sga(pop) print pop.best() + def testSGA_Max(self): + evaluate = EvalFunc() + self.dotestSGA(evaluate) + def testSGA_Min(self): + evaluate = MinEvalFunc() + self.dotestSGA(evaluate) if __name__=='__main__': unittest.main() diff --git a/eo/src/pyeo/valueParam.cpp b/eo/src/pyeo/valueParam.cpp index 5f4e2192..86fd4fac 100644 --- a/eo/src/pyeo/valueParam.cpp +++ b/eo/src/pyeo/valueParam.cpp @@ -19,7 +19,12 @@ */ #include -#include +#include + +// Here's 'len'. Why? dunno +#include "valueParam.h" +#include + using namespace boost::python; @@ -38,31 +43,92 @@ public: std::string getValue() const { - return call_method(self, "getValue"); + return call_method(self, "getValueAsString"); } void setValue(std::string s) { - call_method(self, "setValue", s); + call_method(self, "setValueAsString", s); } }; -template T getv(const eoValueParam& v) { return v.value(); } -template void setv(eoValueParam& v, T val) { v.value() = val; } -template +template +U getv(const eoValueParam& v) { return v.value(); } + +template +void setv(eoValueParam& v, U val) { v.value() = val; } + +template <> +numeric::array getv< std::vector, numeric::array > + (const eoValueParam< std::vector >& param) +{ + const std::vector& v = param.value(); + list result; + + for (unsigned i =0; i < v.size(); ++i) + result.append(v[i]); + + return numeric::array(result); +} + +template <> +void setv< std::vector, numeric::array > + (eoValueParam< std::vector >& param, numeric::array val) +{ + std::vector& v = param.value(); + v.resize( boost::python::len(val) ); + for (unsigned i = 0; i < v.size(); ++i) + { + extract x(val[i]); + if (!x.check()) + throw std::runtime_error("double expected"); + + v[i] = x(); + } +} + +template <> +tuple getv, tuple > + (const eoValueParam< std::pair >& p) +{ + return make_tuple(p.value().first, p.value().second); +} + +template <> +void setv< std::pair, tuple > + (eoValueParam< std::pair >& p, tuple val) +{ + extract first(val[0]); + extract second(val[1]); + + if (!first.check()) + throw std::runtime_error("doubles expected"); + if (!second.check()) + throw std::runtime_error("doubles expected"); + + p.value().first = first(); + p.value().second = second(); +} + +template void define_valueParam(std::string prefix) { - class_, bases >( (prefix + "ValueParam").c_str(), init<>()) + std::string name = "eoValueParam"; + name += prefix; + + class_, bases >(name.c_str(), init<>()) .def(init()) .def(init()) .def(init()) .def(init()) - .def("getValue", &eoValueParam::getValue) + .def("getValueAsString", &eoValueParam::getValue) .def("__str__", &eoValueParam::getValue) - .def("setValue", &eoValueParam::setValue) - //.add_property("value", getv, setv) + .def("setValueAsString", &eoValueParam::setValue) + .def("getValue", getv) + .def("setValue", setv) + //.add_property("value", getv, setv) ; } @@ -70,8 +136,8 @@ void valueParam() { class_("eoParam", init<>()) .def(init< std::string, std::string, std::string, char, bool>()) - .def("getValue", &ParamWrapper::getValue) - .def("setValue", &ParamWrapper::setValue) + .def("getValueAsString", &ParamWrapper::getValue) + .def("setValueAsString", &ParamWrapper::setValue) .def("longName", &eoParam::longName, return_value_policy()) //.def("defValue", &eoParam::defValue, return_value_policy()) .def("description", &eoParam::description, return_value_policy()) @@ -79,7 +145,21 @@ void valueParam() .def("required", &eoParam::required) ; - define_valueParam("int"); - define_valueParam >("vec"); + define_valueParam("Int"); + define_valueParam("Float"); + define_valueParam, numeric::array >("Vec"); + define_valueParam< std::pair, tuple >("Pair"); + + class_ >("eoValueParamPy", init<>()) + //.def(init()) + //.def(init()) + //.def(init()) + //.def(init()) + .def("getValueAsString", &ValueParam::getValue) + .def("__str__", &ValueParam::getValue) + .def("setValueAsString", &ValueParam::setValue) + .add_property("object", &ValueParam::getObj, &ValueParam::setObj) + ; + }