more.py#

View page source

Steps 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:

      ( ax , adynamic ) = 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_dynamic
from cppad_py.fun_new_dynamic import d_fun_new_dynamic

Example#

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.in

the 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.log

was 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 .