1 /* PAMP.c, Copyright, Ziheng Yang, April 1995.
\r
2 Specify the sequence type in the file pamp.ctl. Results go into mp.
\r
4 gcc -o pamp pamp.c tools.o
\r
5 pamp <ControlFileName>
\r
11 #define NBRANCH (NS*2-2)
\r
12 #define NNODE (NS*2-1)
\r
19 double DistanceREV (double Ft[], int n, double alpha, double Root[], double U[],
\r
20 double V[], double pi[], double space[], int *cond);
\r
21 int PMatBranch (double Ptb[], int n, double branch[],
\r
22 double Root[], double U[], double V[], double space[]);
\r
23 int PatternLS (FILE *fout, double Ft[],double alpha, double space[], int *cond);
\r
24 int testx (double x[], int np);
\r
25 int GetOptions (char *ctlf);
\r
26 int AlphaMP (FILE* fout);
\r
27 int PatternMP (FILE *fout, double Ft[]);
\r
28 int PathwayMP1 (FILE *fout, int *maxchange, int NSiteChange[],
\r
29 double Ft[], double space[], int job);
\r
30 double lfunAlpha_Sullivan (double x);
\r
31 double lfunAlpha_YK96 (double x);
\r
34 unsigned char *z[NS];
\r
35 char *spname[NS], seqf[256],outf[256],treef[256];
\r
36 int seqtype, ns, ls, ngene, posG[NGENE+1],lgene[NGENE],*pose,npatt, readpattern;
\r
37 int np, ntime, ncode,fix_kappa,fix_rgene,fix_alpha, clock, model, ncatG, cleandata;
\r
39 double *fpatt, *conP;
\r
41 double lmax,pi[NCODE], kappa,alpha,rou, rgene[NGENE],piG[NGENE][NCODE];
\r
44 int nbranch, nnode, root, branches[NBRANCH][2];
\r
48 int father, nson, sons[MAXNSONS], ibranch;
\r
49 double branch, age, label, *conP;
\r
50 char *nodeStr, fossil;
\r
54 #define NCATCHANGE 100
\r
55 extern int noisy, *ancestor;
\r
56 extern double *SeqDistance;
\r
57 int maxchange, NSiteChange[NCATCHANGE];
\r
59 int LASTROUND=0; /* no use for this */
\r
62 #define REALSEQUENCE
\r
63 #define NODESTRUCTURE
\r
64 #define RECONSTRUCTION
\r
66 #include "treesub.c"
\r
68 int main (int argc, char *argv[])
\r
70 FILE *ftree, *fout, *fseq;
\r
71 char ctlf[32]="pamp.ctl";
\r
72 char *Seqstr[]={"nucleotide", "", "amino-acid", "Binary"};
\r
73 int itree, ntree, i, j, s3;
\r
76 com.nhomo=1; com.print=1;
\r
77 noisy=2; com.ncatG=8; com.clock=0; com.cleandata=1;
\r
80 if(argc>1) { strcpy(ctlf, argv[1]); printf("\nctlfile set to %s.\n",ctlf);}
\r
82 printf("PAMP in %s\n", pamlVerStr);
\r
83 if ((fseq=fopen(com.seqf, "r"))==NULL) error2 ("seqfile err.");
\r
84 if ((fout=fopen (com.outf, "w"))==NULL) error2("outfile creation err.");
\r
85 if((fseq=fopen (com.seqf,"r"))==NULL) error2("No sequence file!");
\r
86 ReadSeq (NULL, fseq, com.cleandata, 0);
\r
88 i=(com.ns*2-1)*sizeof(struct TREEN);
\r
89 if((nodes=(struct TREEN*)malloc(i))==NULL) error2("oom");
\r
91 fprintf (fout,"PAMP %15s, %s sequences\n", com.seqf, Seqstr[com.seqtype]);
\r
92 if (com.nhomo) fprintf (fout, "nonhomogeneous model\n");
\r
94 space = (double*)malloc(1000000*sizeof(double)); /* not safe */
\r
95 SeqDistance=(double*)malloc(com.ns*(com.ns-1)/2*sizeof(double));
\r
96 ancestor=(int*)malloc(com.ns*(com.ns-1)/2*sizeof(int));
\r
97 if (SeqDistance==NULL||ancestor==NULL) error2("oom");
\r
99 i = com.ns*(com.ns-1)/2;
\r
100 s3 = sizeof(double)*((com.ns*2-2)*(com.ns*2-2 + 4 + i) + i);
\r
101 s3 = max2(s3, com.ncode*com.ncode*(2*com.ns-2+1)*(int)sizeof(double));
\r
103 Ft = (double*) malloc(s3);
\r
104 if (space==NULL || Ft==NULL) error2 ("oom space");
\r
106 InitializeBaseAA (fout);
\r
107 if (com.ngene>1) error2 ("option G not allowed yet");
\r
110 PatternLS (fout, Ft, 0., space, &i);
\r
111 printf ("\nPairwise estimation of rate matrix done..\n");
\r
114 ftree=gfopen (com.treef,"r");
\r
115 fscanf (ftree, "%d%d", &i, &ntree);
\r
116 if (i!=com.ns) error2 ("ns in the tree file");
\r
118 for(itree=0; itree<ntree; itree++) {
\r
120 printf ("\nTREE # %2d\n", itree+1);
\r
121 fprintf (fout,"\nTREE # %2d\n", itree+1);
\r
123 if (ReadTreeN (ftree, &i,&j, 0, 1)) error2 ("err tree..");
\r
124 OutTreeN (F0, 0, 0); FPN (F0);
\r
125 OutTreeN (fout, 0, 0); FPN (fout);
\r
127 for (i=0,maxchange=0; i<NCATCHANGE; i++) NSiteChange[i]=0;
\r
129 PathwayMP1 (fout, &maxchange, NSiteChange, Ft, space, 0);
\r
130 printf ("\nHartigan reconstruction done..\n");
\r
132 fprintf (fout, "\n\n(1) Branch lengths and substitution pattern\n");
\r
133 PatternMP (fout, Ft);
\r
134 printf ("pattern done..\n"); fflush(fout);
\r
136 fprintf (fout, "\n\n(2) Gamma parameter\n");
\r
138 printf ("gamma done..\n"); fflush(fout);
\r
140 fprintf (fout, "\n\n(3) Parsimony reconstructions\n");
\r
141 PathwayMP1 (fout, &maxchange, NSiteChange, Ft, space, 1);
\r
142 printf ("Yang reconstruction done..\n"); fflush(fout);
\r
148 int GetOptions (char *ctlf)
\r
150 int iopt, nopt=6, i, lline=4096, t;
\r
151 char line[4096], *pline, opt[32], *comment="*#";
\r
152 char *optstr[] = {"seqfile","outfile","treefile", "seqtype", "ncatG", "nhomo"};
\r
153 FILE *fctl=gfopen (ctlf, "r");
\r
157 if (fgets (line, lline, fctl) == NULL) break;
\r
158 for (i=0,t=0; i<lline&&line[i]; i++)
\r
159 if (isalnum(line[i])) { t=1; break; }
\r
160 else if (strchr(comment,line[i])) break;
\r
161 if (t==0) continue;
\r
162 sscanf (line, "%s%*s%d", opt, &t);
\r
163 if ((pline=strstr(line, "="))==NULL) error2 ("option file.");
\r
165 for (iopt=0; iopt<nopt; iopt++) {
\r
166 if (strncmp(opt, optstr[iopt], 8)==0) {
\r
168 printf ("\n%3d %15s | %-20s %6d", iopt+1,optstr[iopt],opt,t);
\r
170 case ( 0): sscanf(pline+2, "%s", com.seqf); break;
\r
171 case ( 1): sscanf(pline+2, "%s", com.outf); break;
\r
172 case ( 2): sscanf(pline+2, "%s", com.treef); break;
\r
173 case (3): com.seqtype=t; break;
\r
174 case (4): com.ncatG=t; break;
\r
175 case (5): com.nhomo=t; break;
\r
181 { printf ("\nopt %s in %s\n", opt, ctlf); exit (-1); }
\r
186 if (noisy) printf ("\nno ctl file..");
\r
188 if (com.seqtype==0) com.ncode=4;
\r
189 else if (com.seqtype==2) com.ncode=20;
\r
190 else if (com.seqtype==3) com.ncode=2;
\r
191 else error2("seqtype");
\r
192 if (com.ncatG>NCATG) error2 ("raise NCATG?");
\r
197 int AlphaMP (FILE* fout)
\r
200 double x, xb[2], lnL, var;
\r
202 xb[0]=1e-3; xb[1]=99; /* alpha */
\r
204 fprintf (fout, "\n# changes .. # sites");
\r
205 for (k=0,ntotal=0,MuChange=var=0; k<maxchange+1; k++) {
\r
206 fprintf (fout, "\n%6d%10d", k, NSiteChange[k]);
\r
207 ntotal+=NSiteChange[k]; MuChange+=k*NSiteChange[k];
\r
208 var+=k*k*NSiteChange[k];
\r
211 var=(var-MuChange*MuChange*ntotal)/(ntotal-1.);
\r
212 x=MuChange*MuChange/(var-MuChange);
\r
213 fprintf (fout, "\n\n# sites%6d, total changes%6d\nmean-var%9.4f%9.4f",
\r
214 ntotal, (int)(ntotal*MuChange+.5), MuChange, var);
\r
215 fprintf (fout, "\nalpha (method of moments)%9.4f", x);
\r
218 LineSearch(lfunAlpha_Sullivan, &lnL, &x, xb, 0.02, 1e-8);
\r
219 fprintf (fout, "\nalpha (Sullivan et al. 1995)%9.4f\n", x);
\r
221 MuChange/=tree.nbranch;
\r
222 LineSearch(lfunAlpha_YK96, &lnL, &x, xb, 0.02, 1e-8);
\r
223 fprintf (fout, "alpha (Yang & Kumar 1995, ncatG= %d)%9.4f\n", com.ncatG,x);
\r
227 double lfunAlpha_Sullivan (double x)
\r
230 double lnL=0, a=x, t;
\r
232 FOR (k, maxchange+1) {
\r
233 if (NSiteChange[k]==0) continue;
\r
234 t=-a*log(1+MuChange/a);
\r
236 t+=LnGamma(k+a)-LnGamma(k+1.) - LnGamma(a)
\r
237 + k*log(MuChange/a/(1+MuChange/a));
\r
238 lnL += NSiteChange[k]*t;
\r
243 double lfunAlpha_YK96 (double x)
\r
245 int k, ir, b=tree.nbranch, n=com.ncode;
\r
246 double lnL=0, prob, a=x, t=MuChange, p;
\r
247 double freqK[NCATG], rK[NCATG];
\r
249 DiscreteGamma (freqK, rK, a, a, com.ncatG, 0);
\r
250 FOR (k, maxchange+1) {
\r
251 if (NSiteChange[k]==0) continue;
\r
252 for (ir=0,prob=0; ir<com.ncatG; ir++) {
\r
253 p=1./n+(n-1.)/n*exp(-n/(n-1.)*rK[ir]*t);
\r
254 prob+=freqK[ir]*pow(p,(double)(b-k))*pow((1-p)/(n-1.),(double)k);
\r
256 lnL += NSiteChange[k]*log(prob);
\r
262 int OutQ (FILE *fout, int n, double Q[], double pi[], double Root[],
\r
263 double U[], double V[], double space[])
\r
267 double *T1=space, t;
\r
269 fprintf(fout,"\nrate matrix Q: Qij*dt = prob(i->j; dt)\n");
\r
271 /* matout (fout, pi, 1, n); */
\r
272 matout (fout, Q, n, n);
\r
274 fprintf (fout, "Order: T, C, A, G");
\r
275 t=pi[0]*Q[0*4+1]+pi[1]*Q[1*4+0]+pi[2]*Q[2*4+3]+pi[3]*Q[3*4+2];
\r
276 fprintf (fout, "\nAverage Ts/Tv =%9.4f\n", t/(1-t));
\r
280 for (i=0; i<n; i++,FPN(fout))
\r
281 FOR (j,n) fprintf (fout, "%6.0f", Q[i*n+j]*100);
\r
284 fprintf (fout,"\n%-4s", getAAstr(aa3,i));
\r
285 FOR (j,i) fprintf (fout, "%4.0f", Q[i*n+j]/pi[j]*100);
\r
286 fprintf (fout, "%4.0f", -Q[i*n+i]*100);
\r
288 fputs("\n ",fout); FOR(i,naa) fprintf(fout,"%5s",getAAstr(aa3,i));
\r
290 fprintf (fout, "\n\nPAM matrix, P(0.01)\n");
\r
291 FOR (i,n) FOR (j,n) T1[i*n+j]=U[i*n+j]*exp(0.01*Root[j]);
\r
292 matby (T1, V, Q, n, n, n);
\r
293 FOR (i,n*n) if (Q[i]<0) Q[i]=0;
\r
295 fprintf (fout,"\n%-4s", getAAstr(aa3,i));
\r
296 FOR(j,n) fprintf(fout, "%6.0f", Q[i*n+j]*10000);
\r
298 fputs("\n ",fout); FOR(i,n) fprintf(fout,"%5s",getAAstr(aa3,i));
\r
303 int PMatBranch (double Ptb[], int n, double branch[],
\r
304 double Root[], double U[], double V[], double space[])
\r
306 /* homogeneised transition prob matrix, with one Q assumed for the whole tree
\r
309 double *T1=space, *P;
\r
311 FOR (k, tree.nbranch) {
\r
313 FOR (i,n) FOR (j,n) T1[i*n+j]=U[i*n+j]*exp(Root[j]*branch[k]);
\r
314 matby (T1, V, P, n, n, n);
\r
315 FOR (i,n*n) if (P[i]<0) P[i]=0;
\r
317 printf ("\nbranch %d, P(%.5f)", k+1, branch[k]);
\r
318 matout (F0, P, n, n);
\r
326 int PatternMP (FILE *fout, double Ft[])
\r
328 /* Ft[]: input counts for the F(t) matrix for each branch, output P(t)
\r
330 int n=com.ncode, i,j,k;
\r
331 double *Q, *pi, *Root, *U, *V, *branch, *space, *T1, t;
\r
333 if((Q=(double*)malloc((n*n*6+tree.nbranch)*sizeof(double)))==NULL)
\r
334 error2("PathwayMP: oom");
\r
335 pi=Q+n*n; Root=pi+n; U=Root+n; V=U+n*n; branch=V+n*n;
\r
336 space=T1=branch+tree.nbranch;
\r
338 for (k=0; k<tree.nbranch; k++) { /* branch lengths */
\r
339 xtoy(Ft+k*n*n, Q, n*n);
\r
340 branch[k]=nodes[tree.branches[k][1]].branch=
\r
341 DistanceREV(Q, n, 0, Root, U, V, pi, space, &j);
\r
343 OutTreeB (fout); FPN (fout);
\r
344 FOR (i, tree.nbranch) fprintf(fout,"%9.5f", branch[i]);
\r
345 fprintf (fout,"\ntree length: %9.5f\n", sum(branch,tree.nbranch));
\r
347 /* pattern Q from average F(t) */
\r
348 fprintf(fout,"\nF(t)");
\r
349 xtoy (Ft+tree.nbranch*n*n, Q, n*n);
\r
350 matout2 (fout, Q, n, n, 12, 2);
\r
351 DistanceREV (Q, n, 0, Root, U, V, pi, space, &j);
\r
352 if (noisy>=3&&j==-1) { puts("F(t) modified in DistanceREV"); }
\r
354 OutQ (fout, n, Q, pi, Root, U, V, T1);
\r
356 PMatBranch (Ft, n, branch, Root, U, V, space);
\r
358 for (k=0; k<tree.nbranch; k++) {
\r
359 for (i=0; i<n; i++) {
\r
360 t=sum(Ft+k*n*n+i*n, n);
\r
361 if (t>1e-5) abyx (1/t, Ft+k*n*n+i*n, n);
\r
362 else Ft[k*n*n+i*n+i]=1;
\r
371 int PathwayMP1 (FILE *fout, int *maxchange, int NSiteChange[],
\r
372 double Ft[], double space[], int job)
\r
374 /* Hartigan, JA. 1973. Minimum mutation fits to a given tree.
\r
375 Biometrics, 29:53-65.
\r
377 job=0: 1st pass: calculates maxchange, NSiteChange[], and Ft[]
\r
378 job=1: 2nd pass: reconstructs ancestral character states (->fout)
\r
380 char *pch=(com.seqtype==0?BASEs:(com.seqtype==2?AAs:BINs));
\r
381 char *zz[NNODE],nodeb[NNODE],bestPath[NNODE-NS],Equivoc[NS-1];
\r
382 int n=com.ncode, nid=tree.nbranch-com.ns+1, it,i1,i2, i,j,k, h, hp,npath;
\r
383 int *Ftt=NULL, nchange, nchange0, visit[NS-1]={0};
\r
384 double sumpr, bestpr, pr, *pnode=NULL, *pnsite;
\r
387 fputs("\nList of most parsimonious reconstructions (MPRs) at each site: #MPRs (#changes)\n",fout);
\r
388 fputs("and then the most likely reconstruction out of the MPRs and its probability\n",fout);
\r
389 if((pnsite=(double*)malloc((com.ns-1)*n*sizeof(double)))==NULL)
\r
390 error2("PathwayMP1: oom");
\r
392 PATHWay=(char*)malloc(nid*(n+3)*sizeof(char));
\r
393 NCharaCur=PATHWay+nid; ICharaCur=NCharaCur+nid; CharaCur=ICharaCur+nid;
\r
395 zero(Ft,n*n*(tree.nbranch+1));
\r
396 if((Ftt=(int*)malloc(n*n*tree.nbranch*sizeof(int)))==NULL) error2("oom");
\r
399 pnode=(double*)malloc((nid*com.npatt+1)*(sizeof(double)+sizeof(char)));
\r
400 FOR (j,nid) zz[com.ns+j]=(char*)(pnode+nid*com.npatt)+j*com.npatt;
\r
401 FOR (j,com.ns) zz[j]=com.z[j];
\r
402 if (pnode==NULL) error2 ("oom");
\r
404 for (j=0,visit[i=0]=tree.root-com.ns; j<tree.nbranch; j++)
\r
405 if (tree.branches[j][1]>=com.ns)
\r
406 visit[++i]=tree.branches[j][1]-com.ns;
\r
408 for (h=0; h<com.ls; h++) {
\r
411 fprintf (fout, "\n%4d ", h+1);
\r
412 FOR (j, com.ns) fprintf (fout, "%c", pch[com.z[j][hp]]);
\r
413 fprintf (fout, ": ");
\r
414 FOR (j,nid*n) pnsite[j]=0;
\r
416 FOR (j,com.ns) nodeb[j]=com.z[j][hp];
\r
417 if (job==0) FOR (j,n*n*tree.nbranch) Ftt[j]=0;
\r
419 InteriorStatesMP (1, hp, &nchange, NCharaCur, CharaCur, space);
\r
420 ICharaCur[j=tree.root-com.ns]=0; PATHWay[j]=CharaCur[j*n+0];
\r
421 FOR (j,nid) Equivoc[j]=(NCharaCur[j]>1);
\r
423 if (nchange>*maxchange) *maxchange=nchange;
\r
424 if (nchange>NCATCHANGE-1) error2 ("raise NCATCHANGE");
\r
426 NSiteChange[nchange]++;
\r
427 /* NSiteChange[nchange]+=(int)com.fpatt[hp]; */
\r
429 DownStates (tree.root);
\r
430 for (npath=0,sumpr=bestpr=0; ;) {
\r
431 for (j=0,k=visit[nid-1]; j<NCharaCur[k]; j++) {
\r
432 PATHWay[k]=CharaCur[k*n+j]; npath++;
\r
433 FOR (i,nid) nodeb[i+com.ns]=PATHWay[i];
\r
435 FOR (i,nid) fprintf(fout,"%c",pch[PATHWay[i]]); fputc(' ',fout);
\r
436 pr=com.pi[(int)nodeb[tree.root]];
\r
437 for (i=0; i<tree.nbranch; i++) {
\r
438 i1=nodeb[tree.branches[i][0]];
\r
439 i2=nodeb[tree.branches[i][1]];
\r
440 pr*=Ft[i*n*n+i1*n+i2];
\r
443 FOR (i,nid) pnsite[i*n+nodeb[i+com.ns]]+=pr;
\r
445 { bestpr=pr; FOR(i,nid) bestPath[i]=PATHWay[i];}
\r
448 for (i=0,nchange0=0; i<tree.nbranch; i++) {
\r
449 i1=nodeb[tree.branches[i][0]];
\r
450 i2=nodeb[tree.branches[i][1]];
\r
451 if(i1!=i2) nchange0++;
\r
452 Ftt[i*n*n+i1*n+i2]++;
\r
454 if (nchange0!=nchange) {
\r
455 printf("\a\nerr:PathwayMP %d != %d", nchange, nchange0);
\r
456 fprintf(fout,".%d. ", nchange0); /* ??? */
\r
460 for (j=nid-2; j>=0; j--) {
\r
461 if(Equivoc[k=visit[j]] == 0) continue;
\r
462 if (ICharaCur[k]+1<NCharaCur[k]) {
\r
463 PATHWay[k] = CharaCur[k*n + (++ICharaCur[k])];
\r
464 DownStates (k+com.ns);
\r
467 else { /* if (next equivocal node is not ancestor) update node k */
\r
468 for (i=j-1; i>=0; i--) if (Equivoc[(int)visit[i]]) break;
\r
470 for (it=k+com.ns,i=visit[i]+com.ns; ; it=nodes[it].father)
\r
471 if (it==tree.root || nodes[it].father==i) break;
\r
473 DownStatesOneNode (k+com.ns, nodes[k+com.ns].father);
\r
478 } /* for (npath) */
\r
480 printf ("\rsite pattern %4d/%4d: %6d%6d", hp+1,com.npatt,npath,nchange);
\r
483 FOR (j,n*n*tree.nbranch) Ft[j]+=(double)Ftt[j]/npath*com.fpatt[hp];
\r
485 FOR (i,nid) zz[com.ns+i][hp]=bestPath[i];
\r
486 FOR (i,nid) pnode[i*com.npatt+hp]=pnsite[i*n+bestPath[i]]/sumpr;
\r
487 fprintf (fout, " |%4d (%d) | ", npath, nchange);
\r
489 FOR (i,nid) fprintf (fout, "%c", pch[bestPath[i]]);
\r
490 fprintf (fout, " (%.3f)", bestpr/sumpr);
\r
498 FOR (i,tree.nbranch) FOR (j,n*n) Ft[tree.nbranch*n*n+j]+=Ft[i*n*n+j];
\r
501 fprintf (fout,"\n\nApprox. relative accuracy at each node, by site\n");
\r
504 fprintf (fout,"\n%4d ", h+1);
\r
505 FOR (j, com.ns) fprintf (fout, "%c", pch[com.z[j][hp]]);
\r
506 fprintf (fout, ": ");
\r
507 FOR (i,nid) if (pnode[i*com.npatt+hp]<.99999) break;
\r
508 if (i<nid) FOR (j, nid)
\r
509 fprintf(fout,"%c (%5.3f) ", pch[zz[j][hp]],pnode[j*com.npatt+hp]);
\r
511 /* Site2Pattern (fout); */
\r
512 fprintf (fout,"\n\nlist of extant and reconstructed sequences\n\n");
\r
513 for(j=0;j<tree.nnode;j++,FPN(fout)) {
\r
514 if(j<com.ns) fprintf(fout,"%-20s", com.spname[j]);
\r
515 else fprintf(fout,"node #%-14d", j+1);
\r
516 print1seq (fout, zz[j], (com.readpattern?com.npatt:com.ls), com.pose);
\r
524 double DistanceREV (double Ft[], int n,double alpha,double Root[],double U[],
\r
525 double V[], double pi[], double space[], int *cond)
\r
527 /* input: Ft, n, alpha
\r
528 output: Q(in Ft), t, Root, U, V, and cond
\r
531 int i,j, InApplicable;
\r
532 double *Q=Ft, *T1=space, *T2=space+n*n, t, pi_sqrt[20], small=0.1/com.ls;
\r
534 for (i=0,t=0; i<n; i++) FOR (j,n) if (i-j) t+=Q[i*n+j];
\r
535 if (t<small) { *cond=1; zero(Q,n*n); return (0); }
\r
537 for(i=0;i<n;i++) for (j=0;j<i;j++)
\r
538 Q[i*n+j]=Q[j*n+i]=(Q[i*n+j]+Q[j*n+i])/2;
\r
540 abyx(1./sum(Q,n*n), Q, n*n);
\r
542 pi[i]=sum(Q+i*n, n);
\r
544 abyx(1/pi[i], Q+i*n, n);
\r
547 eigenQREV(Q, pi, n, Root, U, V, pi_sqrt);
\r
548 for(i=0,InApplicable=0; i<n; i++) {
\r
551 Root[i]=-300; /* adhockery */
\r
554 Root[i]=(alpha<=0?log(Root[i]):gammap(Root[i],alpha));
\r
556 FOR (i,n) FOR (j,n) T1[i*n+j]=U[i*n+j]*Root[j];
\r
557 matby (T1, V, Q, n, n, n);
\r
558 for (i=0,t=0; i<n; i++) t-=pi[i]*Q[i*n+i];
\r
560 if(noisy>=9 && InApplicable) printf("Root(P)<0. adhockery invoked\n");
\r
561 if(t<=0) error2("err: DistanceREV");
\r
563 FOR (i,n) Root[i]/=t;
\r
564 FOR (i, n) FOR (j,n) { Q[i*n+j]/=t; if (i-j) Q[i*n+j]=max2(0,Q[i*n+j]); }
\r
570 int PatternLS (FILE *fout, double Ft[], double alpha,double space[],int *cond)
\r
574 int n=com.ncode, i,j,k,h, it;
\r
575 double *Q=Ft,*Qt=Q+n*n,*Qm=Qt+n*n;
\r
576 double *pi,*Root,*U, *V, *T1=space, *branch, t;
\r
577 FILE *fdist=gfopen("Distance", "w");
\r
579 if((pi=(double*)malloc((n*n*3+tree.nbranch)*sizeof(double)))==NULL)
\r
580 error2("PatternLS: oom");
\r
581 Root=pi+n; U=Root+n; V=U+n*n; branch=V+n*n;
\r
584 for (i=0,zero(Qt,n*n),zero(Qm,n*n); i<com.ns; i++) {
\r
585 for (j=0; j<i; j++) {
\r
586 for (h=0,zero(Q,n*n); h<com.npatt; h++) {
\r
587 Q[(com.z[i][h])*n+com.z[j][h]] += com.fpatt[h]/2;
\r
588 Q[(com.z[j][h])*n+com.z[i][h]] += com.fpatt[h]/2;
\r
590 FOR (k,n*n) Qt[k]+=Q[k]/(com.ns*(com.ns-1)/2);
\r
592 SeqDistance[it]=DistanceREV (Q, n, alpha, Root,U,V, pi, space, &k);
\r
595 *cond=-1; printf("\n%d&%d: F(t) modified in DistanceREV",i+1,j+1);
\r
598 fprintf(fdist,"%9.5f",SeqDistance[it]);
\r
601 if (Q[k*n+k]>0) { printf ("%d %d %.5f\n", i+1, j+1, Q[k*n+k]); }
\r
603 FOR (k,n*n) Qm[k]+=Q[k]/(com.ns*(com.ns-1)/2);
\r
608 DistanceREV (Qt, n, alpha, Root, U, V, pi, space, &k);
\r
609 if (k==-1) { puts ("F(t) modified in DistanceREV"); }
\r
611 fprintf (fout, "\n\nQ: from average F over pairwise comparisons");
\r
612 OutQ(fout, n, Qt, pi, Root, U, V, T1);
\r
613 fprintf (fout, "\n\nQ: average of Qs over pairwise comparisons\n");
\r
614 fprintf (fout, "(disregard this if very different from the previous Q)");
\r
615 OutQ (fout, n, Qm, pi, Root, U, V, T1);
\r
617 if (tree.nbranch) {
\r
618 fillxc (branch, 0.1, tree.nbranch);
\r
619 LSDistance (&t, branch, testx);
\r
620 OutTreeB (fout); FPN (fout);
\r
621 FOR (i,tree.nbranch) fprintf(fout,"%9.5f", branch[i]);
\r
622 PMatBranch (Ft, com.ncode, branch, Root, U, V, space);
\r
628 int testx (double x[], int np)
\r
631 double tb[]={1e-5, 99};
\r
632 FOR(i,np) if(x[i]<tb[0] ||x[i]>tb[1]) return(-1);
\r
636 int SetBranch (double x[])
\r
642 if (i!=tree.root && (nodes[i].branch=x[nodes[i].ibranch])<-small)
\r