User's Guide
for
RBFpack

 

Software for Modeling
Multi-dimensional Surfaces
from Numerical Scattered Data

By:

Windward Technologies, Inc.

 

 

Contents

 

Introduction

Overview for C Interface

C Examples

Example 1: rbf_fit

Example 2: rbf_fit Continued

Example 3: rbf_lsq_fit

Example 4: Interpolation

Example 5: Constrained Surface Fit

 

The RBFpack Interface

User First Level

lsd_initialize

rbf_fit

rbf_interpolate

rbf_error

rbf_value

 

User Second Level

rbf_lsq_fit

rbf_initialize

rbf_set_values

 

Built-in Radial functions

gaussian

radial_poly

hardy_multiquadric

inverse_hardy_multiquadric

 

RBF_FIT options

rbf_fit_opt_int

rbf_fit_opt_radfcn

 

Input-Output

set_io_file

rbf_view

rbf_error_stat

lsd_read

lsd_view

 

Optimization and Support

rbf_optimize

step_up_optimize

step_up

rbf_to_x

x_to_rbf

lsq_error

 

Support functions

test_data

rbf_compare

rbf_copy

copy_rbf

rbf_fd_der

free_LSD

free_RBF

get_box

 

RBF and LSD data structure declarations

struct RBF

struct LSD

 

Overview for MATLAB Interface

Matlab Examples

Example 1: rbf_fit

Example 2: rbf_lsq

Example 3: rbf_interpolate

Example 4: Noisy Data

Example 5: Parametric Fits

 

Matlab Functions

rbf_fit

rbf_lsq_fit

rbf_interpolate

rbf_value

rbf_error

lsd_struct

rbf_struct

rbf_fit_opt_radfcn

rbf_graph_m

 

References

 

 


Introduction

 

This document describes functions that compute and manipulate Radial Basis Functions (RBFs). For our purposes a RBF is a function f mapping Rn to Rm. It takes the form:

f (x) = a0 + å {i=1...k} ai j(pi ,||S (x - ci)||)

where ai Î Rm, x, ci Î Rn, S is a diagonal matrix, and the double bars denote the Euclidean norm. Several support functions are available including those which read least squares data and those which print information concerning the radial basis functions as well as relevant information on least squares fits.

The functions in RBFpack are designed to solve the least squares approximation problem:

min å {j=1... nobs} wj ||{yj - [a0 + å {i=1...k} ai j (pi ,||S (x - ci)||)]}||2

where yj Î Rm and wj Î R+ and the double bars denote the Euclidean norm. The upper limit on the first sum is nobs which stands for number of observations. We use the CLAPACK function dgelsx to solve the least squares problems. When m = 1 this has the form

min å {j=1... nobs} wj {yj - [a0 + å {i=1... k} ai j(pi ,||S (x - ci)||)] }2

If the minimization takes place only with respect to the linear parameters ai Î Rm, then this is a standard linear least squares problem and it can be solved very efficiently. 

Standard choices for the radial function j(p, r) are:

exp(-{pr}2), sqrt(p2 + r2), 1/sqrt(p2 + r2), {(1 - pr)+}4 (1 + 4 pr)

These radial functions are referred to as the Gaussian, Hardy multiquadric, the inverse Hardy multiquadric, and the radial polynomial (of degree 5). For convenience, we store the information for a given RBF in one structure. The user can add a favorite radial function by following the directions in the section Built-in Radial Functions.

The Matlab user should go directly to the Matlab section.

 

Overview for C Interface

 Using RBFpack is easy provided the user understands the Surface Fitting Paradigm. This paradigm is:

 

Data (LSD *) ®

Surface (RBF *) ®

Evaluate / Operate

lsd_initialize
lsd_read
lsd_view

rbf_fit
rbf_interpolate
rbf_lsq_fit

rbf_value
rbf_error
rbf_error_stat
rbf_view

 

Data

The easiest way to envision an appropriate data set for RBFpack is to think of a table or spreadsheet of data arranged in a rectangle. The first M columns represent independent values, while the last N columns contain the dependent values. We illustrate this with surface values drawn from the function

(w, x, y, z) ® (w + x + y + z, 2w + x + y + z)

which has a 4 dimensional domain and a 2 dimensional range. Some data from this surface can be found in the table below:

 

Observation #

Ind Var 1

Ind Var 2

Ind Var 3

Ind Var 4

Dep Var 1

Dep Var 2

1

.3

.2

.4

.5

1.4

1.7

2

.5

.5

.4

.1

1.5

2.0

3

.1

.1

.2

.4

.7

0.8

 

Since C does not naturally support two-dimensional arrays, RBFpack has a data structure (LSD) to easily store and retrieve these values. Thus, the user must first initialize an LSD data structure of the correct size with lsd_initialize and then stuff the problem data into the structure, or the user can use lsd_read to read this data from a file. After the data is in the LSD data structure, the user can view this data by calling lsd_view.

Surface Fit

Once having stored the data in an LSD data structure, the next operation is to produce an RBF approximation to this data. There are three main methods for doing this. The function, rbf_fit, is recommended if a least squares fit is desired. This function attempts to find a global, nonlinear least-squares fit to the data by varying the centers and the center parameters. A sophisticated local minimizer (LSGRG2) is used to complement the global techniques. It is possible that rbf_fit could take too much time to arrive at an answer. In this case, we recommend rbf_lsq_fit. This will produce a least squares fit using linear techniques. It requires the user to supply all of the parameters for the RBF except the coefficients (rbf->rad_coef). The last option is to use the interpolation routine rbf_interpolate. This function produces an interpolating RBF to the data.

Operate

At this point, it is assumed that an RBF has been computed and stored in an RBF data structure. Having a mathematical representation of the surface is nice, but it is not very helpful if there are no evaluation or differentiation routines. Thus, one uses rbf_value to get function values and derivatives. Other functions are available to compute the least squares error (rbf_error), to view the RBF parameters (rbf_view), or to compute statistical information on the fit (rbf_error_stat).

C Examples

RBFpack is designed to produce a surface from discrete data. Once produced, we can evaluate, differentiate, or view the error between the surface and data. The general methodology is to minimize the least squares error between the data and a candidate surface (using the RBF representations mentioned above). Thus the general sequence of events is:

 

Data (LSD *) ®

Surface (RBF *) ®

Evaluate / Operate

 

Data (LSD *)

Consider the problem of approximating the surface (x, y, sin(x+y^2)) from the data

 

X values

Y values

Sin(x+y^2)

0

0

0

0.5

0

0.479426

1

0

0.841471

0

0.5

0.247404

0.5

0.5

0.681639

1

0.5

0.948985

0

1

0.841471

0.5

1

0.997495

1

1

0.909297

 

This data has nine observations. The domain dimension is two and the range dimension is one. We present this data to the RBFpack functions through a Least Squares Data structure called LSD. It is a C data structure and it stores all the relevant data for the general surface-fitting problem as follows:

struct LSD *lsd;
int error_flag; 
/* Allocate space for the LSD data structure for 9 observations, 
   domain dimension = 2 and range dimension = 1  */

lsd = lsd_initialize(9 /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &error_flag);
	
lsd->xdata[0][0] = 0., lsd->xdata[0][1] = 0., lsd->ydata[0][0] = 0.;
lsd->xdata[1][0] = .5, lsd->xdata[1][1] = 0., lsd->ydata[1][0] = .479426;
lsd->xdata[2][0] = 1., lsd->xdata[2][1] = 0., lsd->ydata[2][0] = .841471;
lsd->xdata[3][0] = 0., lsd->xdata[3][1] = .5, lsd->ydata[3][0] = .247404;
lsd->xdata[4][0] = .5, lsd->xdata[4][1] = .5, lsd->ydata[4][0] = .681639;
lsd->xdata[5][0] = 1., lsd->xdata[5][1] = .5, lsd->ydata[5][0] = .948985;
lsd->xdata[6][0] = 0., lsd->xdata[6][1] = 1., lsd->ydata[6][0] = .841471;
lsd->xdata[7][0] = .5, lsd->xdata[7][1] = 1., lsd->ydata[7][0] = .997495;
lsd->xdata[8][0] = 1., lsd->xdata[8][1] = 1., lsd->ydata[8][0] = .909297;

The function lsd_initialize defaults the weights (in the least squares problem) to one. A more compact representation for the last 9 lines is:

for(j=0; j<3; j++)
     for(k=0; k<3; k++)
	lsd->xdata[k+3*j][0] = k/2. , lsd->xdata[k+3*j][1] = j/2., 
        lsd->ydata[k+3*j][0] = sin( k/2. + (j/2.)*(j/2.) );     
    

 

 Surface (RBF *)

The data has been moved into the LSD data structure. Now we compute the approximating surface (whose parameters are stored in the RBF data structure). There are several functions which return RBF surface fits. We will discuss two functions in the overview. The first function is rbf_fit. This function uses a rather complex nonlinear algorithm to find a good fit to the data with as few parameters as possible. The function rbf_fit has three arguments. The first argument is the pointer to the LSD data structure, the second argument is the maximum number of centers that will be used in the fit, and the third argument is an error flag. Below is a code fragment which returns the surface fit in the RBF data structure rbf.

struct RBF * rbf;
rbf = rbf_fit(lsd, 3, &error_flag);

 A second function, rbf_interpolate, produces an interpolating surface to the given data. One generally uses the interpolation function when there is no noise in the data as in this simple example. The four arguments are the data (in an LSD data structure), a parameter to control the linear algebra solution, a pointer to an integer which returns the numerical rank, and an error flag.

struct RBF * rbf;
int rank;
rbf = rbf_interpolate(lsd, 1.e-6, &rank, &error_flag);

Evaluate/Operate

From the previous discussion, we assume that a surface has been computed and its parameters are stored in the RBF data structure. We now want to evaluate or operate on the computed surface (perhaps for the purpose of obtaining a graph). The following functions are useful in this regard:

 

Function name

Function result

rbf_value

Returns zero, first, or second derivatives

rbf_error

Returns least squares error

rbf_view

Prints information on the RBF parameters

rbf_error_stat

Computes and/or prints error statistics

 

For example, if one wants the values of the surface on a 10 by 10 grid the following code could be used.

double x[2], Value[10][10];
for(j=0; j<10; j++)
    for(k=0; k<10; k++)
        x[0] = j/10. , x[1] = k/10., 
        rbf_value(rbf, x, 0, 0, &Value[j][k]);

 

Example 1: rbf_fit

From a user perspective there are only a few functions that one needs to understand. The program listed below demonstrates an elementary use of RBFpack based on the discussion above. The fit is stored in the Radial Basis Function labeled rbf. The call to rbf_fit produces the least squares fit. The user should study this code to understand the flow of data from one call to the next, since this is a standard method of producing a least squares fit.

 

#include "rbf.h"

void main()
{   /*  Example 1  */
    struct LSD *lsd;
    struct RBF *rbf;
    int inform, j, k, nout=9, npts = 5;
    double error, Value[10][10], x[2];

    lsd = lsd_initialize(npts*npts /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &inform);

    for(j=0; j<npts; j++)
       for(k=0; k<npts; k++)
         lsd->xdata[k+npts*j][0] = k/(npts-1.), lsd->xdata[k+npts*j][1] = j/(npts -1.),  
	     lsd->ydata[k+npts*j][0] = sin( k/(npts -1.) + (j/(npts -1.))*(j/(npts -1.)) );     

    rbf = rbf_fit(lsd, 3, &inform);       /* fit data */
    error = rbf_error(rbf, lsd, &inform); /* compute error */
    printf("The error is  %5.6f \n", error);
    for(j=0; j<nout; j++){ /* Print surface values */
        printf(" \n");
      for(k=0; k<nout; k++){
        x[0] = j/(nout -1.) , x[1] = k/(nout-1.), 
        rbf_value(rbf, x, 0, 0, &Value[j][k]);
        printf(" %4.2f ", Value[j][k] );}
   }
}

 

The output on the screen should be "The error is .000794" followed by a 10 by 10 matrix of surface values.

 

Example 2:rbf_fit Continued

We continue the discussion of Example 1. In this example, the same computation is made, but we use the functions lsd_view, rbf_view, and rbf_error_stat to view the data, the RBF fit, and the error characteristics. The function set_io_file opens the output file whose name is "example2.txt".

 

#include "rbf.h"

void main()
{   /*  Example 2  */
    struct LSD *lsd;
    struct RBF *rbf;
    int inform, j, k, nout=9, npts = 5;
    double error, stat_out[5];

    lsd = lsd_initialize(npts*npts /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &inform);
/* get data */
    for(j=0; j<npts; j++)
       for(k=0; k<npts; k++)
         lsd->xdata[k+npts*j][0] = k/(npts-1.), lsd->xdata[k+npts*j][1] = j/(npts -1.),  
	     lsd->ydata[k+npts*j][0] = sin( k/(npts -1.) + (j/(npts -1.))*(j/(npts -1.)) );     

    set_io_file("example2.txt", "open output file", &inform);
    
    
    lsd_view(lsd, 10, &inform);           /* view first 10 data points */  
    rbf = rbf_fit(lsd, 3, &inform);       /* fit data */
    rbf_view(rbf, 2, &inform);            /* view RBF coefs and centers */  
    error = rbf_error(rbf, lsd, &inform); /* compute error */
    printf("The error is  %5.3f \n", error);
    rbf_error_stat(rbf, lsd, 0, stat_out, &inform); /* view error stats */

    set_io_file("example2.txt", "close output file", &inform);
}

The data written into example2.txt follows:

 

The following is the output from lsd_view at level    10 

 
The number of observations is     25 
The domain dimension  is           2 
The range  dimension  is           1 

 
 
      0 xdata  0.000000  0.000000  
      0 ydata  0.000000  
      0 weight 1.000000
 
      1 xdata  0.250000  0.000000  
      1 ydata  0.247404  
      1 weight 1.000000
 
      2 xdata  0.500000  0.000000  
      2 ydata  0.479426  
      2 weight 1.000000
 
      3 xdata  0.750000  0.000000  
      3 ydata  0.681639  
      3 weight 1.000000
 
      4 xdata  1.000000  0.000000  
      4 ydata  0.841471  
      4 weight 1.000000
 
      5 xdata  0.000000  0.250000  
      5 ydata  0.062459  
      5 weight 1.000000
 
      6 xdata  0.250000  0.250000  
      6 ydata  0.307439  
      6 weight 1.000000
 
      7 xdata  0.500000  0.250000  
      7 ydata  0.533303  
      7 weight 1.000000
 
      8 xdata  0.750000  0.250000  
      8 ydata  0.726009  
      8 weight 1.000000
 
      9 xdata  1.000000  0.250000  
      9 ydata  0.873575  
      9 weight 1.000000
 

 
The following is the output from rbf_view at level     2 
 
The number of centers is      3 
The domain dimension  is      2 
The range  dimension  is      1 
The function switch   is  gaussian. 


  
coefficients for center  0 
   -41.360094  
coefficients for center  1 
   40.127099  
coefficients for center  2 
   0.098018  

coefficients for constant  
   0.926057  

 
 
Center  0 
   -0.098248     -0.101000  
Center  1 
   -0.089618     -0.097606  
Center  2 
   0.346511     0.807048  

 
This is output from rbf_error_stat at level 0

The number of observations is 25 
The R-square value is         0.991015 
The SSE value is              0.000794 
The SST value is              0.088401 
The Max absolute error is     0.072847 
The Ave absolute error is     0.020636 


 

Example 3: rbf_lsq_fit

This example features the function rbf_lsq_fit. This function solves a linear least squares problem. The RBF data structure must be initialized. Then rbf_lsq_fit computes the RBF coefficients stored in rbf->rad_coef and rbf->const_coef.

 

#include "rbf.h"

void main()
{   /*  Example 3  */
    struct LSD *lsd;
    struct RBF *rbf;
    int inform, j, k, rank, npts = 5;
    double error, stat_out[5], rcond = 1.e-6;

    lsd = lsd_initialize(npts*npts /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &inform);
/* get data */
    for(j=0; j<npts; j++)
       for(k=0; k<npts; k++)
         lsd->xdata[k+npts*j][0] = k/(npts-1.), lsd->xdata[k+npts*j][1] = j/(npts -1.),  
	     lsd->ydata[k+npts*j][0] = sin( k/(npts -1.) + (j/(npts -1.))*(j/(npts -1.)) );     
    set_io_file("example3.txt", "open output file", &inform);
    
    rbf = rbf_initialize(9, lsd->domain_dim, lsd->range_dim, 
        gaussian, 1, .77, &inform);          /* initialize rbf */
    rbf_set_values(rbf, lsd, .777, &inform); /* use lsd to set rbf parameters */
    rbf_lsq_fit(rbf, lsd, rcond, &rank, &inform);       /* fit data */
    rbf_view(rbf, 2, &inform);            /* view RBF coefs and centers */  
    error = rbf_error(rbf, lsd, &inform); /* compute error */
    printf("The error is  %5.3f \n", error);
    rbf_error_stat(rbf, lsd, 0, stat_out, &inform); /* view error stats */

    set_io_file("example3.txt", "close output file", &inform);
}

 

The output follows: Notice that although the RBF computed in this example has nine centers while Examples 1 and 2 have three centers. The centers have not been optimized and consequently the least squares error is much larger than in the earlier examples (4.156e-3 versus 7.94e-4). Of course, the computational time for Example 3 is somewhat less.

 
The following is the output from rbf_view at level     2 
 
The number of centers is      9 
The domain dimension  is      2 
The range  dimension  is      1 
The function switch   is  gaussian. 

 
 
coefficients for center  0 
   0.089003  
coefficients for center  1 
   0.481678  
coefficients for center  2 
   1.377656  
coefficients for center  3 
   0.127444  
coefficients for center  4 
   6.003829  
coefficients for center  5 
   -6.559107  
coefficients for center  6 
   0.191392  
coefficients for center  7 
   -1.891668  
coefficients for center  8 
   -0.055148  

coefficients for constant  
   0.754600  

 
 
Center  0 
   0.102205     0.757105  
Center  1 
   0.669371     0.121016  
Center  2 
   0.918494     0.125301  
Center  3 
   0.942194     0.459643  
Center  4 
   0.223915     0.332254  
Center  5 
   0.194164     0.318733  
Center  6 
   0.953705     0.917702  
Center  7 
   0.817704     0.151333  
Center  8 
   0.457494     0.098142  

 
This is output from rbf_error_stat at level 0 

The number of observations is 25 
The R-square value is         0.952989 
The SSE value is              0.004156 
The SST value is              0.088401 
The Max absolute error is     0.163329 
The Ave absolute error is     0.046738

 

Example 4 Interpolation

The next example produces an interpolant to the data. The interpolant uses the radial_poly radial basis function.

 

#include "rbf.h"

void main()
{   /*  Example 4  */
    struct LSD *lsd;
    struct RBF *rbf;
    int inform, j, k, rank, npts = 5;
    double error, stat_out[5], rcond = 1.e-6;

    lsd = lsd_initialize(npts*npts /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &inform);
/* get data */
    for(j=0; j<npts; j++)
       for(k=0; k<npts; k++)
         lsd->xdata[k+npts*j][0] = k/(npts-1.), lsd->xdata[k+npts*j][1] = j/(npts -1.),  
	     lsd->ydata[k+npts*j][0] = sin( k/(npts -1.) + (j/(npts -1.))*(j/(npts -1.)) );     

    set_io_file("example4.txt", "open output file", &inform);
   
    rbf_fit_opt_radfcn(radial_poly); /* change default radial function */
    
    rbf = rbf_interpolate(lsd, rcond, &rank, &inform); /* interpolate data */
    rbf_view(rbf, 0, &inform);               /* view RBF coefs and centers */  
    error = rbf_error(rbf, lsd, &inform);    /* compute error */
    printf("The error is  %5.3f \n", error);
    rbf_error_stat(rbf, lsd, 0, stat_out, &inform); /* view error stats */

    set_io_file("example4.txt", "close output file", &inform);
}

 

The output from this example is listed below. Note that the R-square is one and the error is zero to six places. This is to be expected for interpolation. Notice that the max error is not zero since we are allowing the possibility of errors in the third decimal to creep into the calculation. This is a matter of conditioning of the linear interpolation problem. If this is not acceptable then one can adjust the rcond parameter.

 

The following is the output from rbf_view at level     0 
 
The number of centers is     25 
The domain dimension  is      2 
The range  dimension  is      1 
The function switch   is  radial_poly. 

 
This is output from rbf_error_stat at level 0 

The number of observations is 25 
The R-square value is         1.000000 
The SSE value is              0.000000 
The SST value is              0.088401 
The Max absolute error is     0.000474 
The Ave absolute error is     0.000075 

 

Example 5: Constrained Fit

This last example is the most realistic use of RBFpack. It is also the most complicated. The problem is to find an approximating surface to two-dimensional histogram data. This problem is prototypical of many problems which arise in engineering and finance. That is, a surface is to be erected over a domain, but in addition to the raw data used to determine the fit there are certain qualitative features which must be reflected by the surface. For the example below where we are trying to produce a smooth surface from histogram data these qualitative features are A) the integral of the surface should be 1 and B) the surface should be nonnegative. We use lsgrg2 to produce an approximating surface satisfying these "qualitative" constraints. Lsgrg2 is an optimizer which allows equality and inequality constraints to be applied while optimizing some quantity. Please consult our web pages at web.wt.net/~wti for more information on lsgrg2.

The data is generated in the function get_density_data. Now a histogram surface should have several characteristics. It should be non-negative and the integral of the surface over its domain should be one. These characteristics are (partially) enforced by the constraints generated in the functions rbf_optimize_const (where the upper and lower bounds are set for these constraints) and in lsq_error_const where the corresponding surface values are computed. We would like to enforce non-negativity everywhere, however since that is not possible we require that the function be non-negative on the 7 by 7 grid where the histogram data is taken. This is just a convenience and a larger grid could be used for this purpose if necessary.

RBFpack Histogram

The constrained fit looks like the surface below, except we have graphed the max(0, s(x,y)) where s is the surface computed. You might wonder why the surface is not nonnegative already since we are enforcing s >= 0 on a 7 by 7 grid. The problem is that we are using a finer grid to obtain more detail and on this finer grid a few of the values are negative. We could have enforced nonnegativity on this finer grid but that would have increased the computing time:

RBFpack Surface Plot

The code for this example follows: Note that global variables centers_1, …, const_coef_1 are used to specify which of the RBF parameters are to be used in the optimization. For this example, we allow only the radial coefficient parameters to vary (ie rad_coef_1 =1). This example requires 3 minutes to run on a 166 MH pentium. This is a rather complicated example and it is suggested that the user spend some time studying it if a similar problem is to be attempted.

 

#include "rbf.h"

struct RBF * glob_rbf_1;
struct LSD * glob_lsd_1;

int NPTS = 7;
int NUM_SIMS = 10000;
int FIRST = 1;
int NVARS, NFUNS;

double x[10000][2], y[20][20];


/*	These are the switches to determine which 
	variables are in play when the optimizer is used  */
 int centers_1				= 0; /* InActive */
 int rad_coef_1				= 1; /* Active   */
 int center_parameter_1		        = 0; /* InActive */
 int domain_scale_1			= 0; /* InActive */
 int const_coef_1			= 0; /* InActive */ 


TYPE_export(struct RBF *) rbf_optimize_const(struct RBF * rbf_in, struct LSD * lsd,
                  int itmax, int * inform);

TYPE_export(void) lsq_error_const(double   g[], double x[]);

TYPE_export(struct LSD *) get_density_data();

void print_graph_data(struct RBF * rbf );

double lsq_nlin(double *x);

TYPE_export(void) const_P (double x[], double g[],
                   long int igrad[], long int jgrad[],
                   double grad[], long int nzg);

TYPE_export(void) get_mat (int nfuns, int nvars, double x[], double g[],
                   long int igrad[], long int jgrad[],
                   double grad[]) ;



double f(double x,double y);
double g(double x, double y);
double drand(double); 



void main()
{/*  Example 5  */
    struct LSD *lsd;
    struct RBF *rbf, *rbf1;
    int inform, k, count, npts1, i, j;
    double  sum=0., xmin, xmax, ymin, ymax, x[2];

    lsd = get_density_data(); 
    for(k=0; k<lsd->nobs; k++)
        sum += (lsd->ydata[k][0]);
    sum = sum/lsd->nobs;
    printf("sum =  %f \n", sum);
    set_io_file("example5.txt", "open output file", &inform);
    
    rbf = rbf_initialize(16+36, lsd->domain_dim, lsd->range_dim, 
      radial_poly, 1, .677, &inform);          /* initialize rbf */
    rbf_set_values(rbf, lsd, .5, &inform); 
  
    rbf->domain_scale[0]=1. , rbf->domain_scale[1]=1.;
    rbf->const_coef[0] = .0;

    count = 0;

    npts1 = 4;
    xmin = .35 , xmax = .65;
    ymin=.35 , ymax = .65;

    for(i=0; i<npts1; i++){
     
     for(j=0; j<npts1; j++){
        x[0] = xmin+i*(xmax-xmin)/(npts1-1.);
		x[1] = ymin+j*(ymax-ymin)/(npts1-1.);
	 
		rbf->center_parameter[count] = 1.;
		rbf->centers[count][0] = x[0];
		rbf->centers[count++][1] = x[1];
	 }
	}
    npts1 = 6;
    xmin = .3 , xmax = .7;
    ymin=.3 , ymax = .7;
    for(i=0; i<npts1; i++){
     
     for(j=0; j<npts1; j++){
        x[0] = xmin+i*(xmax-xmin)/(npts1-1.);
		x[1] = ymin+j*(ymax-ymin)/(npts1-1.);
	 
		rbf->center_parameter[count] = 5.;
		rbf->centers[count][0] = x[0];
		rbf->centers[count++][1] = x[1];
	 }
	}

    rbf->num_centers = 16+36;
	for(i=0; i<rbf->num_centers; i++)
		rbf->rad_coef[i][0] = .17;
    rbf_view(rbf, 5, &inform);
   
    rbf1 = rbf_optimize_const(rbf, lsd, 500, &inform);
    printf("the error is  %f\n", sqrt(rbf_error(rbf1, lsd, &inform)));

    rbf1->const_coef[0] = .001;
	print_graph_data(rbf1);
    rbf_view(rbf1, 5, &inform);
    lsd_view(lsd, 225, &inform);
    set_io_file("example5.txt", "close output file", &inform);

}



TYPE_export(struct RBF *) rbf_optimize_const(struct RBF * rbf_in, struct LSD * lsd,
                  int itmax, int * inform)
{
/*  Purpose:    This function returns the result
                of applying optimization to the standard regression
                problem.  The starting point for the nonlinear
                regression is contained in rbf_in and the data for
                the regression is in lsd.

    Return Value:  A pointer to the solution of the NL regression 
                   problem.


    Arguments:

        rbf_in          The initial guess for the Nonlinear
                        regression proble.  (input)
        lsd             The regression data (input)
        itmax           An upperbound on the number of line searches (input)
                        in the optimization algorithm  (input)



        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          100           rbf_in has some int members <= 0


          200           rbf_copy failed

          300           allocation error

            J           return value from lsgrg2 whose value is J


*/

    struct RBF * rbf_out;
    int         i, j, info, count = 0;
    double      *max_box, *min_box, big = 1.e30, temp;
    int         nvars, nfuns, nobj;
    double      *xx, *xlb, *xub, *glb, *gub;
    char        *title, *report;
    double      *gg;

    /* Check initial input  */
    if(rbf_in->num_centers <= 0 || rbf_in->domain_dim <= 0 ||
       rbf_in->range_dim <= 0){
       *inform = 100;
       return NULL; /* Either rbf_in int members are mis-specified
                  or rbf_in and rbf_out have different int data */
       }





    /* Set pointers to global data structures
       and copy the input info from rbf_in into glob_rbf_1 */
    glob_rbf_1 = rbf_copy(rbf_in, &info);

    if(info != 0){
        *inform = 200;
        return NULL; /* Failure from rbf_copy */
    }

    glob_lsd_1 = lsd;

    /* Set optimization parameters */
    nfuns = 2+glob_lsd_1->nobs+1;
    nobj = -1;
    nvars = centers_1 *(rbf_in->num_centers * (rbf_in->domain_dim)) +
            rad_coef_1 *(rbf_in->num_centers * (rbf_in->range_dim)) +
            center_parameter_1 *(rbf_in->num_centers) +
            domain_scale_1 *(rbf_in->domain_dim) +
            const_coef_1 *(rbf_in->range_dim)+1;

   NVARS = nvars, NFUNS = nfuns;
    title = "Output from rbf_optimize";
    report = "rbopt.txt";


    /*  Allocate space for the extreme corners of the
     smallest box that contains the points in lsd->xdata
     and store these in min_box and max_box */

    max_box = (double *) CALLOC(rbf_in->domain_dim, sizeof(double));
    min_box = (double *) CALLOC(rbf_in->domain_dim, sizeof(double));
    xlb     = (double *) CALLOC(nvars+1, sizeof(double));
    xub     = (double *) CALLOC(nvars+1, sizeof(double));
    xx      = (double *) CALLOC(nvars+1, sizeof(double));
    glb     = (double *) CALLOC(nfuns+1, sizeof(double));
    gub     = (double *) CALLOC(nfuns+1, sizeof(double));
    gg      = (double *) CALLOC(nfuns+1, sizeof(double));
    /* Error checking for allocation failure */
    if((void *) max_box == NULL || (void *) min_box == NULL ||
       (void *) xlb     == NULL || (void *) xub     == NULL ||
       (void *) glb     == NULL || (void *) gub     == NULL ||
       (void *) gg     == NULL ) {
        *inform = 300;
        return NULL;
    }

    /* Set function constraints */
    glb[2] = 1.0, gub[2] = 1.0;
	glb[0] = -big, gub[0] = big;
    for(i=0; i<glob_lsd_1->nobs; i++)
        glb[3+i] = 0, gub[3+i] = big;

    get_box(lsd, min_box, max_box);

    /* Set the upper and lower bounds for the variables  */
    for(i=0; i<=nvars; i++)
        xlb[i] = -big, xub[i] = big;

    count = 0;
    if(centers_1 != 0)
        for(i=0; i<rbf_in->num_centers; i++)
            for(j=0; j< rbf_in->domain_dim; j++){
                temp = .1*(.01+ max_box[j] - min_box[j]);
                xlb[++count] = min_box[j] - temp;

                xub[  count] = max_box[j] + temp;
                }

    if(rad_coef_1 != 0) /* No upper bound, lower bound = 0 */
        for(i=0; i<rbf_in->num_centers; i++)
        for(j=0; j<rbf_in->range_dim; j++){
            xlb[++count] = -big;
            xub[  count] = big;
         }
        
        
    if(center_parameter_1 != 0)
        for(i=0; i<rbf_in->num_centers; i++){
            xlb[++count] = .3/sqrt((double) rbf_in->num_centers);
            xub[  count] = sqrt((double) rbf_in->num_centers);
        }

    if(domain_scale_1 != 0)
        for(i=0; i<rbf_in->domain_dim; i++){
            temp = 1.1*(.01+ max_box[j] - min_box[j]);
            xlb[++count] = .1/temp;
            xub[  count] = 10./temp;
        }

    if(const_coef_1 != 0) /* No upper bound, lower bound = 0 */
        for(i=0; i<rbf_in->range_dim; i++){
            xlb[++count] = -big;
            xub[  count] = big;
        }


    /* Set optimization parameters and call the optimization routine */
    rbf_to_x(glob_rbf_1,  xx, centers_1, rad_coef_1, center_parameter_1,
             domain_scale_1, const_coef_1);
    lgoptD( "limser", itmax );
    lgoptD("report", 1.); /* control printing */
    /* Must use "fullj" option if centers or center parmeters are
	   variables since the structure of the jacobion might change */
	if(centers_1 == 1 || center_parameter_1 == 1) lgoptD ("fullj", 1);
    lgoptG( lsq_error_const ) ;
	 /* if centers and center parameters are not used then we can
	    take advantage of the fact that all the functions are linear 
		with the exception of the objective */
	if(centers_1 ==0 && center_parameter_1 ==0) lgoptP(const_P);
    lsgrg2 ( nvars, xlb, xub, nfuns, nobj, glb, gub, title, report,
           xx, &info ) ;
    *inform = info;
	if(info <0)   return NULL; /* Failure from rbf_optimize */
   
        
    /* Put the final results into rbf_out */
    lsq_error_const(gg, xx);
    rbf_out = rbf_copy(glob_rbf_1, &info);
    free_RBF(glob_rbf_1), free(xx), free(xlb), free(xub);
    free(min_box), free(max_box), free(glb), free(gub), free(gg);
    return rbf_out;

}

TYPE_export(void) lsq_error_const(double   g[], double x[])
{
/*
Purpose:    This function computes the square root of the
            least squares errorgiven the values x and
            the global variables centers_1, rad_coef_1, center_parameter_1,
            domain_scale_1,   const_coef_1.  This version assumes that
            rad_coef_1 = 0 and it computes the linear variables by calling
            rbf_lsq_fit.  This routine is designed to be called
            by grg2.


    Return Value:  void


    Arguments:


        g       The objective value for the NL regression
                is stored in g[1] (output)

        x       The input independent variables for the
                grg2 function (input)


   Global Variables Used:

        glob_lsd_1          Pointer to global Least Squares Data set
        glob_rbf_1          Pointer to global rbf
        centers_1           = 0   centers_1 do not enter the optimizaton
        rad_coef_1          = 1   coeficients do explicitly enter
        center_parameter_1  = 0   center_parameter_1 do not enter the optimization
        domain_scale_1      = 0   domain_scale_1 is not optimized
        const_coef_1        = 0   const_coef_1 does not explicitly enter the
                                  optimization problem.
    */
    int i, j, count,info;
    double  v[1], sum;

    x_to_rbf(x, glob_rbf_1, centers_1, rad_coef_1,
        center_parameter_1, domain_scale_1, const_coef_1);


    g[1] = sqrt(rbf_error(glob_rbf_1, glob_lsd_1, &info));

    sum = 0.;
    for(i=0; i< glob_lsd_1->nobs; i++){
        rbf_value(glob_rbf_1, glob_lsd_1->xdata[i], 0, 0, v);
        sum = sum + v[0];
    }
    g[2] = sum/(glob_lsd_1->nobs);

   /* for(i=0; i< glob_lsd_1->nobs; i++)
        {rbf_value(glob_rbf_1, glob_lsd_1->xdata[i], 0, 0, v);
        g[3+i] = v[0];}
 */
	count = 0;
	for(i=0; i<NPTS; i++)
     for(j=0; j<NPTS; j++){
        rbf_value(glob_rbf_1, glob_lsd_1->xdata[j+NPTS*i], 0, 0, v);
        g[3+count++] = v[0];
	 }
     
	g[0] =0.; /* define g[0] so that the optimization can "start" at 0 */
    return;
}

double f(double x, double y)
{double temp;
        
        temp = .1+(2*x+y)/4.;
        return temp;
}    

double g(double x, double y)
{double temp;
        
        temp = .3+ y/2;
        return temp;
}    

TYPE_export(struct LSD *) get_density_data()
{struct LSD * lsd;
 int i , j, k, inform;
 double xsum, ysum;
/* fill simulation data */
     drand(.777);
     for(j=0; j<NUM_SIMS; j++){
         xsum = (drand(-1.)+drand(-1.)+drand(-1.))/3.;
		 ysum = (drand(-1.)+drand(-1.)+drand(-1.))/3.;
         x[j][0] = f(xsum, ysum);
         x[j][1] = g(xsum, ysum);
     }

    for(j = 0; j<NPTS; j++)
            for(k = 0; k<NPTS; k++)
                y[j][k] = 0.;

     /* first pass, find out how many points are in each bin */

     for(i=0; i < NUM_SIMS; i++)
         for(j = 0; j<NPTS; j++)
            for(k = 0; k<NPTS; k++)
                if(j/(NPTS-0.)    <= x[i][0] &&
                   k/(NPTS-0.)    <= x[i][1] &&
                   (j+1)/(NPTS-0.) > x[i][0] &&
                   (k+1)/(NPTS-0.) > x[i][1]) y[j][k] += 1.;

     for(j = 0; j<NPTS; j++)
            for(k = 0; k<NPTS; k++)
                y[j][k] = y[j][k]/NUM_SIMS;

     

     lsd = lsd_initialize((NPTS)*(NPTS) /* nobs */, 2 /* domain dimension */, 
               1 /* range dimension */, &inform);

    
     for(j = 0; j<NPTS; j++)
            for(k = 0; k<NPTS; k++)
                lsd->xdata[j + k*(NPTS)][0] = (j+.5)/(NPTS),
                lsd->xdata[j + k*(NPTS)][1] = (k+.5)/(NPTS),
                lsd->ydata[j + k*(NPTS)][0] = y[j][k]*(NPTS*NPTS);

     return lsd;
}

void print_graph_data(struct RBF * rbf )
{
int i, j, NUM_GRAPH = 15;
double v[1], x[2];
FILE *fp;

fp = fopen("rbf_graph_3.txt" , "w");
 for(i=0; i<NUM_GRAPH; i++){
     for(j=0; j<NUM_GRAPH; j++){
        x[0] = i/(NUM_GRAPH-1.), x[1] = j/(NUM_GRAPH-1.);
        rbf_value(rbf, x, 0, 0, v);
        fprintf(fp, " %f \t", v[0]);
     }
     fprintf(fp, "\n");
   }

   fprintf(fp, "\n");   
    for(i=0; i<NPTS; i++){
     for(j=0; j<NPTS; j++){
        rbf_value(rbf, glob_lsd_1->xdata[j+NPTS*i], 0, 0, v);
        fprintf(fp, " %f \t", v[0]);
     }
     fprintf(fp, "\n");
   }

   fprintf(fp, "\n");
   for(i=0; i<NPTS; i++){
     for(j=0; j<NPTS; j++){
        v[0] = glob_lsd_1->ydata[j+NPTS*i][0];
        fprintf(fp, " %f \t", v[0]);
     }
     fprintf(fp, "\n");
   }


fclose(fp);
}



TYPE_export(void) get_mat (int nfuns, int nvars, double x[], double g[],
                   long int igrad[], long int jgrad[],
                   double grad[]) 
{  int i, j, nnz;
   double h = 1.e-7, *gx, *gxph, *jacob_col;
   
   gx     = (double *) CALLOC(nfuns+1, sizeof(double));
   gxph   = (double *) CALLOC(nfuns+1, sizeof(double));
   jacob_col   = (double *) CALLOC(nfuns+1, sizeof(double));
   lsq_error_const(gx, x);
   
   nnz = 0;
   jgrad[0] = 0;
   for(i=0; i<nvars; i++){
	   x[i] = x[i] +h;
	   lsq_error_const(gxph, x);
	   for(j=0; j<nfuns; j++)
		   jacob_col[j] = (gxph[j] - gx[j])/h;

       for(j=0; j<nfuns; j++)
		   if(jacob_col[j] != 0.){
			   grad[nnz] = jacob_col[j];
			   igrad[nnz++] = j;}
        jgrad[i+1] = nnz;
		x[i] = x[i] -h;
   }
    free(gx), free(gxph), free(jacob_col);
}
			   
TYPE_export(void) const_P (double x[], double g[],
                   long int igrad[], long int jgrad[],
                   double grad[], long int nzg)
{	int i, nfuns = 124, nvars = 63;
	double h = 1.e-7, temp;

	nfuns = NFUNS, nvars = NVARS;
	if(nzg >0) get_mat(nfuns, nvars, x, g, igrad, jgrad, grad);
	else{
		for(i=1; i<nvars; i++){
			x[i] += h;
			temp = (lsq_nlin(x)-g[1])/h;
			x[i] -= h;
			grad[jgrad[i]] = temp;
		}
	}
}

double lsq_nlin(double *x)
{	/* code to compute the value of the objective function only.
	   This function is called by the Jacobian generating function
	   const_P */
	double temp;
	int info;
	x_to_rbf(x, glob_rbf_1, centers_1, rad_coef_1,
        center_parameter_1, domain_scale_1, const_coef_1);


    temp = sqrt(rbf_error(glob_rbf_1, glob_lsd_1, &info));
	return temp;
}

 


The RBFpack Interface

 

 


User First level:

The routines listed in this section are sufficient to allow the user to compute least squares fits to large and complicated data sets. At this level, we have attempted to hide all the distracting details of radial basis functions. We have identified the routines which will allow the user to compute sophisticated surface fits and interpolants without having to dive into the minutiae of radial basis functions. To this end we provide an initialization routine so that the user can initialize the area where he will store the data he is trying to fit. We also provide the all-purpose rbf_fit routine which will produce a least squares fit to the data from (a somewhat intelligent) choice of RBF parameters. Likewise, we provide the interpolation routine rbf_interpolate. Having computed a least-squares fit or an interpolant we must be able to evaluate the fit and asses the error. The routines rbf_error and rbf_value satisfy this need.

 

lsd_initialize


TYPE_export(struct LSD *) lsd_initialize(int nobs, int domain_dim,
                                         int range_dim, int *inform)

.......................................................................
    Purpose: This function allocates and initializes all the pointers
             in the LSD data structure.

    Return Value:  A pointer to the newly initialized LSD structure


    Arguments:

        nobs            Number of observations (input)
        domain_dim      Domain dimension (input)
        range_dim       Range dimension (input)

        inform          Error code (output)


    Fatal Errors (which return a NULL pointer):

        inform          Error Condition

          1             nobs        <= 0
          2             domain_dim  <= 0
          3             range_dim   <= 0
          4             allocation failure for some member of LSD
.......................................................................

 

rbf_fit


TYPE_export(struct RBF *)  rbf_fit(struct LSD * lsd, int max_centers,
                                   int * inform)

.......................................................................

    Purpose:    This function returns the result
                of applying local and global optimization
                techniques to the standard regression
                problem.  The data for the regression is in lsd.
                This function is a good starting point to explore
                the rbf fit properties.  The default parameters
                are chosen to balance the computational burden against
                the attempt to find a good fit.

                See rbf_fit_opt_int and rbf_fit_radfcn for functions
                which can change the defaults set up in this function.


    Return Value:  A pointer to the solution of the RBF regression
                   problem.  The default radial function is the gaussian.


    Arguments:


        lsd             The regression data (input)
        max_centers     An upperbound on the number of centers
                        to be used in the search for a good RBF fit (input)

        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             problem is mis-specified (ie integer
                        data in lsd is less than or equal 0.

          2             max_centers = 0.

          3             allocation error

          4             allocation error from rbf_initialize

          5             allocation error from rbf_set_values

.......................................................................

 

rbf_interpolate


TYPE_export(struct RBF *) rbf_interpolate(struct LSD * lsd_in,
                                          double rcond, int *rank, int *inform)

.......................................................................

    Purpose:    This function computes an interpolant
                to the data in lsd_in. The user can set the radial
                function by invoking rbf_fit_radfcn.


    Return Value:  The rbf interpolant.


    Arguments:

        lsd_in          Pointer to LSD structure (input)

        rcond           This parameter is used to determine
                        the effective rank of the
                        (nobs x 1+nobs) matrix for
                        the interpolation problem.
                        Suggested value for rcond is 1.e-6;
                        This variable must be positive. (input)

        rank            The numerical effective rank of the
                        interpolation problem which depends
                        on rcond (output)


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition


           1            rcond is not > 0
           2            Error from linear lsq solver dgelsx
                        (check integer members of the
                         structures)
           3            Allocation failure (check integer
                        members of the structures)

.......................................................................

 

rbf_error


TYPE_export(double) rbf_error(struct RBF * rbf_in, struct LSD * lsd_in,
                              int *inform)

.......................................................................

    Purpose:    This function computes the average weighted
                squared error

                (sum_{i=1}^nobs w_i ||F(x_i) - y_i||^2)/(nobs*range_dim)

                between the values in the rbf F specified in rbf_in
                and the Least Squares Data set specified in lsd_in


        Return Value:   Weighted average squared error

    Arguments:

        rbf_in          Pointer to RBF structure (input)
        lsd_in          Pointer to LSD structure (input)


        inform          Error code (output)


    Fatal Errors:

        inform          Error Condition

          1             The two structures are incompatible
                        due to different specification of

                            domain_dim
                            range_dim

                        members

           2            Allocation error

.......................................................................

 

rbf_value


TYPE_export(void) rbf_value(struct RBF * rbf_in, double *x, 
                            int ider1, int ider2, double *value)

.......................................................................

    Purpose:    This function computes the value

                    D_{(ider1, ider2)}F(x)

                  (of the function specified in rbf_in)
                  and returns it in the vector value.


        Return Value:   void

    Arguments:

        rbf_in          Pointer to RBF structure (input)
        x               Vector of length rbf_in->domain_dim (input)
        ider1           Partial derivative specification (input)
        ider2           Partial derivative specification (input)
        value           Value of D_{(ider1, ider2)}F(x) (output)


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

.......................................................................

 


User Second level:

The second level of RBFpack requires the user to become more involved with the RBF parameters. In particular to user rbf_lsq_fit (which computes a least-squares fit given the nonlinear RBF parameters) requires the user to specify some of the RBF parameters (such as the center parameters, the scale parameters, the centers, and of course the number of the centers). The user is assisted in this effort by rbf_initialize (which sets up the pointers for the RBF) and rbf_set_values which generates trial values for the RBF parameters.

 

rbf_lsq_fit


TYPE_export(void) rbf_lsq_fit(struct RBF * rbf_in, struct LSD * lsd_in,
                              double rcond, int *rank, int *inform)

.......................................................................

    Purpose:    This function computes a least squares fit
                to the data in lsd_in.  It assumes that all
                the values in rbf_in have been determined with
                the exception of the members {rad_coef const_coef}.
                This function then computes the appropriate coefficient
                vaues and places them in rbf_in.

    Return Value:  void


    Arguments:

        rbf_in          Pointer to RBF structure (input/output)
        lsd_in          Pointer to LSD structure (input)

        rcond           This parameter is used to determine
                        the effective rank of the
                        (nobs x 1+num_centers) matrix for
                        the least squares problem.
                        Suggested value for rcond is 1.e-6;
                        This variable must be positive. (input)

        rank            The numerical effective rank of the
                        least squares problem which depends
                        on rcond (output)


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             The two structures are incompatible
                        due to different specification of

                            domain_dim
                            range_dim

                        members

           2            rcond is not > 0
           3            Error from linear lsq solver dgelsx
                        (check integer members of the
                         structures)
           4            Allocation failure (check integer
                        members of the structures)

....................................................................... 
 

rbf_initialize


TYPE_export(struct RBF *) rbf_initialize(int num_centers, int domain_dim,
                                         int range_dim,
                        double (STDCALL *radial_fcn)(double, double, int),
                        int level, double seed, int  * inform)

.......................................................................

    Purpose:    This function allocates and initializes all the pointers
                in the RBF data structure.  Depending on the specified
                level some of the numerical data in the structure may 
                also be initialized.

    Return Value:  A pointer to the newly initialized RBF structure


    Arguments:

        num_centers     Number of centers (input)
        domain_dim      Domain dimension (input)
        range_dim       Range dimension (input)
        radial_fcn      Name of a function (input)
        level           Level of numerical values placed in (input)
                        the rbf structure (input)
        {
          level <= 0    All double data set to zero in rbf structure

          level  = 1    Center parameters and domain scale are
                        set to 1.1 and 1.2 respectively

          level >= 2    (level 1) and centers are filled out
                        randomly in [0,1]^(domain_dim)
        }
        seed            A seed for the random number generator
        inform          Error code (output)


    Fatal Errors (which return a NULL pointer):

        inform          Error Condition

          1             num_centers <= 0
          2             domain_dim  <= 0
          3             range_dim   <= 0
          4             allocation failure for some member of RBF

.......................................................................
 

rbf_set_values


TYPE_export(void) rbf_set_values(struct  RBF * rbf_in, struct LSD * lsd_in,
                                 double seed, int *inform)

.......................................................................

    Purpose:    This function selects centers and domain_scale values
                based on the xdata in lsd_in.  The centers are randomly
                chosen in the smallest hyper-cube containing the xdata
                values.  The domain_scale values are selected to equalize
                the apparent width of each dimension.

    Return Value:  void


    Arguments:

        rbf_in          Pointer to RBF structure (input)
        lsd_in          Pointer to LSD structure (input)
        seed            Seed for the random number generator (input)

        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             The two structures are incompatible
                        due to different specification of

                            domain_dim
                            range_dim

                        members
          2             Allocation failure (check value of domain_dim)

.......................................................................
 


Built-in radial functions:

There are four built-in radial functions. They are the gaussian, hardy_multiquadric, inverse_hardy_multiquadric, and the radial_poly. The user can add his own radial function. RBFpack supports user supplied radial functions by allowing the user to code and specify a new radial function. All the user must do is provide code based on the template of the gaussian listed below. The value r2 is the (scaled) distance squared, p is a parameter used to change the shape of the (univariate) radial function, and k is the derivative (with respect to r2). Note, there is a routine which can be used to check the correct programming of the partials (rbf_fd_der) which uses finite differences to compute the partials.

 TYPE_export(double) gaussian(double r2, double p, int k)
{
/*  Purpose:    This function computes the Gaussian
                radial function defined by

                  f(r2) = exp(-p*p*r2)
*/
    double value, f_value=0.;
    value = exp(-p*p*r2);
    if (k == 0)  f_value = value;
    if (k == 1)  f_value = -p*p*value;
    if (k == 2)  f_value = p*p*p*p*value;
    return f_value;
}

 

gaussian


TYPE_export(double) gaussian(double r2, double p, int k)

.......................................................................

    Purpose:    This function computes the Gaussian
                radial function defined by

                  f(r2) = exp(-p*p*r2)


                as well as its first and second derivatives in r2.

                This function is used as a pointer to a function in
                rbf->radial_fcn.

    Return Value:  D^k f(r2).

    Arguments:

        r2              r2 (usually the squared scaled distance from
                        scnorm) (input)
        p               A scalling parameter (input)
                        This parameter is supplied most often
                        by center_parameter members.
        k               The derivative value (input)
                        Only values 0, 1, 2 are expected,
                        all others return 0.


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

.......................................................................
 

radial_poly


TYPE_export(double) radial_poly(double r2, double p, int k)

.......................................................................

    Purpose:    This function computes the (compactly supported)
                radial function defined by

                  f(r2) =
                      (1-p*sqrt(r2))^4*(4*p*sqrt(r2) + 1) if p*sqrt(r2) < 1
                      0 if p*sqrt(r2) >= 1

                as well as its first and second derivatives in r2.

                This function is used as a pointer to a function in
                rbf->radial_fcn.


    Return Value:  D^k f(r2).

    Arguments:

        r2              r2 (usually the squared scaled distance from
                        scnorm) (input)
        p               A scalling parameter (input)
                        This parameter is supplied most often
                        by center_parameter members.
        k               The derivative value (input)
                        Only values 0, 1, 2 are expected all
                        others return 0.


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

.......................................................................
 

hardy_multiquadric


TYPE_export(double) hardy_multiquadric(double r2, double p, int k)

.......................................................................

  Purpose:    This function computes the hardy multiquadric
                radial function defined by

                  f(r2) = sqrt(p**2 + r2)


                as well as its first and second derivatives in r2.

                This function is used as a pointer to a function in
                rbf->radial_fcn.

    Return Value:  D^k f(r2).

    Arguments:

        r2              r2 (usually the squared scaled distance from
                        scnorm) (input)
        p               A scalling parameter (input)
                        This parameter is supplied most often
                        by center_parameter members.
        k               The derivative value (input)
                        Only values 0, 1, 2 are expected,
                        all others return 0.


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

.......................................................................
 

inverse_hardy_multiquadric


TYPE_export(double) inverse_hardy_multiquadric(double r2, double p, int k)

.......................................................................

  Purpose:    This function computes the inverse hardy multiquadric
                radial function defined by

                  f(r2) = 1/sqrt(p**2 + r2)


                as well as its first and second derivatives in r2.

                This function is used as a pointer to a function in
                rbf->radial_fcn.

    Return Value:  D^k f(r2).

    Arguments:

        r2              r2 (usually the squared scaled distance from
                        scnorm) (input)
        p               A scaling parameter (input)
                        This parameter is supplied most often
                        by center_parameter members.
        k               The derivative value (input)
                        Only values 0, 1, 2 are expected,
                        all others return 0.


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

.......................................................................

 


RBF_FIT options:

These routines allow the user to change the various parameters in the rbf_fit routine.

 

rbf_fit_opt_int


TYPE_export(void) rbf_fit_opt_int(char * par_name, int value,
                                  int * inform)

.......................................................................

    Purpose:    This function sets integer parameters for rbf_fit.
                Setting Optimize = 0 forces no optimization.  In this
                case the function rbf_fit relies solely on global search.
                Setting Optimize = 1 forces nonlinear optimization in
                conjunction with global search. Otherwise the
                function attempts to choose the most efficient method.

                Note: The default values are reset after each call to
                rbf_fit.  Thus they must be explicitly overridden before
                each invocation of rbf_fit.

    Return Value:  Void.


    Arguments:

        par_name        The name of the parameter to be set (input)
        value           The value of the parameter (input)

par_name         value        default

"Optimize"          0, 1          Not set
"Num_tries"         1, 2, ...     150       This parameter controls
                                            the global search.  Larger
                                            values will produce smaller
                                            sums of squares and take 
                                            more time.

 "Max_it"            1, 2, ...      30      This parameter controls the
                                            nonlinear optimizer.  Larger
                                            values will produce smaller
                                            sums of squares and take 
                                            more time.

        Fatal Errors:

        inform           Error

          1              Optimize value not 0 or 1
          2              Num_tries value not positive
          3              Max_it value not positive
          4              Unrecognized option.

.......................................................................

 

rbf_fit_opt_radfcn


TYPE_export(void) rbf_fit_opt_radfcn(double (STDCALL *radial_fcn)
                                               (double, double, int))

.......................................................................

    Purpose:    To change the default radial function used in rbf_fit
                or rbf_interpolate.

                 Note: The default values are reset after each call to
                 rbf_fit or rbf_interpolate.  Thus they must be explicitly 
                 overridden before each invocation of rbf_fit.


    Return Value:  Void.


    Arguments:

        radial_fcn      The pointer to the new radial function. (input)
                        The default radial function is the gaussian.
                        This package internally supports three other
                        radial functions:
                                           radial_poly
                                           hardy_multiquadric
                                           inverse_hardy_multiquadric

                        The user can supply his own radial function
                        provided
                        it is properly prototyped and implemented as any of
                        the above 3 functions.


        Fatal Errors:  None

.......................................................................
 


Input-Output:

These routines are designed to read or write data to files.

 

set_io_file


TYPE_export(int) set_io_file(char * file_name, char * s, int *inform)

.......................................................................

    Purpose:    This function opens or closes input or output
                files.

    Return Value:    0 for correct function
                     1 for unrecognized character string (s) input
                    -1 for file open failure


    Arguments:

        file_name       Name of file where data is to be sent (input)
        s               Option character string (input)
                        {The only strings recognized by the function
                            are:
                                "open output file"
                                "open output file append"
                                "open input file"
                                "close output file"
                                "close input file"
                        }


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             Output file could not be opened
          2             Input file could not be opened
          3             Unrecognizable second argument
          

.......................................................................
 

rbf_view


TYPE_export(void) rbf_view(struct RBF * rbf_in, int level, int * inform)

.......................................................................

    Purpose:    This function prints out various levels of information
                contained in the RBF structure.

        Return Value:  void

    Arguments:

        rbf_in          Pointer to RBF structure (input)
        level           Level of printed information (nested) (input)

        {
          level  = 0    All integer information is printed from
                        rbf_in

          level  > 0    All coefficients are printed out

          level  > 1    All centers are printed out

          level  > 2    All center parameters are printed out

          level  > 3    All "domain scale" info is printed out
        }

        inform          Error code (output)


    Fatal Errors:

        inform          Error Condition

          1             Output file not set (see set_io_file)

.......................................................................
 

rbf_error_stat


TYPE_export(void) rbf_error_stat(struct RBF * rbf_in, struct LSD * lsd_in,
                    int level, double * stat_out, int *inform)

.......................................................................

    Purpose:    This function computes statistics on the Least
                Squares Fit and if requested it prints out these
                statistics.

    Return Value:  void


    Arguments:

        rbf_in          Pointer to RBF structure (input)
        lsd_in          Pointer to LSD structure (input)
        level           level of printed output required (input)
                        {
                            level <  0  no printed output
                            level <= 0  stat_out is printed out

                        }
        stat_out        A vector of length 5 which contains statistics
                        of the fit
                        {
                            stat_out[0] = rsq (R-squre)
                            stat_out[1] = sse (normalized sum of 
                                               squares error)
                            stat_out[2] = sst (sum of squares total)
                            stat_out[3] = mae (maximum absolute error)
                            stat_out[4] = aae (average absolute error)

                            Note rsq = 1 - (sse/sst) and under 
                            usual conditions is between 0 and 1.

                        }

        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             The two structures are incompatible
                        due to different specification of

                            domain_dim
                            range_dim

                        members
          2             Allocation failure (check value of range_dim)
          3             Output file not set
          4             Allocation error in rbf_error

.......................................................................
 

lsd_read


TYPE_export(struct LSD *) lsd_read(char *file_name, int option, 
                                   int *inform)

.......................................................................

    Purpose:    This function reads data from the data file
                specified in file_name.  The first line of the file
                must contain only the three integers
                nobs domain_dim range_dim

    Return Value:  (LSD *) A pointer to a Least Squares Data set


    Arguments:

        file_name       The file_name of the data set (input)
        option          Option describing the format of the
                        file to be read(input)
                        {
                            option =  0

                        Data formated with data numbers and weights ie
                        0 .5 .3 .2  <-- xdata
                        0 .1        <-- ydata
                        0  2.       <-- weight

                              option  =  1  
                        data 
                        number   xdata     ydata    weight
                        0      .5 .3 .2     .1       2
                        1      .5 .2 .2     .2       7 

                              option = 2
                        data 
                        number   xdata     ydata   
                        0      .5 .3 .2     .1 
                        
                        The weights are set to 1 in option 2.

                        }

        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             set_io_file failed to open the designated
                        input file

          2             lsd_initialize failed to allocate the LSD
                        data structure.

          3             set_io_file failed to close the input file

.......................................................................
 

lsd_view


TYPE_export(void) lsd_view(struct LSD * lsd_in, int level,int * inform)

.......................................................................

    Purpose:    This function prints out various levels of information
                contained in the LSD structure.

        Return Value:  void

    Arguments:

        lsd_in          Pointer to RBF structure (input)
        level           Level of printed information (nested) (input)

        {
          level  = 0    All integer information is printed from
                        lsd_in

          level  > 0    The first level data points are printed out
                        with their weights.


        }

        inform          Error code (output)


    Fatal Errors:

        inform          Error Condition

          1             Output file not set (see set_io_file)

.......................................................................
 


Optimization and Support:

These routines allow one to optimize the RBF parameters in the context of a least-squares problem.

 

 rbf_optimize


TYPE_export(struct RBF *) rbf_optimize(struct RBF * rbf_in, 
                                       struct LSD * lsd,
                                       int itmax, int * inform)

.......................................................................

    Purpose:    This function returns the result
                of applying optimization to the standard regression
                problem.  The starting point for the nonlinear
                regression is contained in rbf_in and the data for
                the regression is in lsd.

    Return Value:  A pointer to the solution of the NL regression 
                   problem.


    Arguments:

        rbf_in          The initial guess for the Nonlinear
                        regression proble.  (input)
        lsd             The regression data (input)
        itmax           An upperbound on the number of line 
                        searches (input)
                        in the optimization algorithm  (input)


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             rbf_in has some int members <= 0


          2             rbf_copy failed

          3             allocation error

          J<0           error from grg2 whose value is J

.......................................................................
 

step_up_optimize


TYPE_export(struct RBF *)  step_up_optimize(struct RBF *rbf_in,
                                            struct LSD * lsd,
                     double * lbound, double * ubound, int num_steps,
                     int num_fcn_evals_per_step, int itmax, int *inform)

.......................................................................

    Purpose:    This function returns the result
                of applying a step_up algorithm followed by
                optimization to the standard regression
                problem.  The starting point for the
                regression is contained in rbf_in and the data for
                the regression is in lsd.

    Return Value:  A pointer to the solution of the step up
                   Nonlinear regression problem.


    Arguments:

        rbf_in          The initial guess for the Nonlinear
                        regression problem.  (input)
        lsd             The regression data (input)
        lbound          A pointer to the lower bounds for the
                        centers and the center_parameter. (input)
        ubound          A pointer to the lower bounds for the
                        centers and the center_parameter. (input)

        num_fcn_evals_per_step   The number of random centers tried
                                 per step in the step_up algorithm (input)
        itmax           An upper bound on the number of line searches
                        in the optimization algorithm.  (input)


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             rbf_in has some int members <= 0


          2             rbf_copy failed

.......................................................................
 

step_up


TYPE_export(struct RBF *)  step_up(struct RBF *rbf_in, struct LSD * lsd,
                     double * lbound, double * ubound, int num_steps,
                     int num_fcn_evals_per_step, int *inform)

.......................................................................

    Purpose:    This function returns the result
                of applying a step_up algorithm followed by
                optimization to the standard regression
                problem.  The starting point for the
                regression is contained in rbf_in and the data for
                the regression is in lsd.

    Return Value:  A pointer to the solution of the step up
                   Nonlinear regression problem.


    Arguments:

        rbf_in          The initial guess for the Nonlinear
                        regression problem.  (input)
        lsd             The regression data (input)
        lbound          A pointer to the lower bounds for the
                        centers and the center_parameter. (input)
        ubound          A pointer to the lower bounds for the
                        centers and the center_parameter. (input)

        num_fcn_evals_per_step   The number of random centers tried
                                 per step in the step_up algorithm (input)
        itmax           An upper bound on the number of line searches
                        in the optimization algorithm.  (input)


        inform          Error code (output)


        Fatal Errors:

        inform          Error Condition

          1             rbf_in has some int members <= 0


          2             rbf_copy failed

.......................................................................
 

rbf_to_x


TYPE_export(void) rbf_to_x(struct RBF * rbf, double *x, int centers, 
                           int rad_coef, int center_parameter, 
                           int domain_scale, int const_coef)

.......................................................................

    Purpose:    This function moves the parameters in rbf
                into the appropriate positions in x.

    Return Value:  void


    Arguments:


        rbf             The radial basis function which will
                        receive the parameters in x (output)

          x             The parameters to be copied into
                        rbf.  (input)

        centers         Variable indicating whether the centers
                        are to be varied in the NL regression
                        problem (input)

        rad_coef        Variable indicating whether the radial
                        coefficients are to be varied in the NL
                        regression problem (input)

        center_parameter    Variable indicating whether the center
                        parameters are to be varied in the NL
                        regression problem (input)

        domain_scale    Variable indicating whether the domain
                        scale are to be varied in the NL
                        regression problem (input)

        const_coef      Variable indicating whether the constant
                        coefficients are to be varied in the NL
                        regression problem (input)

.......................................................................
 

x_to_rbf


TYPE_export(void) x_to_rbf(double *x, struct RBF * rbf, int centers, 
                           int rad_coef, int center_parameter, 
                           int domain_scale, int const_coef)

.......................................................................

    Purpose:    This function moves the parameters pointed to
                by x into the appropriate positions into
                the rbf.

    Return Value:  void


    Arguments:

        x               The parameters to be copied into
                        rbf.  (input)

        rbf             The radial basis function which will
                        receive the parameters in x (output)

        centers         Variable indicating whether the centers
                        are to be varied in the NL regression
                        problem (input)

        rad_coef        Variable indicating whether the radial
                        coefficients are to be varied in the NL
                        regression problem (input)

        center_parameter    Variable indicating whether the center
                        parameters are to be varied in the NL
                        regression problem (input)

        domain_scale    Variable indicating whether the domain
                        scale are to be varied in the NL
                        regression problem (input)

        const_coef      Variable indicating whether the constant
                        coefficients are to be varied in the NL
                        regression problem (input)

.......................................................................
 

lsq_error


TYPE_export(void) lsq_error(double g[], double x[])

.......................................................................

    Purpose:    This function computes the square root of the
            least squares error given the values x and
            the global variables centers, rad_coef, center_parameter,
            domain_scale,   const_coef.  This version assumes that
            rad_coef = 0 and it computes the linear variables by calling
            rbf_lsq_fit.  This function is designed to be called
            by grg2.


    Return Value:  void


    Arguments:


        g       The objective value for the NL regression
                is stored in g[1] (output)

        x       The input independent variables for the
                grg2 function (input)


   Global Variables Used:

        glob_lsd          Pointer to global Least Squares Data set
        glob_rbf          Pointer to global rbf
        centers           = 1   Centers enter the optimization
        rad_coef          = 0   coefficients do not explicitly enter
        center_parameter  = 1   center_parameter enter the optimization
        domain_scale      = 0   domain_scale is not optimized
        const_coef        = 0   const_coef does not explicitly enter the
                                optimization problem.

.......................................................................
 


Support functions:

 

test_data


TYPE_export(struct LSD *) test_data(struct RBF * rbf, int nobs, 
                                    double seed, int choice, 
                                    int * inform)

.......................................................................

    Purpose:    This function returns an LSD * which is generated by known
                data so that we can test the least squares functions.

    Return Value:  A pointer to the LSD test data.


    Arguments:

        rbf             Radial basis function
        nobs            Number of observations (input)
        domain_dim      Domain dimension (input)
        range_dim       Range dimension (input)
        seed            Seed for the random number generator (input)
        choice          Choice of data set generated. Unless otherwise
                        stated the weights are 1 and the xdata values are
                        randomly generated in the unit cube.

                        Choice       Data
                          0            1

                          1            ydata[i] = rbf(lsd->xdata[i])
                          
                          2            ydata[i] = rbf(lsd->xdata[i])    
                                       with weights alternately 0 and 1

                          3            ydata[i] = rbf(lsd->xdata[i])    
                                       with weights alternately 1+i

                          4            same as 3 but also writes the data
                                       to the file lsq_data.txt

                          

        inform          Error code (output)


        Fatal Errors (which return a NULL pointer):

        inform          Error Condition

          1             nobs        <= 0
          2             rbf->domain_dim  <= 0
          3             rbf->range_dim   <= 0
          4             allocation failure for some member of LSD
          5             error from set_io_file

.......................................................................
 

rbf_compare


TYPE_export(double) rbf_compare(struct RBF * rbf1, struct RBF * rbf2)

.......................................................................

    Purpose:    This function compares two rbfs.  If they are
                different then the function returns a positive
                number indicating the difference.

    Return Value:  -1.  if one of the two rbfs are NULL
                    0.  if the rbfs point to identical data

                        Otherwise a positive value is returned
                        indicating that the two rbfs represent
                        different functions


    Arguments:

        rbf1        The first rbf (input)
        rbf2        The second rbf (input)

.......................................................................
 

rbf_copy


TYPE_export(struct RBF *) rbf_copy(struct RBF * rbf_in, int * inform)

.......................................................................

    Purpose:    This function produces a copy of rbf_in.

    Return Value:  Pointer to a copy of rbf_in.


    Arguments:

        rbf_in          The RBF to be copied (input)
        inform          Error code (output)

        Fatal Errors:

        inform          Error Condition

          1             rbf_in is inconsistently specified

          2             rbf_initialize failed

.......................................................................
 

copy_rbf


TYPE_export(void) copy_rbf(struct RBF * rbf_in,
                           struct RBF * rbf_out)

.......................................................................

    Purpose:    This function produces a copy of rbf_in in rbf_out.
                it is assumed that rbf_out has been appropriately
                initialized.  This function is useful if one wants
                to allocate an rbf once and reuse the allocation by
                storing "smaller" rbfs in the space.

    Return Value:  Void.


    Arguments:

        rbf_in          The rbf to be copied (input)
        rbf_out         The copied version of rbf_in (out_put)
                        rbf_out should be initialized so that the
                        following equalities and inequalities hold.

                        rbf_in-> num_centers <= rbf_out->num_centers
                        rbf_in-> domain_dim   = rbf_out->domain_dim
                        rbf_in->  range_dim   = rbf_out-> range_dim

        Fatal Errors:

        No fatal errors.

.......................................................................
 

rbf_fd_der


TYPE_export(void) rbf_fd_der(struct RBF *rbf_in, double *x, int ider1,
                             int ider2, double *value)

.......................................................................

    Purpose:    This function approximates the value

                    D_{(ider1, ider2)}F(x)

                  (of the function specified in rbf_in
                  using finite differences) and returns
                  it in the vector value.


    Return Value:   void

    Arguments:

        rbf_in          Pointer to RBF structure (input)
        x               Vector of length rbf_in->domain_dim (input)
        ider1           Partial derivative specification (input)
        ider2           Partial derivative specification (input)
        value           Value of D_{(ider1, ider2)}F(x) (output)


    Fatal Errors:

        No Fatal errors are defined since this function is the heart
        of many other computations and error handling would adversely
        affect performance.

....................................................................... 
 

free_LSD


TYPE_export(void) free_LSD(struct LSD * lsd_in)

.......................................................................

    Purpose:    This function frees all the space allocated in
                the LSD structure.
              

    Return Value:    void


    Arguments:

        rbf_in          The pointer to the LSD structure (input)
        

        No Fatal Errors

.......................................................................
 

free_RBF


TYPE_export(void) free_RBF(struct RBF * rbf_in)

.......................................................................

    Purpose:    This function frees all the space allocated in
                the RBF structure.
              

    Return Value:    void


    Arguments:

        rbf_in          The pointer to the RBF structure (input)
        

        No Fatal Errors
.......................................................................
 

get_box


TYPE_export(void) get_box(struct LSD * lsd_in, double * min_box, double *max_box)

.......................................................................

    Purpose:    This function computes the lower left
                (in min_box) and upper right (in max_box)
                coordinates of the smallest box containing
                the xdata values in lsd_in.

    Return Value:  void


    Arguments:


        min_box     A vector of length lsd_in->domain_data (output)
                    The coordinates in min_box satisfy
                        min_box[j] = min{lsd_in->xdata[i][j]: 
                                     1<= i <= lsd_in->nobs}

        max_box     A vector of length lsd_in->domain_data (output)
                    The coordinates in min_box satisfy
                        max_box[j] = max{lsd_in->xdata[i][j]: 1<= i <= lsd_in->nobs}

.......................................................................
 


RBF and LSD data structure declarations:


struct RBF  /* Radial Basis Funcion */ {
    int         num_centers;
    int         domain_dim;
    int         range_dim;
    double      (STDCALL *radial_fcn)(double, double, int);
    double **   rad_coef;
    double *    const_coef;
    double **   centers;
    double *    center_parameter;
    double *    domain_scale;
    };


struct LSD /*Least Squares Data */ {
    int         nobs;
    int         domain_dim;
    int         range_dim;
    double **   xdata;
    double **   ydata;
    double *    weight;
    };

 


Overview for MATLAB Interface

Using RBFpack is easy provided the user understands the Surface Fitting Paradigm. This paradigm is:

 

Data (LSD *) ®

Surface (RBF *) ®

Evaluate / Operate

Lsd_struct

Rbf_fit

Rbf_lsq_fit

Rbf_interpolate

Rbf_value

Rbf_error

Rbf_graph_m

 

Data

The easiest way to envision an appropriate data set for RBFpack is to think of a table or spreadsheet of data arranged in a rectangle. The first M columns represent independent values, while the last N columns contain the dependent values. We illustrate this with surface values drawn from the function

(w, x, y, z) ® (w + x + y + z, 2w + x + y + z)

which has a 4 dimensional domain and a 2 dimensional range. Some data from this surface can be found in the table below:

 

Observation #

Ind Var 1

Ind Var 2

Ind Var 3

Ind Var 4

Dep Var 1

Dep Var 2

1

.3

.2

.4

.5

1.4

1.7

2

.5

.5

.4

.1

1.5

2.0

3

.1

.1

.2

.4

.7

0.8

 

RBFpack has a data structure (LSD) to easily store and retrieve these values. Thus, the user must first initialize an LSD data structure of the correct size using lsd_struct and then stuff the problem data into the structure. In particular, lsd for the above data set would be initialized by the call lsd_struct(3, 4, 2) so that lsd.nobs = 3, lsd.domain_dim = 4, lsd.range_dim = 2, lsd.xdata is a (lsd.nobs by lsd.domain_dim) matrix, lsd.ydata is a (lsd.nobs by lsd.range_dim) matrix, and lsd.weight is a (lsd.nobs by 1) matrix.

Surface Fit

Once having stored the data in an LSD data structure, the next operation is to produce an RBF approximation to this data. There are three main methods for doing this. The function, rbf_fit, is recommended if a least squares fit is desired. This function attempts to find a global, nonlinear least-squares fit to the data by varying the centers and the center parameters. A sophisticated local minimizer (LSGRG2) is used to complement the global techniques. It is possible that rbf_fit could take too much time to arrive at an answer. In this case, we recommend rbf_lsq_fit. This will produce a least squares fit using linear techniques. The last option is to use the interpolation routine rbf_interpolate. This function produces an interpolating RBF to the data and hence is not appropriate for noisy data.

Operate

At this point, it is assumed that an RBF has been computed and stored in an RBF data structure (see rbf_struct). Having a mathematical representation of the surface is nice, but it is not very helpful if there are no evaluation or differentiation routines. Thus, one uses rbf_value to get function values and derivatives. A function is available to compute the least squares error, rbf_error, and finally there is a prototype m-file for graphing certain RBFs, rbf_graph_m.

Matlab Examples

RBFpack is designed to produce a surface from discrete data. Once produced, we can evaluate, differentiate, or view the error between the surface and data. The general methodology is to minimize the least squares error between the data and a candidate surface (using the RBF representations mentioned above). Thus the general sequence of events is:

 

Data (lsd_struct) ®

Surface (rbf_struct) ®

Evaluate / Operate

 

Data (lsd_struct)

Consider the problem of approximating the surface (x, y, sin(x+y^2)) from the data

 

X values

Y values

Sin(x+y^2)

0

0

0

0.5

0

0.479426

1

0

0.841471

0

0.5

0.247404

0.5

0.5

0.681639

1

0.5

0.948985

0

1

0.841471

0.5

1

0.997495

1

1

0.909297

 

This data has nine observations. The domain dimension is two and the range dimension is one. We present this data to the RBFpack functions through a Least Squares Data structure called LSD.

 

Example 1: rbf_fit

The following m-file follows the paradigm described above. First, the LSD data structure is allocated and filled out. Second, the RBF approximation is computed and third, this approximation is graphed, the error is computed, and the RBF is evaluated at (0,0). Notice that at most 3 centers are required for the fit. The routine rbf_fit can be very time-consuming. For that reason we have given the user the option of guiding the routine by furnishing a second argument which places an upper bound on the number of centers allowed. This m-file is provided with the RBFpack product under the name example_1.m.


function example_1()

num_points = 15;

% allocate the lsd data structure 
lsd = lsd_struct(num_points*num_points, 2, 1);

x = [0:num_points-1]/(num_points-1);

for i = 1:num_points
   for j = 1:num_points
      lsd.xdata(j + (i-1)*num_points, :) = [x(i);x(j)];
   end
end

lsd.ydata = sin(lsd.xdata(:,1) + lsd.xdata(:,2).^2);

% Get the approximation
rbf = rbf_fit(lsd, 5);

% Get the error
'the error is: '
rbf_error(rbf,lsd)

% Graph the result
rbf_graph_m(rbf, lsd, [0,0], [1,1], 'Surface Plot of RBF computed using rbf\_fit');

% Get the value of the RBF at the origin (0,0)
'The value at (0,0) is:'
rbf_value(rbf, [0,0])

 

Example 2: rbf_lsq_fit

This example uses the same data set as above and computes the least squares fit based on 10 centers. The location of the centers is randomly generated and not optimized. Comparing the error of the fit in this example with that of Example 1, we see that the error is smaller in Example 1 even though the number of centers is more than tripled. This illustrates the power of optimizing the parameters in the RBF fit. This m-file is provided with the RBFpack product under the name example_2.m.

 

function example_2()

num_points = 15;

% allocate the lsd data structure 
lsd = lsd_struct(num_points*num_points, 2, 1);

x = [0:num_points-1]/(num_points-1);

for i = 1:num_points
   for j = 1:num_points
      lsd.xdata(j + (i-1)*num_points, :) = [x(i);x(j)];
   end
end

lsd.ydata = sin(lsd.xdata(:,1) + lsd.xdata(:,2).^2);


% Get the approximation
rbf = rbf_lsq_fit(lsd, 10)

%Examine the rbf values
rbf.rad_coef
rbf.centers
rbf.center_parameter
rbf.domain_scale
rbf

% Get the error
'the error is: '
rbf_error(rbf,lsd)

% Graph the result
rbf_graph_m(rbf, lsd, [0,0], [1,1], 'Surface Plot of RBF computed using rbf\_lsq\_fit');

 

Example 3: rbf_interpolate

Interpolation is appropriate when the data is not noisy. The interpolation routine returns an RBF with as many centers as data points. Thus for very large data sets, least squares may be appropriate even if the data is not noisy. We also demonstrate the use of rbf_fit_opt_radfcn to change the radial function from 'gaussian' to 'radial_poly'. This m-file is provided with the RBFpack product under the name example_3.m.

 

function example_3()

num_points = 5;

% allocate the lsd data structure 
lsd = lsd_struct(num_points*num_points, 2, 1);

x = [0:num_points-1]/(num_points-1);

for i = 1:num_points
   for j = 1:num_points
      lsd.xdata(j + (i-1)*num_points, :) = [x(i);x(j)];
   end
end

lsd.ydata = sin(lsd.xdata(:,1) + lsd.xdata(:,2).^2);

% Get the approximation
rbf_fit_opt_radfcn('radial_poly');
rbf = rbf_interpolate(lsd);

% Get the error
'the error is: '
rbf_error(rbf,lsd)

% Graph the result
rbf_graph_m(rbf, lsd, [0,0], [1,1], 'Surface Plot of RBF computed by rbf\_interpolate');

% Get the value of the RBF at the origin (0,0)
'The value at (0,0) is:'
rbf_value(rbf, [0,0])

 

Example 4: Data with random noise

This example resets the default radial function from 'gaussian' to 'radial_poly'. We then try to fit data with noise first by using rbf_lsq_fit and then by rbf_fit. When executed, graphs of both functions are displayed. This m-file is provided with the RBFpack product under the name example_4.m.

 

function example_4()

num_points = 30;

% allocate the lsd data structure 
lsd = lsd_struct(num_points, 1, 1);

x = [0:num_points-1]/(num_points-1);


   for j = 1:num_points
      lsd.xdata(j , 1) = x(j);
   end

lsd.ydata = sin(6*lsd.xdata(:,1).^2)+ (rand(num_points, 1)-.5);

% Get the approximation
rbf_fit_opt_radfcn('radial_poly');
rbf = rbf_lsq_fit(lsd,9);


% Get the error
'the error is: '
rbf_error(rbf,lsd)

% Graph the result
rbf_graph_m(rbf, lsd, 0, 1, 'Plot of data and RBF computed by rbf\_lsq\_fit');

figure
rbf_fit_opt_radfcn('radial_poly');
rbf = rbf_fit(lsd, 3)

% Graph the result
rbf_graph_m(rbf, lsd, 0, 1, 'Plot of data and RBF computed by rbf\_fit');

% Get the error
'the error is: '
rbf_error(rbf,lsd)

 

Example 5: Range Dimension = 2

This example illustrates the