From 0c85180b6266f6a6f36dd78110e652c4bb71ea56 Mon Sep 17 00:00:00 2001 From: jutke Date: Fri, 4 Mar 2016 15:53:28 -0600 Subject: [PATCH 1/2] implement the condeqassign newly added to adolc in order to cover conditions such as <= and >= with condassign rather than just < and > --- adolc/src/py_adolc.cpp | 23 +++++++ adolc/src/py_adolc.hpp | 10 ++- adolc/tests/test_wrapped_functions.py | 65 +++++++++++++++++++ adolc/wrapped_functions.py | 29 +++++++++ .../adolc_tiny_unit_test/test_adolc.cpp | 34 ++++++++++ 5 files changed, 160 insertions(+), 1 deletion(-) diff --git a/adolc/src/py_adolc.cpp b/adolc/src/py_adolc.cpp index 4cb59a1..20c668c 100755 --- a/adolc/src/py_adolc.cpp +++ b/adolc/src/py_adolc.cpp @@ -69,6 +69,29 @@ adouble wrapped_condassign_adouble_if_else(adouble &res, const adouble &cond, co return res; } +double wrapped_condeqassign_double_if(double res, const double cond, const double arg1){ + // printf("res = %f\ncond = %f\narg1=%f",res,cond,arg1); + condeqassign(res,cond,arg1); + // printf("after assign res= %f\n",res); + return res; +} + +double wrapped_condeqassign_double_if_else(double res, const double cond, const double arg1, const double arg2){ + // printf("res = %f\ncond = %f\narg1=%f\narg2=%f\n",res,cond,arg1,arg2); + condeqassign(res,cond,arg1,arg2); + // printf("after assign res= %f\n",res); + return res; +} + +adouble wrapped_condeqassign_adouble_if(adouble &res, const adouble &cond, const adouble &arg1){ + condeqassign(res,cond,arg1); + return res; +} +adouble wrapped_condeqassign_adouble_if_else(adouble &res, const adouble &cond, const adouble &arg1, const adouble &arg2){ + condeqassign(res,cond,arg1,arg2); + return res; +} + /* C STYLE CALLS OF FUNCTIONS */ diff --git a/adolc/src/py_adolc.hpp b/adolc/src/py_adolc.hpp index 7aceda5..77fb302 100755 --- a/adolc/src/py_adolc.hpp +++ b/adolc/src/py_adolc.hpp @@ -66,8 +66,11 @@ double wrapped_condassign_double_if_else(double res, const double cond, const do adouble wrapped_condassign_adouble_if(adouble &res, const adouble &cond, const adouble &arg1); adouble wrapped_condassign_adouble_if_else(adouble &res, const adouble &cond, const adouble &arg1, const adouble &arg2); +double wrapped_condeqassign_double_if(double res, const double cond, const double arg1); +double wrapped_condeqassign_double_if_else(double res, const double cond, const double arg1, const double arg2); - +adouble wrapped_condeqassign_adouble_if(adouble &res, const adouble &cond, const adouble &arg1); +adouble wrapped_condeqassign_adouble_if_else(adouble &res, const adouble &cond, const adouble &arg1, const adouble &arg2); /* THIN WRAPPER FOR OVERLOADED FUNCTIONS */ int trace_on_default_argument(short tape_tag){ return trace_on(tape_tag,0);} @@ -278,6 +281,11 @@ BOOST_PYTHON_MODULE(_adolc) def("condassign", &wrapped_condassign_adouble_if); def("condassign", &wrapped_condassign_adouble_if_else); + def("condeqassign", &wrapped_condeqassign_double_if); + def("condeqassign", &wrapped_condeqassign_double_if_else); + def("condeqassign", &wrapped_condeqassign_adouble_if); + def("condeqassign", &wrapped_condeqassign_adouble_if_else); + class_("badouble", init()) .def(boost::python::self_ns::str(self)) diff --git a/adolc/tests/test_wrapped_functions.py b/adolc/tests/test_wrapped_functions.py index 215c0d7..f3e682c 100644 --- a/adolc/tests/test_wrapped_functions.py +++ b/adolc/tests/test_wrapped_functions.py @@ -220,6 +220,38 @@ def test_double_condassign_if_else(self): x = condassign(x,cond,y,z) assert x == 5 + def test_double_condeqassign_if(self): + x = 3. + y = 4. + cond = 0. + + x = condeqassign(x,cond,y) + print x + assert_almost_equal(x,4.) + + x = 3. + y = 4. + cond = -1. + x = condeqassign(x,cond,y) + print x + assert_almost_equal(x,3.) + + def test_double_condeqassign_if_else(self): + x = 3. + y = 4. + z = 5. + cond = 0. + + x = condeqassign(x,cond,y,z) + assert x == 4. + + x = 3. + y = 4. + z = 5. + cond = -1. + + x = condeqassign(x,cond,y,z) + assert x == 5 def test_adouble_condassign_if(self): x = adouble(3.) @@ -237,6 +269,21 @@ def test_adouble_condassign_if(self): print x assert_almost_equal(x.val, 3.) + def test_adouble_condeqassign_if(self): + x = adouble(3.) + y = adouble(4.) + cond = adouble(0.) + + x = condeqassign(x,cond,y) + print x + assert_almost_equal(x.val, 4.) + + x = adouble(3.) + y = adouble(4.) + cond = adouble(-3.) + x = condeqassign(x,cond,y) + print x + assert_almost_equal(x.val, 3.) def test_xuchen_condassign(self): """ @@ -288,6 +335,24 @@ def test_adouble_condassign_if_else(self): print x assert_almost_equal(x.val, 5.) + def test_adouble_condeqassign_if_else(self): + x = adouble(3.) + y = adouble(4.) + z = adouble(5.) + cond = adouble(0.) + + x = condeqassign(x,cond,y,z) + print x + assert_almost_equal(x.val, 4.) + + x = adouble(3.) + y = adouble(4.) + z = adouble(5.) + cond = adouble(-3.) + + x = condeqassign(x,cond,y,z) + print x + assert_almost_equal(x.val, 5.) class CorrectnessTests(TestCase): def test_sin(self): diff --git a/adolc/wrapped_functions.py b/adolc/wrapped_functions.py index 96dfd78..b291583 100644 --- a/adolc/wrapped_functions.py +++ b/adolc/wrapped_functions.py @@ -667,6 +667,35 @@ def c(v): z = c(z) return _adolc.condassign(x, cond, y, z) +def condeqassign(x, cond, y, z = None): + """ + + x = condeqassign(cond, y, z = None) + + equivalent to: + if cond: + x = y + + else: + if z != None: + x = z + + """ + + def c(v): + if isinstance(v, _adolc.adub): + return _adolc.adouble(v) + return v + + x = c(x) + cond = c(cond) + y = c(y) + + if z == None: + return _adolc.condeqassign(x, cond, y) + else: + z = c(z) + return _adolc.condeqassign(x, cond, y, z) def tape_to_latex(tape_tag,x,y): """ diff --git a/tests/misc_tests/adolc_tiny_unit_test/test_adolc.cpp b/tests/misc_tests/adolc_tiny_unit_test/test_adolc.cpp index 77a7c8e..d37d552 100644 --- a/tests/misc_tests/adolc_tiny_unit_test/test_adolc.cpp +++ b/tests/misc_tests/adolc_tiny_unit_test/test_adolc.cpp @@ -23,6 +23,22 @@ int test_condassign_on_adouble(){ return 0; } +int test_condeqassign_on_adouble(){ + adouble a(2.); + adouble cond(0.); + adouble cond2(-3.); + adouble b(4.); + adouble c(5.); + + condeqassign(a,cond,b,c); + if(a != b)return -1; + + condeqassign(a,cond2,b,c); + if(a != c)return -1; + + return 0; +} + int test_condassign_on_double(){ double a(2.); double cond(3.); @@ -39,6 +55,22 @@ int test_condassign_on_double(){ return 0; } +int test_condeqassign_on_double(){ + double a(2.); + double cond(0.); + double cond2(-3.); + double b(4.); + double c(5.); + + condeqassign(a,cond,b,c); + if(a != b) return -1; + + condeqassign(a,cond2,b,c); + if(a != c) return -1; + + return 0; +} + void check(int error, string test_name){ if(error != 0){ cout<<"Test "< Date: Wed, 9 Mar 2016 07:37:59 -0600 Subject: [PATCH 2/2] expand the cond(eq)assign testing to verify the actual cutoff being reflected in the trace-based function evaluation --- adolc/tests/test_wrapped_functions.py | 36 ++++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/adolc/tests/test_wrapped_functions.py b/adolc/tests/test_wrapped_functions.py index f3e682c..dbae349 100644 --- a/adolc/tests/test_wrapped_functions.py +++ b/adolc/tests/test_wrapped_functions.py @@ -254,13 +254,19 @@ def test_double_condeqassign_if_else(self): assert x == 5 def test_adouble_condassign_if(self): - x = adouble(3.) + trace_on(1) + x = independent(adouble(3.)) y = adouble(4.) - cond = adouble(1.) - - x = condassign(x,cond,y) - print x - assert_almost_equal(x.val, 4.) + cond = adouble(x-1.) + r = dependent(condassign(x,cond,y)) + trace_off() + assert_almost_equal(r.val, 4.) + y_arr = function(1,numpy.array([3.0])) + assert_almost_equal(y_arr[0],4.0) + y_arr = function(1,numpy.array([1.0])) + assert_almost_equal(y_arr[0],1.0) + y_arr = function(1,numpy.array([.5])) + assert_almost_equal(y_arr[0],.5) x = adouble(3.) y = adouble(4.) @@ -270,13 +276,19 @@ def test_adouble_condassign_if(self): assert_almost_equal(x.val, 3.) def test_adouble_condeqassign_if(self): - x = adouble(3.) + trace_on(1) + x = independent(adouble(3.)) y = adouble(4.) - cond = adouble(0.) - - x = condeqassign(x,cond,y) - print x - assert_almost_equal(x.val, 4.) + cond = adouble(x-1.) + r = dependent(condeqassign(x,cond,y)) + trace_off() + assert_almost_equal(r.val, 4.) + y_arr = function(1,numpy.array([3.0])) + assert_almost_equal(y_arr[0],4.0) + y_arr = function(1,numpy.array([1.0])) + assert_almost_equal(y_arr[0],4.0) + y_arr = function(1,numpy.array([.5])) + assert_almost_equal(y_arr[0],.5) x = adouble(3.) y = adouble(4.)