User-Supplied Functions

User functions are used with many PyIMSL functions to allow the developer to specify a custom function to be evaluated, such as when performing optimization. User functions are defined as standard Python routines before calling the PyIMSL routine. The function name is passed as a normal argument to the wrapper. For example, to call the minUncon function, which requires a user function as the first argument, the code would look like:

# Define the user function
def fcn(x):
    return x*(pow(x,3)-1.0) + 10.0

# Call the IMSL routine and pass the function as a parameter
result = minUncon (fcn, ...)

When a user supplied function is used in the PyIMSL library, the data passed can be in the form of scalars (int, float, complex) or arrays of these types. When arrays are passed they do not take the form of Python lists or NumPy ndarrays, but rather are passed as Python ctype arrays. In general such arrays can be indexed as one dimensional arrays as with other data structures, but if you want to call a routine that does not accept ctype arguments such as another PyIMSL routine, you must convert these arrays before calling the routine and then convert back to ctypes afterward. This can be accomplished easily using two utility routines from the pyimsl.util.imslConvert module as shown in this example:

from numpy import *
from pyimsl.util.imslConvert import toCtypes
from pyimsl.math.linSolDefCg import linSolDefCg
from pyimsl.math.matMulRect import matMulRect
from pyimsl.math.writeMatrix import writeMatrix
from pyimsl.util.imslConvert import toNdarray

n = 3
a = [[ 1.0, -3.0,  2.0],
     [-3.0, 10.0, -5.0],
     [ 2.0, -5.0,  6.0]]
def amultp (p,z):             # A user supplied function for linSolDegCg
    ptmp = toNdarray(p, (n))  # Convert from ctype to ndarray
    ztmp=matMulRect("Ax",     # Call another IMSL routine with ndarray
                    aMatrix = a,
                    xVector = ptmp)
    toCtypes(ztmp, z)         # Copy results from ndarray back into ctype
b = [27.0, -78.0, 64.0]
x = linSolDefCg (amultp, b)
writeMatrix ("x", x)

All values returned by user-supplied functions must be valid real numbers. It is the user’s responsibility to check that the values returned by a user-supplied function do not contain NaN, infinity, or negative infinity values.