> next up previous contents index
: Inequality constraints : Higher-order conditional kernels : Higher-order conditional kernels   目次   索引

Functional diracs

In many conditional kernels $P(\Omega_s\vert\Omega_k)$ the values of $\Omega_s$ are computed as function of those of $\Omega_k$. As we pointed out before this kind of conditional kernel defines a family of diracs (see section [*]), that's why they are called Functional diracs.

Definition 26   Let $\omega=(\omega_s\cup\omega_k)\in(\Omega_s\cup\Omega_k)$. Given $f:\Omega_k \rightarrow \Omega_s$, a functional dirac on $f$ is a higher-order conditional kernel $P(\Omega_s\vert\Omega_k)$ with:


$\displaystyle compute(\omega)$ $\textstyle =$ $\displaystyle \left\{
\begin{array}{ll} 1 & if~\omega_s = f(\omega_k) \\
0 & otherwise
\end{array}\right.$  

and
$\displaystyle instantiate(\omega_k)$ $\textstyle =$ $\displaystyle dirac(\Omega_s,\omega_s) ~\mbox{ with }
\omega_s = f(\omega_k)$  

We describe now how to implement this kind of kernels on ProBT. Before we go on creating a functional dirac we need to define an ProBT external function, that is, $f$ in the previous definition. Generally speaking there are two ways of creating external functions, either by using a C++ function with the following prototype

  void user_function(plValues &output_values,
                     const plValues &input_values)

or a method of an object class

  object_class::class_method(plValues &output_values, 
                             const plValues &input_values)

In the following example we illustrate the construction of external functions and functional diracs.

Example 15   This example consists in constructing the joint distribution for the sum of points on $n$ dice and tabulate the possible values of the dice given the sum of points. Otherwise stated show every value of $\{Die_0=die_0,Die_1=die_1,...,Die_{n-1}=die_{n-1}\}$ such that $P(Die_0=die_1~Die_1=die_1 ... Die_{n-1}=die_{n-1} \vert Addition=v) \neq
0$.



Program 12: Adding n dice.

     1  /*=============================================================================
     2   * File           : addDice.cpp
     3   *=============================================================================
     4   *
     5   *------------------------- Description ---------------------------------------
     6   * This program shows the use of external functions by means of C++ functions 
     7   * The construction of a functional dirac is also shown.
     8   * The program gives the possible values of each of the dice given the sum of
     9   * points.
    10   *-----------------------------------------------------------------------------
    11  */
    12
    13  #include <pl.h>
    14
    15  void add_dice(plValues &dice_addition, const plValues &die) {
    16    unsigned int n_dice;   // Number of dice
    17    unsigned int sum=0;    // sum of points
    18    unsigned int i;
    19
    20    n_dice = die.size();   // Get the number of dice
    21
    22    for(i=0;i<n_dice;i++)  // Compute the sum of points
    23      sum = sum+die[i];
    24
    25    dice_addition[0] = sum;     // Set the output values
    26  }
    27
    28
    29  main() 
    30  {
    31   /**********************************************************************
    32       Defining the variable type, set and values plus the kernel for the
    33       variable set
    34   ***********************************************************************/ 
    35
    36    unsigned int number_of_dice;         // Stores the number of dice
    37
    38    cout<<"Give me the number of dice: ";
    39    cin>>number_of_dice;
    40
    41    plIntegerType die_type(1,6);         // die type [1,2,...,6]
    42    plIntegerType dice_sum(number_of_dice,
    43                           number_of_dice*6);// Sum type [n,n+1,...,n*6]
    44    plSymbol points("Addition",dice_sum); // Variable space for the addition
    45    plArray dice("Die",die_type,1,
    46                     number_of_dice);    // Variable space for the dice
    47    
    48    plValues result(dice^points);        // Values storing the result of the
    49                                         // dice and the addition
    50
    51    /**********************************************************************
    52        Writing the joint distribution
    53     ***********************************************************************/
    54
    55    // P(Die0 Die1 ... Die(n-1)) = Uniform(Die0 Die1 ... Die(n-1))
    56    plUniform p_dice(dice);
    57
    58    // Create the external function
    59    plExternalFunction sum(points,dice,add_dice);
    60
    61    // P(points=p | Die0=die0 Die1=die1 ... Die(n-1)=die(n-1)) = 
    62    //                  1 if points = add_dice(die0,die1,...,die(n-1)) else 0
    63    plFunctionalDirac p_addition(points,dice,sum);
    64
    65    // P(Die0 Die1...Die(n-1) points)= 
    66    //                                P(Die0 Die1 ... Die(n-1)) 
    67    //                                P(points | Die0 Die1...Die(n-1))
    68    plJointDistribution dice_jd(dice^points,p_dice*p_addition);
    69
    70    /**********************************************************************
    71        Making a question P(Die0 Die1 ... Die(n-1)| points = v)
    72     ***********************************************************************/
    73
    74    plCndKernel cnd_question;
    75    plKernel question;
    76    int v;
    77
    78    // Get P(Die0 Die1 ... Die(n-1) | points )
    79    dice_jd.ask(cnd_question,dice,points);
    80    cout<<"Give me the total number of points: ";
    81    cin>>v;
    82    result[points] = v;
    83    
    84    // Get P(Die0 Die1 ... Die(n-1) | points=v)
    85    cnd_question.instantiate(question,result);
    86
    87    /**********************************************************************
    88      Tabulate the result of the question
    89     ***********************************************************************/
    90
    91    cout<<"\nThe possibilities are :\n";
    92    question.tabulate(cout,false);
    93  }

The solution is given by Program 12. Once we know the number of dice, line 39, we can proceed to define the variable types, sets and values, lines 41 to 50. The joint distribution of the model is written at lines 51 to 69. Observe that the external function is created at line 59. The two first arguments correspond respectively to the output and input parameters of the function. In this case points$=\{Addition\}$ and dice $=\{Die0,Die1\}$. The third argument is the C++ function coded at lines 14 to 26. The add_dice function computes the total number of points given the values of each of the dice. From line 59 in the add_dice function addition corresponds to points and die to dice. Accordingly, the references die_addition[0] affects the value of $Addition$, die[0] that of Die0, die[1] that of Die1 and so on. Note that, the access to the variable sets is made by using the index of the variables and not a plSymbol. The function add_dice is general for any number $n$ of dice, where $n$ is given by die.size(). After line 63, p_addition programs a generalization of expression 4.1 for $n$ dice. The question $P(Die_0 Die_1
... Die_{n-1} \vert Addition=v)$ is produced by lines 70 to 86. The final lines 87 to 92 tabulate the resulting question distribution. The second argument of the tabulate method in line 92 indicates that the variable values of $\{Die1,Die2\}$ with a zero probability should not be printed.

Here is a sample output of Program 12:

Give me the number of dice: 3
Give me the total number of points: 15       

The possibilities are :
3 6 6  0.00462963
4 5 6  0.00462963
4 6 5  0.00462963
5 4 6  0.00462963
5 5 5  0.00462963
5 6 4  0.00462963
6 3 6  0.00462963
6 4 5  0.00462963
6 5 4  0.00462963
6 6 3  0.00462963

Note that just the values with probability different to zero has been printed out and that the probabilities are not normalized.

A second version of Program 12, using an object class method, can be easily obtained by substituting the C++ function add_dice at lines 15 to 26 by

class dice_analyzer {
public:
void dice_analyzer::add_dice(plValues &addition, const plValues &die) {

  unsigned int n_dice;   // Number of dice
  unsigned int sum=0;    // sum of points
  unsigned int i;

  n_dice = die.size();   // Get the number of dice

  for(i=0;i<n_dice;i++)  // Compute the sum of points
    sum = sum+die[i];

  addition[0] = sum;     // Set the output values
}
};

and writing,

  dice_analyzer my_analyzer;
  plExternalFunction sum(points,dice_set, &my_analyzer,
			 &dice_analyzer::add_dice);

instead of line 59. Observe that, the third argument of the plExternalFunction constructor has been replaced by two arguments: one pointing to an instance of the object class (&my_analyzer); and the other pointing to the method on the class (&dice_analyzer::add_dice).


next up previous contents index
: Inequality constraints : Higher-order conditional kernels : Higher-order conditional kernels   目次   索引
Juan-Manuel Ahuactzin 平成17年3月31日