import java.util.*;
import java.io.*;
import java.lang.*;

/**
 * This class implements Panjer's algorithm
 * in the case of discrete claim sizes.
 *
 * Name the file Panjer.java
 * javac Panjer.java
 * java Panjer
 *
 * @author    Hendrik Schmidt 
 * @version   1.1, 05/07/04
 */
public class Panjer {

    // Global variable
    /** Paramter of the distribution of N. */
    static double p = 100.0/101.0;
    /** Paramter of the distribution of U.*/
    static double delta = 1.0;
    /** Stepwidth. */
    static double h = 0.01;
    /** Number of steps. */
    static int n = 201;
    /** Paramter a of Panjer's recursion. */
    static double a = p;
    /** Paramter b of Panjer's Recursion. */
    static double b = 0.0;

    /** 
     * Main method for the computation of probabilities according to Panjer.
     */
    public static void main (String[] args) {

	// Computation of claim size distribution
	double[] q = new double[n];
	
	for (int i = 0; i < n; i++) {
	    q[i] = getExpCDF(delta,h*(((double) i) + 1.0)) - 
                   getExpCDF(delta,h*((double) i));
	}

	// Compuatation of Panjer-probabilities	  
	double[] pX = new double[n];
	
	pX = getPanjer(n,((1.0-p)/(1.0-a*q[0])),q,a,b);

	// Computation of tail-probabilities	
	double[] rx = new double[n];
	rx[0] = 1 - pX[0];

	for (int i = 1; i < n; i++) {
	    rx[i] = rx[i-1] - pX[i];
	} 
	
	// printout of tail-probabilities
	System.out.println("h*i     TailProb(h*i)");
	for (int i = 20; i < n; i+=20) {
	    System.out.println(((double) i)*h + "     " + rx[i]);
	}
	
	// alternative printout
	System.out.println();
	System.out.println("h*i     TailProb(h*i)");
	for (int i = 20; i < n; i+=20) {
	    double probsum = 0.0;
	    for (int j = 0; j <= i; j++) {
		probsum += pX[j];
	    }
	    double tailprob = 1.0 - probsum;
	    System.out.println(((double) i)*h + "     "  + tailprob);
	}
	
    }

    /**
     * This method returns the values of px, i.e.
     * the probability that X=j for j = 0 ... n
     *
     * @param n      number of itarations.
     * @param p0     probability that X = 0.
     * @param q      probability of U.
     * @param a      variable a in Panjer's recursion-formula.
     * @param b      variable b in Panjer's recursion-formula.
     * @return       value of px.
     */
    public static double[] getPanjer (int n, double p0, 
                                 double[] q, double a, double b) {

	double[] px = new double[n];
	px[0] = p0;
	double u = 1.0/(1.0-a*q[0]);

	for (int i = 1; i < n; i++) {
	    double sum = 0.0;
	    for (int j = 1; j <= i; j++) {
		sum += (a + b*((double) j)/((double) i))*q[j]*px[i-j];
	    }
	    px[i] = u * sum;
	}

	return px;
    }

    /**
     * This method returns the values of the cdf of an
     * expontial-distribution.
     *
     * @param lambda   parameter of an expontial-distribution.
     * @param x        the abscissa.
     * @return         the function value. 
     */ 
    public static double getExpCDF (double lambda, double x) {
	return 1.0 - Math.exp(-lambda*x);
    }


}


