⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cprtree.pas

📁 生物信息学中的遗传数据分析的delphi源码。
💻 PAS
字号:
{*********************************************}
{                                             }
{    COMPONENT for MS DOS and MS WINDOWS      }
{                                             }
{    Source code for Turbo Pascal 6.0 and     }
{    Turbo Pasacal for Windows 1.0 compilers. }
{                                             }
{    (c) 1991, Roderic D. M. Page             }
{                                             }
{*********************************************}


{$I CPDIR.INC}

unit cprtree;

{
   Random tree generators

   1. Uniform unlabeled binary rooted trees
   2.    "        "       "    unrooted trees
   3. All rooted/unrooted, binary, labeled trees

  The methods for unlabeled trees makes extensive use of Furnas' (1984)
  paper. The routines here and in CPTREE.PAS are his, and also allow
  for unique labelling of both rooted and unrooted tree topologies
  using the RRANK and CRANK functions in CPTREE.

  26 Nov 1991 Sketched out.

*}

interface

uses
   cpheader, { Resource ids }
   cpwcdial,
   cpwvars,
   cperror,
   cputil,   { utilities }
   cptree,   { tree }
   cpanc,
   cpbtree,
   cplabels,
   cpwntbuf;

const
   rt_Rooted      = $0001;
   rt_Labeled     = $0002;
   rt_Dendrogram  = $0004;
   rt_Exhaustive  = $0008;
   rt_Sample      = $0010;
   rt_Binary      = $0020;

   rt_HDU = rt_Labeled or rt_Binary;
   rt_HDR = rt_HDU or rt_Rooted;      { = HD }
   rt_HEU = rt_Binary;
   rt_HER = rt_HEU or rt_Rooted;      { = HE }
   rt_HM  = rt_HDR or rt_Dendrogram;  { = HM }

type
   ALLNTREES_PTR = ^ALLNTREES;
   { Pointer to [ALLNTREES] }
   ALLNTREES = object (ALLTREES)
   { Object to generate all rooted and unrooted, labelel n-trees }
      B : PTREE_BUFFEROBJ; {Pointer to tree buffer to store trees }
      constructor Init (ABuffer: PTREE_BUFFEROBJ;L:LABELOBJ_PTR;
                        leaves:integer);
         {Call [ALLTREES], set [B]
          to <\b ABuffer>, and Count (private) to 0.}
      procedure TreeOp;virtual;
         {Store current tree in buffer and update counter display}
      private
      Count:integer;
      end;



procedure UniformUnlabeledRooted (rank, leaves:integer; var T:TREEOBJ);
{Return in <\b T> the unlabeled rooted tree of size <\b leaves> with the
  <\b rank>th topology in the list of ordered topologies. } 

procedure UniformUnlabeledUnrooted (rank, leaves:integer; var T:TREEOBJ;
                                    var phin: longint);
{Return in <\b T> the unlabeled unrooted tree of size <\b leaves> with the
 <\b rank>th topology in the list of ordered unrooted topologies. Must pass
 the value of [phi](n) in <\b phin>} 

implementation

type
   func = function (i,z,Vab:real):real;

var
   ternod,
   intnod,
   root : integer;
   AF   : ANCFUNCOBJ;



{-----------------------------f1-------------------------------------------}

{ Furnas (1984:221) equation for i1 }
function f1 (i,z,Vab:real):real;far;
begin
   f1 := Sqr(i)*i - 3 * (z+1)*Sqr(i) + (3*sqr(z)+6*z+2)*i - 6*Vab;
end;

{-----------------------------f2-------------------------------------------}

{ Furnas (1984:221) equation for i2 }
function f2 (i,z,Vab:real):real;far;
begin
   f2 := Sqr(i)*i - 3*z*Sqr(i) + (3*sqr(z)-1)*i + 3*z*(z+1)- 6*(Vab+1);
end;

{-----------------------------RootOf---------------------------------------}

{ Find the root of function Operation. Used to solve the cubic
  formulas f1 and f2 above (see Furnas, 1984:221).

  Code taken from T. Rugg & P. Feldman. 1986.
  "Turbo Pascal program library," Que, Indianapolis.
}
procedure RootOf (Operation: Func; LowX, HighX, z, Vab:real;
                  var Result:real; var OK:Boolean);
const
   MaxNumSegs = 500;
   MaxError   = 1.0E-06;
var
   X, Xlo, Xhi, Flo, Fhi, Width, Test : real;
   j, numsegs : integer;

   procedure Iterate;
   begin
      repeat
         X := (FHi * XLo - Flo * XHi) / (Fhi-Flo);
         Test := Operation (X, z,vab);
         if (abs (Test) < MaxError) then begin
            Result := X;
            OK     := true;
            end
         else
            if (Test * flo) > 0.0 then begin
               xlo := x;
               flo := test;
               end
            else begin
               xhi := x;
               fhi := test;
               end
      until OK;
   end;

begin
   OK := False;
   xlo := LowX;
   xhi := HighX;
   flo := Operation (xlo, z, vab);
   fhi := Operation (xhi, z, vab);
   if (abs(flo) < MaxError) then begin
      OK := true;
      Result := xlo;
      exit;
      end;
   if (abs(fhi) < MaxError) then begin
      OK := true;
      Result := xhi;
      exit;
      end;
   if (flo*fhi) < 0.0 then begin
      iterate;
      exit;
      end;
   NumSegs := 2;
   repeat
      width := (xhi-xlo)/NumSegs;
      for j := 1 to (NumSegs div 2) do begin
         x := xlo + width * (2 * j - 1);
         fhi := Operation (x, z, vab);
         if (fhi*flo) < 0.0 then begin
            xhi := x;
            iterate;
            exit;
            end;
         end;
      numsegs := numsegs * 2;
   until (Numsegs > maxNumSegs);
end;

{-----------------------------iW1------------------------------------------}

{ Furnas' (1984:214, eqn 9) formula for solving W(x,i,j) for i }
function iW1 (x,w:longint):longint;
begin
   iW1 := max (Trunc ((2*x-1-Sqrt(Sqr(2*x-1) - 8*(w-x+1)))/2),
               Trunc ((2*x+1-Sqrt(Sqr(2*x+1) - 8*w))/2));
end;

{-----------------------------iW2------------------------------------------}

{ Furnas' (1984:214, eqn 10) formula for solving W(x,i,j) for j }
function iW2 (x,w,w1:longint):longint;
begin
   iW2 := w - d(x) + d(x-W1) + W1;
end;

{-----------------------------invrank--------------------------------------}

{ Furnas' (1984:215,231) recursive procedure to generate
  a tree with the LLR toplogy given by rank.

  The first call requires that
     ternod=0;
     root=intnod=n+1;
     AF.Init;

  The result is an ancestor function AF containing a
  tree with the desired topology. The leaves are always
  in 1,..,n order, so a random tree will require relabeling
  of the leaves.
}

procedure invrank (rank:longint; n:integer; node:integer);
var
   a,               { size of left and right subtrees }
   b     : integer;
   bl,              { no. of trees preceding left and right subtrees }
   br: longint;
   x,
   p,
   V     : longint; { local variables }
   lnode,           { indices of left and right subtrees }
   rnode : integer;

begin
   if (n > 1) then begin
      { Find size of left and right subtrees }
      a := 0;
      p := 0;
      repeat
         Inc (a);
         p := p + Z[a]*Z[n-a];
      until (p >= rank);
      p := p - Z[a]*Z[n-a];
      b := n - a;

      { compute relative ranking of subtrees }
      V := rank - p - 1;
      if (a = b) then begin
         x  := Z[n div 2];
         bl := iW1 (x,V);
         br := iW2 (x,V,bl);
         end
      else begin
         bl := V div Z[b];
         br := V mod Z[b];
         end;

      { create subtrees }
      { make left desc }
      if (a > 1) then begin
         { internal }
         Inc (intnod);
         lnode := intnod;
         end
      else begin
         { terminal }
         Inc (ternod);
         lnode := ternod;
         end;

      { place in ancestor function }
      AF.A[lnode+2] := node;

      { generate left subtree }
      invrank (bl+1, a, lnode);

      { make right desc }
      if (b > 1) then begin
         { internal }
         Inc (intnod);
         rnode := intnod;
         end
      else begin
         { terminal }
         Inc (ternod);
         rnode := ternod;
         end;

      { place in ancestor function }
      AF.A[rnode+2] := node;

      { generate right subtree }
      invrank (br+1, b, rnode);
      end;
end; {invrank}

{-----------------------------UniformUnlabeledRooted-----------------------}

{ Return in T an "unlabeled" tree with the rankth topology for
  rooted binary trees with a given number of leaves.

  Although unlabeled, the leaves are ordered left to right
  <1,..,leaves>. Rank is in the range 1..Z[leaves].
}
procedure UniformUnlabeledRooted (rank, leaves:integer; var T:TREEOBJ);
begin
   ternod := 0;
   intnod := leaves + 1;
   root   := intnod;
   AF.Init;
   AF.A[1] := leaves;
   AF.A[2] := Pred(Leaves);
   invrank (rank, leaves, root);
   AF.AncFuncToTree (T);
end;


{-----------------------------UniformUnlabeledUnrooted---------------------}

{ Return in T an "unlabeled" tree with the rankth topology for
  unrooted binary trees with a given number of leaves.

  Although unlabeled, the leaves are ordered left to right
  <1,..,leaves>. Rank is in the range 1..Z[leaves].

  Routine requires that the number of unrooted triple trunk
  tree topologies be already calculated (phin). This is
  done by calling phi(leaves) before any calls to this
  proc. (This is simply to avoid repetetive calls to phi(leaves).
}

procedure UniformUnlabeledUnrooted (rank, leaves:integer; var T:TREEOBJ;
                                    var phin: longint);
var
   a,           { sizes of subtrees }
   b,
   c : integer;
   bl,
   bm,
   br : longint; { no. of trees before @subtree in LLR order }
   Vab,
   w,
   x1 : longint;
   i1,
   i2 : real;
   OK :Boolean;
begin
   if (rank <= phin) then begin
      { triple trunk tree }
      { i. get subtree sizes }
      a  := 0;
      x1 := 0;
      while (x1 < rank) do begin
         Inc (a);
         x1 := U(leaves,a,a);
         end;
      a := a - 1;

      b  := 0;
      x1 := 0;
      while (x1 < rank) do begin
         Inc (b);
         x1 := U(leaves,a,b);
         end;
      b := b - 1;
      c := leaves - a - b;

      { ii. ranks of subtrees }
      Vab := rank - U(leaves,a,b) - 1;
      if (a<b) then begin
         if (b<c) then begin                         { a<b<c}
            bl := Trunc (Vab/(Z[b]*Z[c]));
            bm := Trunc ((Vab-bl*Z[b]*Z[c])/Z[c]);
            br := Vab mod Z[c];
            end
         else begin                                  {a<b=c}
            bl := Trunc (Vab/d(Z[b]));
            w  := Vab-bl*d(Z[b]);
            bm := iW1 (Z[b],w);
            br := iW2 (Z[b], w, bm);
            end;
         end
      else begin
         if (b<c) then begin                         { a=b<c}
            w  := Trunc (Vab/Z[c]);
            bl := iW1 (Z[a], w);
            bm := iW2 (Z[a], w, bl);
            br := Vab mod Z[c];
            end
         else begin                                  {a=b=c}
            Rootof (f1, 0 ,leaves div 2, Z[a], Vab, i1, OK);
            RootOf (f2, 0 ,leaves div 2, Z[a], Vab, i2, OK);
            bl := max (Trunc(i1),Trunc(i2));
            w  := Vab-d3(Z[a])+d3(Z[a]-bl);
            bm := bl + iW1(Z[a]-bl,w);
            br := bl + iW2(Z[a]-bl,w,bm-bl);
            end;
         end;
      end
   else begin
      { double trunk tree }
      { i. get subtree sizes }
      a := leaves div 2;
      c := leaves - a;

      { ii. ranks of subtrees }
      w := rank - phin - 1;
      bl := iW1 (Z[a], w);
      br := iW2 (Z[a], w, bl);
      bm := -1;
      end;

   { build tree }

   ternod  := 0;
   intnod  := leaves + 1;
   root    := intnod;
   AF.Init;
   AF.A[1] := leaves;

   { left subtree }
   if (a = 1) then begin
      { leaf }
      Inc (ternod);
      AF.A[ternod + 2] := root;
      end
   else begin
      { internal }
      Inc (intnod);
      AF.A[intnod + 2] := root;
      invrank (bl + 1, a, intnod);
      end;
   if (bm > -1) then begin
      { middle subtree }
      if (b=1) then begin
         { leaf }
         Inc (ternod);
         AF.A[ternod + 2] := root;
         end
      else begin
         { internal }
         Inc(intnod);
         AF.A[intnod + 2] := root;
         invrank (bm + 1, b, intnod);
         end;
      AF.A[2] := leaves-2; { triple trunk tree }
      end
   else
      AF.A[2] := leaves-1; { double trunk tree }

   { right subtree }
   if (c=1) then begin
      { leaf }
      Inc (ternod);
      AF.A[ternod + 2] := root;
      end
   else begin
      { internal }
      Inc (intnod);
      AF.A[intnod + 2] := root;
      invrank (br + 1, c, intnod);
      end;

  AF.AncFuncToTree (T);
  if (bm > -1) then
     T.MakeRootBinary;
end;



   constructor ALLNTREES.Init(ABuffer : PTREE_BUFFEROBJ;
                              L:LABELOBJ_PTR;leaves:integer);
   begin
      B := ABuffer;
      ALLTREES.Init (leaves, L);
      Count := 0;
   end;

   procedure ALLNTREES.TreeOp;
   begin
      Inc (Count);
      { Store T in P's buffer }
      B^.PutTree (T);
      Error := B^.BufferError;

      {$IFDEF WINDOWS}
      if (Error=erOK) and (Counter <> NIL) then begin
         Counter^.UpDateMeter (id_Meter, Count);
         Counter^.UpDateNumber (id_TreesRead, Count);
         if bUserAbort then
            Error := erUserAbort;
         end;
      {$ENDIF}
   end;




end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -