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

📄 cpnni.pas

📁 生物信息学中的遗传数据分析的delphi源码。
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      LeafCount := LeafCount + S1^.Treeleaves;

      {2:  Red subtree }
      new (S2, Init);
      S2^.Root := There^.Child^.Sib;
      S2^.Root^.anc := NIL;
      S2^.Root^.sib := NIL;
      S2^.SetLeaves (S2^.Root^.GetWeight);
      S2^.SetInternals(Pred (S2^.TreeLeaves));

      LeafCount := LeafCount + S2^.Treeleaves;

      { Ensure green subtree's root doesn't still
        have red subtree as a sibling }
      S1^.Root^.sib := NIL;

      AddExtraNodeGR (S1^);  { do this here }
      AddExtraNodeGR (S2^);


      { 3: Blue subtree }
      { Make There the extra node }
      with There^ do begin
         SetLeaf;
         SetNamePtr (ExtraNodeCount);
         Child := NIL;
         end;
      T.SetLeaves (T.TreeLeaves - LeafCount + 1);
      T.SetInternals (Pred (T.TreeLeaves));
      T.NL[ExtraNodeCount] := There;
      end;

   { Fix up sub trees

     The resulting subtree resembles a pruned tree in that
     the NL fields are indexed by the order of the values
     in the original tree, e.g.


     1  2  3  4  5  6  NL
     ---------------
     -  -  3  -  5  6  NamePtr
     -  -  3  -  1  2  LeafNum

     5   6   3
      \   \ /
       \   * [2,3]
        \ /
         * [1..3]

     Hence, clusters in tree reflect number of leaves in subtree,
     but NamePtr fields reflect original profile. This is essential
     to ensure that leaves are consistently labeled.
   }


   T.ReRoot (T.NL[ExtraNodeCount]);
   new (S0, Init);
   S0^.Root := T.CopyOfSubTree (T.Root);
   S0^.SetLeaves (T.TreeLeaves);
   S0^.SetINternals (T.TreeInternals);
   S0^.BuildLeafList;
   {$IFDEF NNIDEbug}
   writeln (output, 'Ordering S0');
   {$ENDIF}

   S0^.OrderLeaves;
   S0^.BuildClusters;
   S0^.CorrectWeights;

   S1^.BuildLeafList;
   {$IFDEF NNIDEbug}
   writeln (output, 'Ordering S1');
   {$ENDIF}

   S1^.OrderLeaves;
   S1^.BuildClusters;
   S1^.CorrectWeights;
   if not Edge then begin
      S2^.BuildLeafList;
      {$IFDEF NNIDEbug}
      writeln (output, 'Ordering S2');
      {$ENDIF}

      S2^.OrderLeaves;
      S2^.BuildClusters;
      S2^.CorrectWeights;
      end;

   { Store in data structure }
   S[0] := S0;
   S[1] := S1;
   if not Edge then
      S[2] := S2;
end;

{-----------------------------MarkASubTree---------------------------------}

{ For each leaf in T not of the desired Color,
  mark it and its first nonmarked ancestor.
  This is logically equivalent to pruning the
  tree of all leaves except those "of Color." }
procedure MarkASubTree (var T:TREEOBJ;Color:Byte);
var
   i, j: integer;
   q : NODE_PTR;
begin
   { Remember that the leaves of a tree need not be
     labeled 1..n because of pruning. }
   j := 0;
   i := 0;
   while (j < T.TreeLeaves) do begin
      repeat
         Inc (i);
      until (T.NL[i] <> NIL);
      if (T.NL[i]^.NodeIndex <> Color) then begin
         T.NL[i]^.Mark;
         q := T.NL[i]^.NodeAncestor;
         while q^.IsMarked do
            q := q^.NodeAncestor;
         q^.Mark;
         end;
      Inc (j);
      end;
end;

{-----------------------------GetSubTree-----------------------------------}

{ Given a start tree T return in SubT a subtree. Nodes belonging in
  the subtree are unmarked, all other nodes are marked. The subtree
  may be imbedded in T, e.g.:

  T =

  B   B   G   B   G   R G   R

      +---LimitSister
      |
  5   6   4   3   1   2 7   8
   \   \   .   \   . /   . /
    \   \   .   \   *     *
     \   \   .   \ .     .
      \   \   .   *     .
       \   \   .   .   .
        \   \   .   . .
         \   \   .   o
          \   \   . .
           \   \   o <-- (Limit)
            \   \ /
             \   *
              \ /
               *

  o = unmarked, . = imbedded subtree.

  The Green subtree returned is

  SubT =

  x   4   1   7
   .   \   \ /
    .   \   *
     .   \ /
      .   *
       . /
        *

  Algorithm operates by traversing T and using SubT's stack to
  keep track of nodes added to the subtree. The first node
  added may be just a place holder below SubT's root,
  and hence may be pruned off the subtree.


  The original T IS NOT altered or destroyed by this procedure,
  but all nodes are unmarked.

}
procedure GetSubTree (var T, SubT: TREEOBJ; Limit: NODE_PTR; Color: Byte);
var
   BlueOGPtr : NODE_PTR; { first node in blue subtree above Limit }
   GetBlueOG : Boolean;  { flag to trap BlueOGPtr }
   BlueSister: NODE_PTR;
   LimitSister : NODE_PTR;

   procedure Traverse (p:NODE_PTR);
   var
      q, r: NODE_PTR;
   begin
      if (p <> NIL) then begin
         if (p = Limit) then
            { We've passed Limit so prepare to trap the first
              node that is in a subtree...}
            GetBlueOG := True;
         if not p^.IsMarked then begin
            { p is part of subtree }
            q := SubT.ST.TopOfStack;
            if (q^.Child = NIL) then begin
               r := new (NODE_PTR, Init);
               q^.child := r;
               r^.anc := q;
               if (p^.IsLeaf) then begin
                  SubT.IncLeaves;
                  r^.SetLeaf;
                  r^.SetNamePtr (p^.NodeNamePtr);
                  SubT.NL[p^.NodeNamePtr] := r;
                  end
               else begin
                  r^.SetWeight (p^.GetWeight);
                  SubT.IncInternals;
                  SubT.ST.Push (r);
                  end;
               end
            else begin
               r := new (NODE_PTR, Init);
               q^.child^.sib := r;
               r^.anc := q;
               if (p^.IsLeaf) then begin
                  SubT.IncLeaves;
                  r^.SetLeaf;
                  r^.SetNamePtr (p^.NodeNamePtr);
                  SubT.NL[p^.NodeNamePtr] := r;
                  end
               else begin
                  r^.SetWeight (p^.GetWeight);
                  SubT.IncInternals;
                  SubT.ST.Push (r);
                  end;
               end;
            { ...if trap is set, capture the first node
              in the subtree that occurs above Limit and
              release the trap. }
            if GetBlueOG then begin
               BlueOGPtr := r;
               GetBlueOG := false;
               end;
            { trap the first blue node in SubT that corresponds to
              the sister of limit in T }
            if (Color = B) and (p = LimitSister) then
               BlueSister := r;
            end;

         Traverse (p^.child);
         if (not p^.IsLeaf) and (not p^.IsMarked) then
            SubT.ST.Pop;
         { Unmark as we go down tree }
         p^.UnMark;
         { Release trap so that any nodes
           BELOW limit aren't spuriously
           caught. }
         if (p = Limit) then
            GetBlueOG := false;
         Traverse (p^.sib);
         end;
   end;

begin
   BlueOGPtr  := NIL;
   GetBlueOG  := false;

   { Get the sister of limit on T }
   if Limit = Limit^.anc^.child then
      LimitSister := Limit^.sib
   else LimitSister := Limit^.anc^.child;

   SubT.Init;
   SubT.MakeRoot;
   SubT.IncInternals;
   SubT.ST.Push (SubT.Root);
   Traverse (T.Root);

   if (Color <> B) then begin
      { Add extra node }
      SubT.Root^.child^.sib := ExtraNode;
      SubT.Root^.child^.sib^.anc := SubT.Root;
      SubT.IncLeaves;
      SubT.NL[SubT.Root^.child^.sib^.NodeNamePtr] := SubT.Root^.child^.sib;
      end
   else begin
      { prune off subroot }
      SubT.Root := SubT.Root^.child;
      Dispose (SubT.Root^.anc, Done);
      SubT.Root^.anc := NIL;

      { Insert an extra node }
      if (BlueOGPtr <> NIL) then begin
         { >= 1 blue leaves occur above Limit, add the
           Extra node below the first one. }
         AddExtraNodeB (SubT, BlueOGPtr);
         end
      else begin
         { Blue leaves are all below Limit, so
           add extra node below Limit's sister
           node (which must be blue). }
         AddExtraNodeB (SubT, BlueSister);
         end;

      { Ensure consistent rooting by using extra }
      SubT.ReRoot (SubT.NL[ExtraNodeCount]);

      end;

   { Fix up sub tree

     The resulting subtree resembles a pruned tree in that
     the NL fields are indexed by the order of the values
     in the original tree, e.g.


     1  2  3  4  5  6  NL
     ---------------
     -  -  3  -  5  6  NamePtr
     -  -  3  -  1  2  LeafNum

     5   6   3
      \   \ /
       \   * [2,3]
        \ /
         * [1..3]

     Hence, clusters in tree reflect number of leaves in subtree,
     but NamePtr fields refelct original profile. This is essential
     to ensure that leaves are consistently labeled.
   }


{$IFDEF NNIDEbug}
   writeln (output, 'SubT.OrderLeaves');
{$ENDIF}

   SubT.OrderLeaves;      { Ensure LeafNum field allocated }
   SubT.BuildClusters;    { Ensure valid clusters }
   SubT.CorrectWeights;   { Ensure correct weights }
end;

{-----------------------------DRA------------------------------------------}

{ Recursively compute NNI between T1 and T2 }

procedure doDRA (var T1, T2: TREEOBJ);
var
   S1, S2: SUBTREES;
   i, c, k : integer;
   There, Limit : NODE_PTR;
   Edge : Boolean;
   m1, m2: Longint;
begin
   if (T1.TreeLeaves < 4) then
      Exit;

   { Color the goal tree }
   ColorTree (T2, There, Edge);
   if Edge then
      k := 1
   else k := 2;

   { Color the start tree }
   LabelT (T1, T2);

   { Return the NNI needed to transform start- into goal-tree }
   c := Count (T1, Limit);
   NNICount := NNICount + c;

   { Decompose trees... }
   { Goal tree }

   {$IFDEF NNIDEbug}
   writeln (output, 'Doing goal subtrees');
   {$ENDIF}

   DecompGoalTree (T2, S2, There, Edge);

   {$IFDEF NNIDEbug}
   writeln (output, 'Goal subtrees');
   S2[0]^.WriteTree (output);
   S2[1]^.WriteTree (output);
   if not Edge then
      S2[2]^.WriteTree (output);
   {$ENDIF}

   { Start tree }
   { blue }
   {$IFDEF NNIDebug}
   writeln (output, 'Blue');
   {$ENDIF}

   MarkASubTree (T1, 0);
   new (S1[0]);
   GetSubTree (T1, S1[0]^, Limit, 0);

   { green }
   {$IFDEF NNIDebug}
   writeln (output, 'Green');
   {$ENDIF}

   MarkASubTree (T1, 1);
   new (S1[1]);
   GetSubTree (T1, S1[1]^, Limit, 1);

   { red }
   if not Edge then begin
      {$IFDEF NNIDebug}
      writeln (output, 'Red');
      {$ENDIF}
      MarkASubTree (T1, 2);
      new (S1[2]);
      GetSubTree (T1, S1[2]^, Limit, 2);
      end;

   {$IFDEF NNIDebug}
   writeln (output, 'Start subtrees');
   S1[0]^.WriteTree (output);
   S1[1]^.WriteTree (output);
   if not Edge then
      S1[2]^.WriteTree (output);
   {$ENDIF}


   { recursive loop }
   Inc (ExtraNodeCount);
   Inc (LoopCount);
   for i := 0 to k do begin
      doDRA (S1[i]^, S2[i]^);

      { Free the start subtrees }
      Dispose (S1[i], Done);
      Dispose (S2[i], Done);
      end;
   Dec (ExtraNodeCount);
   Dec (LoopCount);
end;

{-----------------------------NNI------------------------------------------}

{ Return dra between T1 and T2, destroying T1 and T2
  in the process. }
function DRA (var T1, T2: TREEOBJ; rt:integer):integer;
var
   m1, m2: longint;
begin
   {$IFDEF NNIDEbug}
   writeln (output, '*****In NNI*****');
   {$ENDIF}


   NNICount  := 0;
   LoopCount := 0;

   { ExtraNodeCount must start at the first cell in
     both T1 and T2 NL array beyond the leaves in
     those trees. Need to take into account that
     (1) T1 and T2 may be pruned, and
     (2) if they're from different profiles then
         they may be unequally pruned.
   }
   ExtraNodeCount := Max (Succ(T1.TreeLeaves + T1.TreePrunedleaves),
                          Succ(T2.TreeLeaves + T2.TreePrunedleaves));

   { Root T1 and T2 with same leaf }
   T1.ReRoot (T1.Ithleaf (rt));
   T2.ReRoot (T2.IthLeaf (rt));

   { Compute }
   doDRA (t1, T2);

   { Dispose of the remains of T1 and T2 }
   T1.Done;
   T2.Done;

   { Return }
   DRA := NNICount;

   {$IFDEF NNIDEbug}
   writeln (output, '*****Out of NNI*****');
   {$ENDIF}

end;

begin
end.

⌨️ 快捷键说明

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