\(\newcommand{\B}[1]{ {\bf #1} }\) \(\newcommand{\R}[1]{ {\rm #1} }\)
more.py#
View page sourceSteps To Add More Python Functions#
Purpose#
This section outlines the steps for adding more python functionality to cppad_py. This is done by example showing how the py_fun_new_dynamic was added. This example case was chosen because it required both changing one python function, py_independent, and adding a new python function, py_fun_new_dynamic.
Documentation#
independent#
The python file lib/python/cppad_py/independent.py
was edited to add the following syntax documentation:
cppad_py::independent ( x , dynamic )and the extra return value was documented; see adynamic.
new_dynamic#
The cpp_fun_new_dynamic documentation was added
in the file lib/python/cppad_py/fun_new_dynamic.py .
In addition, this file
was added to the file list in lib/python/cppad_py/fun.py .
Example#
The example file
example/python/core/fun_dynamic_xam.py
was added to the documentation,
below the py_independent section.
In addition, a reference to this example was added under the
example heading in the independent
documentation.
Implementation#
independent#
The independent function in lib/python/cppad_py/independent.py
was changed to handle dynamic parameters as follows:
import cppad_py
import numpy
def independent(x, dynamic = None) :
"""
ax = independent(x)
creates the indepedent numpy vector ax, with value equal numpy vector x,
and starts recording a_double operations.
"""
# convert x -> u
dtype = float
#
nx = x.size
if dynamic is None :
syntax = 'independent(x)'
u = cppad_py.utility.numpy2vec(x, dtype, nx, syntax, 'x')
av = cppad_py.cppad_swig.independent(u)
ax = cppad_py.utility.vec2numpy(av, av.size());
return ax
#
nd = dynamic.size
syntax = 'independent(x, dynamic)'
u = cppad_py.utility.numpy2vec(x, dtype, nx, syntax, 'x')
v = cppad_py.utility.numpy2vec(dynamic, dtype, nd, syntax, 'dynamic')
a_both = cppad_py.cppad_swig.independent(u, v)
ax = numpy.empty(nx, dtype=cppad_py.a_double)
adynamic = numpy.empty(nd, dtype=cppad_py.a_double)
# use copy constructor so a separate copy is made for numpy arrays
for i in range(nx) :
ax[i] = cppad_py.a_double( a_both[i] )
for i in range(nd) :
adynamic[i] = cppad_py.a_double( a_both[nx + i] )
#
return (ax, adynamic)
new_dynamic#
The following function declaration was added to the
d_fun class
in the lib/python/cppad_py/fun.py file:
def new_dynamic(self, dynamic) :
return cppad_py.d_fun_new_dynamic(self.f, dynamic)
A similar declaration was added to the a_fun class.
fun_new_dynamic.py#
The implementation of d_fun_new_dynamic and
a_fun_new_dynamic were added to the file
fun_new_dynamic.py
__init__.py#
The following code was added to the file lib/python/cppad_py/__init__.py :
from cppad_py.fun_new_dynamic import a_fun_new_dynamicfrom cppad_py.fun_new_dynamic import d_fun_new_dynamicExample#
The file example/python/core/fun_dynamic_xam.py was added
with the following contents:
fun_dynamic_xam.py.
In addition, in the file
example/python/check_all.py.inthe following text was added to the list of python example files.
'fun_dynamic_xam' ,%Testing#
You must do a git add for all of the new files before running
bin/check_all.sh
After all the changes above were implemented,
bin/check_all.sh was run and the changes were made
until the warnings and errors were fixed.
The command
grep 'fun_dynamic_xam' check_all.logwas used to make sure that the new python example / test was run.
Note that the python files in cppad_py are copies of the
python files in lib/python .
So when you fix errors during testing, you need to fix the
lib/python file.
Also note that if a particular step in bin/check_all.sh is failing,
you can just re-run that step to see if a particular fix works.
Once the tests were working, the changes where checked into using
git .