[pomp-announce] pomp version 0.29-1

Aaron A. King kingaa at umich.edu
Sun May 23 17:16:17 CEST 2010


This note is to let you know about changes to the pomp package that may affect 
you.  These changes will become effective as of version 0.29-1. There are two 
main changes to the interface: the first preserves backward compatibility 
(your old codes will continue to work fine for the time being even if you 
ignore it), the second does not, but the changes introduced in the second are 
quite minor and it only affects you if you use compiled native routines in 
the measurement model.

There are three main changes in version 0.29-1.

1. Substantial improvements to the documentation, including both the vignettes 
and the manual pages.

2. A bigger, more intuitive, and easier-to-use set of "plugins" for filling 
the 'rprocess' slot of a 'pomp' object.

3. Changes to the C interface for 'rmeasure' and 'dmeasure' functions.

The first and second changes preserve backward compatibility: your old codes 
will work fine even if you do not make use of the new functionality. Using 
the old-style plugins 'euler.simulate' or 'onestep.simulate' will result in 
annoying warnings about these functions being deprecated and suggesting that 
you migrate to the new-style plugins sometime soon. In a future release of 
pomp, 'euler.simulate' and 'onestep.simulate' will disappear. 

The third change does NOT preserve backward compatibility. If you use compiled 
native routines for 'rmeasure' and/or 'dmeasure', you must modify those 
routines or your codes will not work properly (and will almost certainly 
crash) when used with versions 0.29-1 and later of pomp. The required 
modification is quite minor, however, and is detailed below.

In more detail:

Change 1. 
The vignettes have been completely rewritten to be useful as tutorials. The 
first vignette, "intro_to_pomp", is a step-by-step guide to the construction 
of a 'pomp' and simulation, particle filtering, trajectory-matching, iterated 
filtering, and nonlinear forecasting. View it by doing
R> ?vignette("intro_to_pomp")
The second vignette shows how to accelerate performance using compiled native 
routines and briefly introduces the developer interface to pomp.  View it by 
doing
R> ?vignette("advanced_topics_in_pomp")

Change 2. New plugins.
As you probably know very well, it can be challenging to implement a model in 
pomp.  In particular, the most difficult bit is typically writing the process 
model simulator (rprocess).  In an effort to make this more intuitive, I have 
provided several new "plugins": functions that write the 'rprocess' function 
for you given minimal input on the form of the model.

For some time there has been some plugin functionality, but their structure 
has made them nonintuitive and their documentation difficult to understand 
from the user's point of view. The new plugins are much more straightforward 
to use and their documentation is clearer (I hope). The new plugins provide 
precisely the same functionality: only the interface has changed. To be 
clear: switching over to the new-style plugins will have no effect on the 
underlying model nor, therefore, on inferences that have been based on that 
model.  

If you have been using the old-style plugins (euler.simulate or 
onestep.simulate), you can continue to do so for the time being. However, 
warning messages will be generated to inform you that these functions are 
deprecated and will be removed in a later release of pomp.  

To switch over to the new-style plugins, you need only edit a few lines in the 
R code that constructs a pomp object.  Specifically, if you use

pomp(...,rprocess=euler.simulate,...,delta.t=dt,...,step.fun=foo,...,PACKAGE=bar, ...)

where 'foo' is either an R function or the name of a compiled native routine, 
and 'bar' is the name of the shared-object library where the compiled native 
routine resides, you can achieve the same functionality by using

pomp(...,rprocess=euler.sim(step.fun=foo,delta.t=dt,PACKAGE=bar),...)

Similarly, if you use 

pomp(...,rprocess=onestep.simulate,...,step.fun=foo,...,PACKAGE=bar,...)

replace it with

pomp(...,rprocess=onestep.sim(step.fun=foo,PACKAGE=bar),...)

Essentially, the new-style plugins are functions that return "customized" 
functions suitable for use in the 'rprocess' slot of a 'pomp' object.

There are now new plugins that include a discrete-time model plugin 
('discrete.time.sim') and an implementation of the Gillespie algorithm 
('gillespie.sim'). The FORTRAN codes that underly 'gillespie.sim' are due to 
Helen Wearing.  For documentation on the new functionality, see
R> ?plugins
or 
R>?euler.sim
R>?gillespie.sim
R>?onestep.sim
R>?discrete.time.sim

Change 3. 
New interface for C versions of 'rmeasure' and 'dmeasure'.

This change only affects you if you use compiled native routines for the 
measurement portion of your model.  If you specify your measurement model 
either using 'measurement.model=blah' or by specifying 'rmeasure' 
and/or 'dmeasure' as R functions, you need do nothing.

If you have written C functions to implement your measurement model, you have 
written a C function of prototype

void pomp_measure_model_simulator (double *y, double *x, double *p, int 
*stateindex, 
int *parindex, int *covindex, int ncovars, double *covars, double t);

and/or a function of prototype

void pomp_measure_model_density (double *lik, double *y, double *x, double *p,
int give_log, int *stateindex, int *parindex, int *covindex, int ncovars, 
double
*covars, double t);

In the new version of 'pomp', you must modify these functions to have 
prototypes

void pomp_measure_model_simulator (double *y, double *x, double *p, 
int *obsindex, int *stateindex, int *parindex, int *covindex, int ncovars, 
double *covars, double t);

and

void pomp_measure_model_density (double *lik, double *y, double *x, double *p,
int give_log, int *obsindex, int *stateindex, int *parindex, int *covindex, 
int
ncovars, double *covars, double t);

The only difference is that you need to insert a new int* argument 'obsindex' 
in the appropriate place.

If you simply insert the new argument and do nothing more, your codes should 
function as before. If you wish to take advantage of the new functionality, 
it should make your codes more robust. To do so, when constructing a 'pomp' 
object, specify the names of observed variables in the 'obsnames' argument 
to 'pomp'. If you have done this, upon any call to either your C 'dmeasure' 
or 'rmeasure' function, 'obsindex' will be a pointer to a set of integers 
that indicate the positions in 'y' that correspond to the variables 
in 'obsnames' in that order. Thus, 'obsindex' is exactly analogous 
to 'stateindex', 'parindex', and 'covindex': 'obsindex' is to 'y' 
as 'stateindex' is to 'x' as 'parindex' is to 'p' as 'covindex' is 
to 'covars'.

Here is an example of one of my own codes.  Before version 0.29-1, the code 
was:
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
#define TAU          (p[parindex[0]])
#define DEATHS       (x[stateindex[4]])
#define DATADEATHS   (y[0])

void norm_rmeasure (double *y, double *x, double *p, 
		    int *stateindex, int *parindex, int *covindex,
		    int ncovars, double *covars, double t)
{
  double v, tol = 1.0e-18;
  v = DEATHS*exp(TAU);
  if (!(R_FINITE(v))) {
    DATADEATHS = R_NaReal;
  } else {
    DATADEATHS = rnorm(DEATHS,v+tol);
  }
}

void norm_dmeasure (double *lik, double *y, double *x, double *p, int 
give_log,
		    int *stateindex, int *parindex, int *covindex,
		    int ncovars, double *covars, double t)
{
  double v, tol = 1.0e-18;
  v = DEATHS*exp(TAU);
  if (!(R_FINITE(v))) {
    *lik = tol;
  } else {
    *lik = dnorm(DATADEATHS,DEATHS,v+tol,0)+tol;
  }
  if (give_log) *lik = log(*lik);
}

#undef TAU
#undef DEATHS
#undef DATADEATHS
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

As of pomp version 0.29-1, the code is:
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
#define TAU          (p[parindex[0]])
#define DEATHS       (x[stateindex[4]])
#define DATADEATHS   (y[obsindex[0]])

void norm_rmeasure (double *y, double *x, double *p, 
		    int *obsindex, int *stateindex, int *parindex, int *covindex, 
		    int ncovars, double *covars, double t)
{
  double v, tol = 1.0e-18;
  v = DEATHS*exp(TAU);
  if (!(R_FINITE(v))) {
    DATADEATHS = R_NaReal;
  } else {
    DATADEATHS = rnorm(DEATHS,v+tol);
  }
}

void norm_dmeasure (double *lik, double *y, double *x, double *p, int 
give_log,
		    int *obsindex, int *stateindex, int *parindex, int *covindex,
		    int ncovars, double *covars, double t)
{
  double v, tol = 1.0e-18;
  v = DEATHS*exp(TAU);
  if (!(R_FINITE(v))) {
    *lik = tol;
  } else {
    *lik = dnorm(DATADEATHS,DEATHS,v+tol,0)+tol;
  }
  if (give_log) *lik = log(*lik);
}

#undef TAU
#undef DEATHS
#undef DATADEATHS
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

A diff on these two shows just the changes:
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
3c3
< #define DATADEATHS   (y[0])
---
> #define DATADEATHS   (y[obsindex[0]])
6c6
<                   int *stateindex, int *parindex, int *covindex,
---
>                   int *obsindex, int *stateindex, int *parindex, int 
*covindex,
19c19
<                   int *stateindex, int *parindex, int *covindex,
---
>                   int *obsindex, int *stateindex, int *parindex, int 
*covindex,
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

If you have any questions or problems, please don't hesitate to contact me 
directly. As always, bug reports and suggestions for improvements are more 
than welcome.

Cheers,

Aaron
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.r-forge.r-project.org/pipermail/pomp-announce/attachments/20100523/6bbc85a4/attachment.pgp>


More information about the pomp-announce mailing list