5
This small program tests two methods or routines for calculating the
6
transition probability matrix for a time reversible Markov rate matrix.
7
The first is the routine matexp(), which uses repeated squaring and works
8
on a general matrix (not necesarily time reversible). For large distances,
9
more squaring should be used, but I have not tested this extensively. You
10
can change TimeSquare to see its effect.
11
The second method, PMatQRev, uses a routine for eigen values and eigen
12
vectors for a symmetrical matrix. It involves some copying and moving
13
around when some frequencies are 0.
14
For each algorithm, this program generates random frequencies and random rate
15
matrix and then calls an algorithm to calculate P(t) = exp(Q*t).
17
cl -O2 -Ot -W4 testPMat.c tools.c
18
cc -O3 testPMat.c tools.c -lm
26
int n=400, noisy=0, i,j;
27
int nr=10, ir, TimeSquare=10, algorithm; /* TimeSquare should be larger for large t */
28
double t=5, *Q, *pi, *space, s;
29
char timestr[96], *AlgStr[2]={"repeated squaring", "eigensolution"};
31
if((Q=(double*)malloc(n*n*5*sizeof(double))) ==NULL) error2("oom");
34
for(algorithm=0; algorithm<2; algorithm++) {
37
for (i=0; i<n; i++) pi[i]=rndu();
39
for (i=0; i<n; i++) pi[i]/=s;
41
for(ir=0; ir<nr; ir++) {
42
printf("Replicate %d/%d ", ir+1,nr);
45
for (j=0,Q[i*n+i]=0; j<i; j++)
46
Q[i*n+j]=Q[j*n+i] = square(rndu());
50
for(i=0,s=0; i<n; i++) { /* rescaling Q so that average rate is 1 */
51
Q[i*n+i]=0; Q[i*n+i]=-sum(Q+i*n, n);
56
matout(stdout, pi, 1, n);
57
matout(stdout, Q, n, n);
61
matexp(Q, 1, n, TimeSquare, space);
63
PMatQRev(Q, pi, 1, n, space);
64
printf("%s, time: %s\n", AlgStr[algorithm], printtime(timestr));
66
matout(stdout, Q, n, n);