Skip to main content

NAO


NAO Class NAExpressionFunction

Overview


An ExpressionFunction is a function that is defined at runtime, by way of a character string containing an expression for the function. For example,
  f=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");
defines a function which maps from 3-space to 2-space. The first and second derivatives of an ExpressionFunction are available.

The evaluate for the Expression Function uses the coordinates of the point in the domain to give values to identifiers in the expression, and then "executes" the expression.

In the constructor shown above, the first string is a list of identifiers, (enclosed in parentheses, and separated by commas), which associates an identifier to each coordinate of the point in the domain. The domain is always (for this constructor) a RealEuclideanNSpace , with a dimension which is the number of identifiers listed. There is no special meaning to the identifier names,

  f1=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");
  f2=new NAExpressionFunction("(r,theta,phi)","(sin(r)*sin(theta)*sin(phi),phi*theta)");
 and,

  f3=new NAExpressionFunction("(z,y,x)","(sin(z)*sin(y)*sin(x),x*y)");
all define functions which evalute to the same thing. However, the order is important,
  f1=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");

 and,

  f2=new NAExpressionFunction("(y,x,z)","(sin(x)*sin(y)*sin(z),z*y)");
do not define the same function.

The second string passed to this constructor is a list of expressions (enclosed in parentheses, and separated by commas). This string gives the formula for computing the coordinates of the result. The range (again, for this constructor), is always a RealEuclideanNSpace. The dimension of the range of the function is the number of expressions listed. The expressions may use any (or none) of the identifiers listed in the first argument. If other identifiers are used, a run time error will result when the function is evaluated.

The basic operators +,-,*,/ and ** (exponentiation) are allowed. The following ways of defining constants are allowed:


The current implementation does not allow full exponential notation (the developer got lazy). So, x+1.e-7 is not a legal expression, but x+1/1.e7 is legal.

The values of the identifiers

are automatically set to (what else?) 3.14159... and 2.7182818... .

There are quite a few functions available for use in the expressions. They all take a single argument. The "basic" functions are from the "C" math library:


The derivatives of functions involving these basic functions are available, second derivatives are not. The table of second derivatives has not yet been added.

If the SpecialFunctions library (specfun), from netlib, is installed (see the installation instructions), then the following special functions are available:


Derivatives of functions involving these special functions are not available. The table of derivatives has not yet been added.


User's Guide


To use this class, you must include the header file
NAO/ExprFn.h
and link against library
libNAOBase.a
The following constructors are provided:

The following member functions are available in addition to those provided by the abstract interface NAFunction:


Programmer's Guide


The NAExpressionFunction is an NAFunction, implemented using the Expression Compiler subroutine library, written by one of the authors of NAO. This library compiles a single expression into a pseudo-object code (which contains a symbol table). Identifiers in the symbol table code can be set to particular values, and the object code can then be "executed" to obtain a single floating point result.

The NAExpressionFunction uses the strings input by the user, breaks them up into individual expressions, "compiles" them using the ExpressionCompiler, and stores pointers to the list of object codes. When the function is called to be evaluated, the NAExpressionFunction class uses the stored list of identifiers to set the identifiers in the symbol table of the object code to the corresponding coordinate of the point at which the function is being evaluated.

Derivatives are performed by "differentiating" the object code. This is done by the ExpressionCompiler library, and uses standard techniques for differentiation of subroutines. Essentially, all operations in the object code are duplicated, as are the registers they operate on. The second operation is then modified to perform the derivative of the operation. ( Ri+Rj becomes dRi+dRj, Ri*Rj becomes dRi*Rj+Ri*dRj, etc.). The result is an object code which evaluates the function and its derivative. A symbolic representation of the derivative is never constructed.

The constructor creates object code, and two differentiations of the object code. In the differentiation, identifiers which are function calls (eg sin(x)) generate new identifiers for the derivatives, simple by prepending a "D" (sin(x) -> Dsin(x) and DDsin(x)). The derivatives of the ExpressionFunction therefore depend on the symbols for special functions and their derivatives. The current implementation of the NAExpressionFunction sets many of the basic functions (see the overview above), and their derivatives. Second derivatives are not set at this time, nor are first derivatives of the special functions.


Example


To use the Expression function, we might create a function that returns points on a circle:
#include <NAO/ExprFn.h>

NAFunction *f=new NAExpressionFunction("(theta)",
                   "(4*cos(2*\%pi*theta),4*sin(2*\%pi*theta))");

NAPointOnManifold *x=new NADoublePointOnManifold(1);
NAPointOnManifold *y=new NADoublePointOnManifold(2);

cout << "Points around a circle of radius 4" << endl;
for(i=0;i<10;i++)
 {
  x->setCoordinate(0,.1*i);
  f->evaluate(x,y);
  cout << i << " (" << y->getCoordinate(0).Double() << "," << 
                       y->getCoordinate(1).Double() << ")" << endl;
 }
Getting constants into a string is not as easy as it could be. Here's an example where the constants are written into a string:
#include <NAO/ExprFn.h>

char list[256];
char expression[80];

strcpy(list,"(");
sprintf(expression,"sin(2*\%pi*theta)*(%f+%f*cos(2*\%pi*phi))",R1,R0);
strcat(list,expression);
strcat(list,",");
sprintf(expression,"cos(2*\%pi*theta)*(%f+%f*cos(2*\%pi*phi))",R1,R0);
strcat(list,expression);
strcat(list,",");
sprintf(expression,"%f*sin(2*\%pi*theta)",R0);
strcat(list,expression);
strcat(list,",");

NAFunction *f=new NAExpressionFunction("(theta,phi)",expression);

NAPointOnManifold *x=new NADoublePointOnManifold(2);
NAPointOnManifold *y=new NADoublePointOnManifold(2);

cout << "Points around a torus with small radius of " << R0 
                          << " and large radius << R1 << endl;

for(i=0;i<10;i++)
 {
  theta=i*.1;
  x->setCoordinate(0,theta);
  for(j=0;j<10;i++)
   {
    phi=j*.1;
    x->setCoordinate(1,phi);
    f->evaluate(x,y);
    cout << "(" << i << "," << j << ") -> (" << y->getCoordinate(0).Double() << "," << 
                         y->getCoordinate(1).Double() << ")" << endl;
  }
 }

Related Classes and Subroutines


The parent of this class:

Siblings of this class:

ExpressionFunctions are used in one of the constructors for the NATableFunction which uses an ExpressionFunction (built and destroyed in the constructor) to give values to the vertices of a grid. The Expression Compiler is used in the routines:

which replace identifiers with Operators, Functions or scalars.


Created: Fri Oct 9 09:46:11 EDT 1998

[Comments | NAO home page ]

[Research home page]

[ IBM home page | Order | Privacy | ContactIBM | Legal ]