Appendix G: Adding a Custom Chain Proposal Algorithm

When running a Monte Carlo Markov Chain with the chain command, XSPEC provides several built-in proposal options from which to draw trial parameter values for the next step in the chain. A built-in proposal is selected prior to the chain run with the command:

chain proposal <distribution> <source>
where <distribution> is the statistical distribution used to randomize the parameter values (e.g. gaussian, cauchy), and <source> refers to the source of the applied covariance information (see the chain command for details).

It is also possible for the user to create an arbitrary new proposal scheme and add it to the options available under the chain proposal command. This is done in a way similar to the adding of local models described in Appendix C, though in this case the code can only be written in C++. Essentially three steps are involved, each described in greater detail below:

  • Create a small text file named randomize.dat.
  • Write a class which inherits from XSPEC's abstract base class RandomizerBase.
  • Run XSPEC's initpackage and lmod commands to build and load the shared library containing the new proposal class(es).

The randomize.dat Initialization File

This file must be placed in the same directory as the user's proposal code files, and plays a role similar to the local models' .dat initialization files, though it has a much simpler structure. It also MUST be named randomize.dat, for this name is the only clue initpackage has to distinguish between creating a chain proposal or local models library.

All that needs to be entered into this file is a line of the form:

<class name>  [<opt string arg1> <opt string arg2> ... <opt string argN>]
for each proposal class that will go in the library. <class name> must be a case-sensitive match to the actual C++ class name, and is the only required entry on the line. The class should also be stored in code files <class name>.h and <class name>.cxx.

Any additional arguments on the line will be placed in a single C++ string (including any separating whitespace), and passed to the class constructor. This is to allow the option of setting initialization parameters at the class construction stage. Therefore if optional arguments are included, the class must have a constructor which takes a single string argument. Otherwise, the constructor should contain no arguments.

For example, a randomize.dat file declaring two classes might contain:

MyProposal1
MyProposal2    1.4773     on      false

In the code files, the constructor declarations corresponding to this would then be:

MyProposal1.h
class MyProposal1 : public RandomizerBase
{
public:
// ...
MyProposal1();
// ...
};

MyProposal2.h
class MyProposal2 : public RandomizerBase
{
public:
// ...
MyProposal2(const string& initArgs);
// ...
};

Writing a Chain Proposal Class

All user proposal classes must inherit from XSPEC's abstract class RandomizerBase, whose interface is defined in the file:

headas-<version>/Xspec/src/XSFit/Randomizer/RandomizerBase.h.
The proposal class must declare a constructor as described in the previous section, and which explicitly calls the RandomizerBase constructor, passing it a lower-case name string. This name will become the proposal identifier when making a selection using the chain proposal option during an XSPEC session. For example:
MyProposal1.cxx
MyProposal1::MyProposal1()
: RandomizerBase(“myprop1”)
{
}
In XSPEC:
XSPEC12> chain proposal myprop1 [<optional initializing args>]
The RandomizerBase class contains 5 private virtual functions: doRandomize, doInitializeLoad, doInitializeRun, doAcceptedRejected, and getCovariance.

doRandomize

doRandomize is the only pure virtual function and therefore is the only one which must be overridden in the inheriting class. Its signature is:

virtual void doRandomize(RealArray& parameterValues, const Fit* fit)
where RealArray is a typedef for std::valarray<double> and is defined in src/main/xsTypes.h. This function is called by XSPEC for each chain iteration, and XSPEC passes in the current variable model parameter values. The overridden doRandomize function performs the necessary parameter modifications and sends them back in the same array.

The function's second argument is a const pointer to XSPEC's global Fit class object. For those willing to further explore XSPEC's internals, this pointer provides access to various fit and chain information (such as covariance matrices), which may be necessary for the user's proposal scheme.

doInitializeLoad and doInitializeRun

doInitializeLoad and doInitializeRun may be optionally overridden to perform initialization tasks at different stages during runtime. The default versions of these functions in RandomizerBase do nothing. doInitializeLoad is called by XSPEC immediately after the proposal is selected with the chain proposal command. Therefore one may find it useful to have this function process any additional arguments which may be entered on the command line:

chain proposal myprop [<optional initializing args>]

XSPEC automatically bundles [<optional initializing args>] into a single string and places it in the m_initString data member of RandomizerBase, to which the inheriting class has access. doInitializeRun is called once at the start of a chain run, and is useful for any tasks which must be performed one time immediately after the chain run command is entered.

doAcceptedRejected is called after each iteration in the chain. Its first argument is an array filled with the most recently attempted model parameter values, and its second argument is a boolean true or false indicating whether the attempt was accepted or rejected. The base class function does nothing with this, but an inherited class may want to use this information in an overriden function.

In its simplest form, a proposal class may be declared and defined as in the following example. This doesn't actually do anything since the doRandomize function is empty and the parameterValues array is left unchanged.

MyProposal.h
#ifndef MYPROPOSAL_H
#define MYPROPOSAL_H

#include <xsTypes.h>
#include <XSFit/Randomizer/RandomizerBase.h>

class Fit; // only a forward declaration is required for Fit

class MyProposal : public RandomizerBase
{
public:
MyProposal();
virtual ~MyProposal();
private:
virtual void doRandomize(RealArray& parameterValues, const Fit* fit);
};

#endif

MyProposal.cxx
#include “MyProposal.h”
#include <XSFit/Fit/Fit.h>

MyProposal::MyProposal()
: RandomizerBase(“myprop”)
{
}

MyProposal::~MyProposal()
{
}

void MyProposal::doRandomize(RealArray& parameterValues, const Fit* fit)
{
// This is where the proposal algorithm should modify the variable
// model parameters in the parameterValues array.
}

Building and Loading the Proposal Class Library

Once the randomize.dat file and the class(es) have been written, the library can be built and loaded during an XSPEC session using the same initpackage and lmod sequence that is used for local model libraries. To create a Makefile and build the library:

XSPEC12> initpackage <name> randomize.dat <directory>
To load the new proposal(s) into XSPEC:
XSPEC12> lmod <name> <directory>
where <name> is the name you choose for the package collection of proposal classes. It will also become the library file name. The only differences from the local models case are that here the initializer file MUST be named randomize.dat, and that the directory path to the proposal classes (either relative or absolute) must be provided on the command line. If this is left off XSPEC will default to looking in the directory set by LOCAL_MODEL_DIRECTORY, and these classes should NOT be stored in the same directory as local models. If the building and loading has successfully completed, you should see the proposal name (the same name string that was passed to the RandomizerBase constructor) appear in the chain proposal list displayed by typing chain proposal with no other arguments.


HEASARC Home | Observatories | Archive | Calibration | Software | Tools | Students/Teachers/Public

Last modified: Friday, 23-Aug-2024 13:20:40 EDT