+++ /dev/null
-#include "muscle.h"\r
-#include "clust.h"\r
-#include "clustset.h"\r
-#include <stdio.h>\r
-\r
-#define TRACE 0\r
-\r
-Clust::Clust()\r
- {\r
- m_Nodes = 0;\r
- m_uNodeCount = 0;\r
- m_uLeafCount = 0;\r
- m_uClusterCount = 0;\r
- m_JoinStyle = JOIN_Undefined;\r
- m_dDist = 0;\r
- m_uLeafCount = 0;\r
- m_ptrSet = 0;\r
- }\r
-\r
-Clust::~Clust()\r
- {\r
- delete[] m_Nodes;\r
- delete[] m_dDist;\r
- delete[] m_ClusterIndexToNodeIndex;\r
- }\r
-\r
-void Clust::Create(ClustSet &Set, CLUSTER Method)\r
- {\r
- m_ptrSet = &Set;\r
-\r
- SetLeafCount(Set.GetLeafCount());\r
-\r
- switch (Method)\r
- {\r
- case CLUSTER_UPGMA:\r
- m_JoinStyle = JOIN_NearestNeighbor;\r
- m_CentroidStyle = LINKAGE_Avg;\r
- break;\r
-\r
- case CLUSTER_UPGMAMax:\r
- m_JoinStyle = JOIN_NearestNeighbor;\r
- m_CentroidStyle = LINKAGE_Max;\r
- break;\r
-\r
- case CLUSTER_UPGMAMin:\r
- m_JoinStyle = JOIN_NearestNeighbor;\r
- m_CentroidStyle = LINKAGE_Min;\r
- break;\r
-\r
- case CLUSTER_UPGMB:\r
- m_JoinStyle = JOIN_NearestNeighbor;\r
- m_CentroidStyle = LINKAGE_Biased;\r
- break;\r
-\r
- case CLUSTER_NeighborJoining:\r
- m_JoinStyle = JOIN_NeighborJoining;\r
- m_CentroidStyle = LINKAGE_NeighborJoining;\r
- break;\r
-\r
- default:\r
- Quit("Clust::Create, invalid method %d", Method);\r
- }\r
-\r
- if (m_uLeafCount <= 1)\r
- Quit("Clust::Create: no leaves");\r
-\r
- m_uNodeCount = 2*m_uLeafCount - 1;\r
- m_Nodes = new ClustNode[m_uNodeCount];\r
- m_ClusterIndexToNodeIndex = new unsigned[m_uLeafCount];\r
-\r
- m_ptrClusterList = 0;\r
- for (unsigned uNodeIndex = 0; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
- {\r
- ClustNode &Node = m_Nodes[uNodeIndex];\r
- Node.m_uIndex = uNodeIndex;\r
- if (uNodeIndex < m_uLeafCount)\r
- {\r
- Node.m_uSize = 1;\r
- Node.m_uLeafIndexes = new unsigned[1];\r
- Node.m_uLeafIndexes[0] = uNodeIndex;\r
- AddToClusterList(uNodeIndex);\r
- }\r
- else\r
- Node.m_uSize = 0;\r
- }\r
-\r
-// Compute initial distance matrix between leaves\r
- SetProgressDesc("Build dist matrix");\r
- unsigned uPairIndex = 0;\r
- const unsigned uPairCount = (m_uLeafCount*(m_uLeafCount - 1))/2;\r
- for (unsigned i = 0; i < m_uLeafCount; ++i)\r
- for (unsigned j = 0; j < i; ++j)\r
- {\r
- const float dDist = (float) m_ptrSet->ComputeDist(*this, i, j);\r
- SetDist(i, j, dDist);\r
- if (0 == uPairIndex%10000)\r
- Progress(uPairIndex, uPairCount);\r
- ++uPairIndex;\r
- }\r
- ProgressStepsDone();\r
-\r
-// Call CreateCluster once for each internal node in the tree\r
- SetProgressDesc("Build guide tree");\r
- m_uClusterCount = m_uLeafCount;\r
- const unsigned uInternalNodeCount = m_uNodeCount - m_uLeafCount;\r
- for (unsigned uNodeIndex = m_uLeafCount; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
- {\r
- unsigned i = uNodeIndex + 1 - m_uLeafCount;\r
- Progress(i, uInternalNodeCount);\r
- CreateCluster();\r
- }\r
- ProgressStepsDone();\r
- }\r
-\r
-void Clust::CreateCluster()\r
- {\r
- unsigned uLeftNodeIndex;\r
- unsigned uRightNodeIndex;\r
- float dLeftLength;\r
- float dRightLength;\r
- ChooseJoin(&uLeftNodeIndex, &uRightNodeIndex, &dLeftLength, &dRightLength);\r
-\r
- const unsigned uNewNodeIndex = m_uNodeCount - m_uClusterCount + 1;\r
-\r
- JoinNodes(uLeftNodeIndex, uRightNodeIndex, dLeftLength, dRightLength,\r
- uNewNodeIndex);\r
-\r
-#if TRACE\r
- Log("Merge New=%u L=%u R=%u Ld=%7.2g Rd=%7.2g\n",\r
- uNewNodeIndex, uLeftNodeIndex, uRightNodeIndex, dLeftLength, dRightLength);\r
-#endif\r
-\r
-// Compute distances to other clusters\r
- --m_uClusterCount;\r
- for (unsigned uNodeIndex = GetFirstCluster(); uNodeIndex != uInsane;\r
- uNodeIndex = GetNextCluster(uNodeIndex))\r
- {\r
- if (uNodeIndex == uLeftNodeIndex || uNodeIndex == uRightNodeIndex)\r
- continue;\r
-\r
- if (uNewNodeIndex == uNodeIndex)\r
- continue;\r
-\r
- const float dDist = ComputeDist(uNewNodeIndex, uNodeIndex);\r
- SetDist(uNewNodeIndex, uNodeIndex, dDist);\r
- }\r
-\r
- for (unsigned uNodeIndex = GetFirstCluster(); uNodeIndex != uInsane;\r
- uNodeIndex = GetNextCluster(uNodeIndex))\r
- {\r
- if (uNodeIndex == uLeftNodeIndex || uNodeIndex == uRightNodeIndex)\r
- continue;\r
-\r
- if (uNewNodeIndex == uNodeIndex)\r
- continue;\r
-\r
-#if REDLACK\r
- const float dMetric = ComputeMetric(uNewNodeIndex, uNodeIndex);\r
- InsertMetric(uNewNodeIndex, uNodeIndex, dMetric);\r
-#endif\r
- }\r
- }\r
-\r
-void Clust::ChooseJoin(unsigned *ptruLeftIndex, unsigned *ptruRightIndex,\r
- float *ptrdLeftLength, float *ptrdRightLength)\r
- {\r
- switch (m_JoinStyle)\r
- {\r
- case JOIN_NearestNeighbor:\r
- ChooseJoinNearestNeighbor(ptruLeftIndex, ptruRightIndex, ptrdLeftLength,\r
- ptrdRightLength);\r
- return;\r
- case JOIN_NeighborJoining:\r
- ChooseJoinNeighborJoining(ptruLeftIndex, ptruRightIndex, ptrdLeftLength,\r
- ptrdRightLength);\r
- return;\r
- }\r
- Quit("Clust::ChooseJoin, Invalid join style %u", m_JoinStyle);\r
- }\r
-\r
-void Clust::ChooseJoinNearestNeighbor(unsigned *ptruLeftIndex,\r
- unsigned *ptruRightIndex, float *ptrdLeftLength, float *ptrdRightLength)\r
- {\r
- const unsigned uClusterCount = GetClusterCount();\r
-\r
- unsigned uMinLeftNodeIndex;\r
- unsigned uMinRightNodeIndex;\r
- GetMinMetric(&uMinLeftNodeIndex, &uMinRightNodeIndex);\r
-\r
- float dMinDist = GetDist(uMinLeftNodeIndex, uMinRightNodeIndex);\r
-\r
- const float dLeftHeight = GetHeight(uMinLeftNodeIndex);\r
- const float dRightHeight = GetHeight(uMinRightNodeIndex);\r
-\r
- *ptruLeftIndex = uMinLeftNodeIndex;\r
- *ptruRightIndex = uMinRightNodeIndex;\r
- *ptrdLeftLength = dMinDist/2 - dLeftHeight;\r
- *ptrdRightLength = dMinDist/2 - dRightHeight;\r
- }\r
-\r
-void Clust::ChooseJoinNeighborJoining(unsigned *ptruLeftIndex,\r
- unsigned *ptruRightIndex, float *ptrdLeftLength, float *ptrdRightLength)\r
- {\r
- const unsigned uClusterCount = GetClusterCount();\r
-\r
- //unsigned uMinLeftNodeIndex = uInsane;\r
- //unsigned uMinRightNodeIndex = uInsane;\r
- //float dMinD = PLUS_INFINITY;\r
- //for (unsigned i = GetFirstCluster(); i != uInsane; i = GetNextCluster(i))\r
- // {\r
- // const float ri = Calc_r(i);\r
- // for (unsigned j = GetNextCluster(i); j != uInsane; j = GetNextCluster(j))\r
- // {\r
- // const float rj = Calc_r(j);\r
- // const float dij = GetDist(i, j);\r
- // const float Dij = dij - (ri + rj);\r
- // if (Dij < dMinD)\r
- // {\r
- // dMinD = Dij;\r
- // uMinLeftNodeIndex = i;\r
- // uMinRightNodeIndex = j;\r
- // }\r
- // }\r
- // }\r
-\r
- unsigned uMinLeftNodeIndex;\r
- unsigned uMinRightNodeIndex;\r
- GetMinMetric(&uMinLeftNodeIndex, &uMinRightNodeIndex);\r
-\r
- const float dDistLR = GetDist(uMinLeftNodeIndex, uMinRightNodeIndex);\r
- const float rL = Calc_r(uMinLeftNodeIndex);\r
- const float rR = Calc_r(uMinRightNodeIndex);\r
-\r
- const float dLeftLength = (dDistLR + rL - rR)/2;\r
- const float dRightLength = (dDistLR - rL + rR)/2;\r
-\r
- *ptruLeftIndex = uMinLeftNodeIndex;\r
- *ptruRightIndex = uMinRightNodeIndex;\r
- *ptrdLeftLength = dLeftLength;\r
- *ptrdRightLength = dRightLength;\r
- }\r
-\r
-void Clust::JoinNodes(unsigned uLeftIndex, unsigned uRightIndex, float dLeftLength,\r
- float dRightLength, unsigned uNodeIndex)\r
- {\r
- ClustNode &Parent = m_Nodes[uNodeIndex];\r
- ClustNode &Left = m_Nodes[uLeftIndex];\r
- ClustNode &Right = m_Nodes[uRightIndex];\r
-\r
- Left.m_dLength = dLeftLength;\r
- Right.m_dLength = dRightLength;\r
-\r
- Parent.m_ptrLeft = &Left;\r
- Parent.m_ptrRight = &Right;\r
-\r
- Left.m_ptrParent = &Parent;\r
- Right.m_ptrParent = &Parent;\r
-\r
- const unsigned uLeftSize = Left.m_uSize;\r
- const unsigned uRightSize = Right.m_uSize;\r
- const unsigned uParentSize = uLeftSize + uRightSize;\r
- Parent.m_uSize = uParentSize;\r
-\r
- assert(0 == Parent.m_uLeafIndexes);\r
- Parent.m_uLeafIndexes = new unsigned[uParentSize];\r
-\r
- const unsigned uLeftBytes = uLeftSize*sizeof(unsigned);\r
- const unsigned uRightBytes = uRightSize*sizeof(unsigned);\r
- memcpy(Parent.m_uLeafIndexes, Left.m_uLeafIndexes, uLeftBytes);\r
- memcpy(Parent.m_uLeafIndexes + uLeftSize, Right.m_uLeafIndexes, uRightBytes);\r
-\r
- DeleteFromClusterList(uLeftIndex);\r
- DeleteFromClusterList(uRightIndex);\r
- AddToClusterList(uNodeIndex);\r
- }\r
-\r
-float Clust::Calc_r(unsigned uNodeIndex) const\r
- {\r
- const unsigned uClusterCount = GetClusterCount();\r
- if (2 == uClusterCount)\r
- return 0;\r
-\r
- float dSum = 0;\r
- for (unsigned i = GetFirstCluster(); i != uInsane; i = GetNextCluster(i))\r
- {\r
- if (i == uNodeIndex)\r
- continue;\r
- dSum += GetDist(uNodeIndex, i);\r
- }\r
- return dSum/(uClusterCount - 2);\r
- }\r
-\r
-float Clust::ComputeDist(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- switch (m_CentroidStyle)\r
- {\r
- case LINKAGE_Avg:\r
- return ComputeDistAverageLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
- case LINKAGE_Min:\r
- return ComputeDistMinLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
- case LINKAGE_Max:\r
- return ComputeDistMaxLinkage(uNewNodeIndex, uNodeIndex);\r
-\r
- case LINKAGE_Biased:\r
- return ComputeDistMAFFT(uNewNodeIndex, uNodeIndex);\r
-\r
- case LINKAGE_NeighborJoining:\r
- return ComputeDistNeighborJoining(uNewNodeIndex, uNodeIndex);\r
- }\r
- Quit("Clust::ComputeDist, invalid centroid style %u", m_CentroidStyle);\r
- return (float) g_dNAN;\r
- }\r
-\r
-float Clust::ComputeDistMinLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
- const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
- const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
- const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
- return (dDistL < dDistR ? dDistL : dDistR);\r
- }\r
-\r
-float Clust::ComputeDistMaxLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
- const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
- const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
- const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
- return (dDistL > dDistR ? dDistL : dDistR);\r
- }\r
-\r
-float Clust::ComputeDistAverageLinkage(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
- const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
- const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
- const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
- return (dDistL + dDistR)/2;\r
- }\r
-\r
-float Clust::ComputeDistNeighborJoining(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
- const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
- const float dDistLR = GetDist(uLeftNodeIndex, uRightNodeIndex);\r
- const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
- const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
- const float dDist = (dDistL + dDistR - dDistLR)/2;\r
- return dDist;\r
- }\r
-\r
-// This is a mysterious variant of UPGMA reverse-engineered from MAFFT source.\r
-float Clust::ComputeDistMAFFT(unsigned uNewNodeIndex, unsigned uNodeIndex)\r
- {\r
- const unsigned uLeftNodeIndex = GetLeftIndex(uNewNodeIndex);\r
- const unsigned uRightNodeIndex = GetRightIndex(uNewNodeIndex);\r
-\r
- const float dDistLR = GetDist(uLeftNodeIndex, uRightNodeIndex);\r
- const float dDistL = GetDist(uLeftNodeIndex, uNodeIndex);\r
- const float dDistR = GetDist(uRightNodeIndex, uNodeIndex);\r
- const float dMinDistLR = (dDistL < dDistR ? dDistL : dDistR);\r
- const float dSumDistLR = dDistL + dDistR;\r
- const float dDist = dMinDistLR*(1 - g_dSUEFF) + dSumDistLR*g_dSUEFF/2;\r
- return dDist;\r
- }\r
-\r
-unsigned Clust::GetClusterCount() const\r
- {\r
- return m_uClusterCount;\r
- }\r
-\r
-void Clust::LogMe() const\r
- {\r
- Log("Clust %u leaves, %u nodes, %u clusters.\n",\r
- m_uLeafCount, m_uNodeCount, m_uClusterCount);\r
-\r
- Log("Distance matrix\n");\r
- const unsigned uNodeCount = GetNodeCount();\r
- Log(" ");\r
- for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
- Log(" %7u", i);\r
- Log("\n");\r
-\r
- Log(" ");\r
- for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
- Log(" ------");\r
- Log("\n");\r
-\r
- for (unsigned i = 0; i < uNodeCount - 1; ++i)\r
- {\r
- Log("%4u: ", i);\r
- for (unsigned j = 0; j < i; ++j)\r
- Log(" %7.2g", GetDist(i, j));\r
- Log("\n");\r
- }\r
-\r
- Log("\n");\r
- Log("Node Size Prnt Left Rght Length Name\n");\r
- Log("---- ---- ---- ---- ---- ------ ----\n");\r
- for (unsigned uNodeIndex = 0; uNodeIndex < m_uNodeCount; ++uNodeIndex)\r
- {\r
- const ClustNode &Node = m_Nodes[uNodeIndex];\r
- Log("%4u %4u", uNodeIndex, Node.m_uSize);\r
- if (0 != Node.m_ptrParent)\r
- Log(" %4u", Node.m_ptrParent->m_uIndex);\r
- else\r
- Log(" ");\r
-\r
- if (0 != Node.m_ptrLeft)\r
- Log(" %4u", Node.m_ptrLeft->m_uIndex);\r
- else\r
- Log(" ");\r
-\r
- if (0 != Node.m_ptrRight)\r
- Log(" %4u", Node.m_ptrRight->m_uIndex);\r
- else\r
- Log(" ");\r
-\r
- if (uNodeIndex != m_uNodeCount - 1)\r
- Log(" %7.3g", Node.m_dLength);\r
- if (IsLeaf(uNodeIndex))\r
- {\r
- const char *ptrName = GetNodeName(uNodeIndex);\r
- if (0 != ptrName)\r
- Log(" %s", ptrName);\r
- }\r
- if (GetRootNodeIndex() == uNodeIndex)\r
- Log(" [ROOT]");\r
- Log("\n");\r
- }\r
- }\r
-\r
-const ClustNode &Clust::GetNode(unsigned uNodeIndex) const\r
- {\r
- if (uNodeIndex >= m_uNodeCount)\r
- Quit("ClustNode::GetNode(%u) %u", uNodeIndex, m_uNodeCount);\r
- return m_Nodes[uNodeIndex];\r
- }\r
-\r
-bool Clust::IsLeaf(unsigned uNodeIndex) const\r
- {\r
- return uNodeIndex < m_uLeafCount;\r
- }\r
-\r
-unsigned Clust::GetClusterSize(unsigned uNodeIndex) const\r
- {\r
- const ClustNode &Node = GetNode(uNodeIndex);\r
- return Node.m_uSize;\r
- }\r
-\r
-unsigned Clust::GetLeftIndex(unsigned uNodeIndex) const\r
- {\r
- const ClustNode &Node = GetNode(uNodeIndex);\r
- if (0 == Node.m_ptrLeft)\r
- Quit("Clust::GetLeftIndex: leaf");\r
- return Node.m_ptrLeft->m_uIndex;\r
- }\r
-\r
-unsigned Clust::GetRightIndex(unsigned uNodeIndex) const\r
- {\r
- const ClustNode &Node = GetNode(uNodeIndex);\r
- if (0 == Node.m_ptrRight)\r
- Quit("Clust::GetRightIndex: leaf");\r
- return Node.m_ptrRight->m_uIndex;\r
- }\r
-\r
-float Clust::GetLength(unsigned uNodeIndex) const\r
- {\r
- const ClustNode &Node = GetNode(uNodeIndex);\r
- return Node.m_dLength;\r
- }\r
-\r
-void Clust::SetLeafCount(unsigned uLeafCount)\r
- {\r
- if (uLeafCount <= 1)\r
- Quit("Clust::SetLeafCount(%u)", uLeafCount);\r
-\r
- m_uLeafCount = uLeafCount;\r
- const unsigned uNodeCount = GetNodeCount();\r
-\r
-// Triangular matrix size excluding diagonal (all zeros in our case).\r
- m_uTriangularMatrixSize = (uNodeCount*(uNodeCount - 1))/2;\r
- m_dDist = new float[m_uTriangularMatrixSize];\r
- }\r
-\r
-unsigned Clust::GetLeafCount() const\r
- {\r
- return m_uLeafCount;\r
- }\r
-\r
-unsigned Clust::VectorIndex(unsigned uIndex1, unsigned uIndex2) const\r
- {\r
- const unsigned uNodeCount = GetNodeCount();\r
- if (uIndex1 >= uNodeCount || uIndex2 >= uNodeCount)\r
- Quit("DistVectorIndex(%u,%u) %u", uIndex1, uIndex2, uNodeCount);\r
- unsigned v;\r
- if (uIndex1 >= uIndex2)\r
- v = uIndex2 + (uIndex1*(uIndex1 - 1))/2;\r
- else\r
- v = uIndex1 + (uIndex2*(uIndex2 - 1))/2;\r
- assert(v < m_uTriangularMatrixSize);\r
- return v;\r
- }\r
-\r
-float Clust::GetDist(unsigned uIndex1, unsigned uIndex2) const\r
- {\r
- unsigned v = VectorIndex(uIndex1, uIndex2);\r
- return m_dDist[v];\r
- }\r
-\r
-void Clust::SetDist(unsigned uIndex1, unsigned uIndex2, float dDist)\r
- {\r
- unsigned v = VectorIndex(uIndex1, uIndex2);\r
- m_dDist[v] = dDist;\r
- }\r
-\r
-float Clust::GetHeight(unsigned uNodeIndex) const\r
- {\r
- if (IsLeaf(uNodeIndex))\r
- return 0;\r
-\r
- const unsigned uLeftIndex = GetLeftIndex(uNodeIndex);\r
- const unsigned uRightIndex = GetRightIndex(uNodeIndex);\r
- const float dLeftLength = GetLength(uLeftIndex);\r
- const float dRightLength = GetLength(uRightIndex);\r
- const float dLeftHeight = dLeftLength + GetHeight(uLeftIndex);\r
- const float dRightHeight = dRightLength + GetHeight(uRightIndex);\r
- return (dLeftHeight + dRightHeight)/2;\r
- }\r
-\r
-const char *Clust::GetNodeName(unsigned uNodeIndex) const\r
- {\r
- if (!IsLeaf(uNodeIndex))\r
- Quit("Clust::GetNodeName, is not leaf");\r
- return m_ptrSet->GetLeafName(uNodeIndex);\r
- }\r
-\r
-unsigned Clust::GetNodeId(unsigned uNodeIndex) const\r
- {\r
- if (uNodeIndex >= GetLeafCount())\r
- return 0;\r
- return m_ptrSet->GetLeafId(uNodeIndex);\r
- }\r
-\r
-unsigned Clust::GetLeaf(unsigned uNodeIndex, unsigned uLeafIndex) const\r
- {\r
- const ClustNode &Node = GetNode(uNodeIndex);\r
- const unsigned uLeafCount = Node.m_uSize;\r
- if (uLeafIndex >= uLeafCount)\r
- Quit("Clust::GetLeaf, invalid index");\r
- const unsigned uIndex = Node.m_uLeafIndexes[uLeafIndex];\r
- if (uIndex >= m_uNodeCount)\r
- Quit("Clust::GetLeaf, index out of range");\r
- return uIndex;\r
- }\r
-\r
-unsigned Clust::GetFirstCluster() const\r
- {\r
- if (0 == m_ptrClusterList)\r
- return uInsane;\r
- return m_ptrClusterList->m_uIndex;\r
- }\r
-\r
-unsigned Clust::GetNextCluster(unsigned uIndex) const\r
- {\r
- ClustNode *ptrNode = &m_Nodes[uIndex];\r
- if (0 == ptrNode->m_ptrNextCluster)\r
- return uInsane;\r
- return ptrNode->m_ptrNextCluster->m_uIndex;\r
- }\r
-\r
-void Clust::DeleteFromClusterList(unsigned uNodeIndex)\r
- {\r
- assert(uNodeIndex < m_uNodeCount);\r
- ClustNode *ptrNode = &m_Nodes[uNodeIndex];\r
- ClustNode *ptrPrev = ptrNode->m_ptrPrevCluster;\r
- ClustNode *ptrNext = ptrNode->m_ptrNextCluster;\r
-\r
- if (0 != ptrNext)\r
- ptrNext->m_ptrPrevCluster = ptrPrev;\r
- if (0 == ptrPrev)\r
- {\r
- assert(m_ptrClusterList == ptrNode);\r
- m_ptrClusterList = ptrNext;\r
- }\r
- else\r
- ptrPrev->m_ptrNextCluster = ptrNext;\r
-\r
- ptrNode->m_ptrNextCluster = 0;\r
- ptrNode->m_ptrPrevCluster = 0;\r
- }\r
-\r
-void Clust::AddToClusterList(unsigned uNodeIndex)\r
- {\r
- assert(uNodeIndex < m_uNodeCount);\r
- ClustNode *ptrNode = &m_Nodes[uNodeIndex];\r
-\r
- if (0 != m_ptrClusterList)\r
- m_ptrClusterList->m_ptrPrevCluster = ptrNode;\r
-\r
- ptrNode->m_ptrNextCluster = m_ptrClusterList;\r
- ptrNode->m_ptrPrevCluster = 0;\r
-\r
- m_ptrClusterList = ptrNode;\r
- }\r
-\r
-float Clust::ComputeMetric(unsigned uIndex1, unsigned uIndex2) const\r
- {\r
- switch (m_JoinStyle)\r
- {\r
- case JOIN_NearestNeighbor:\r
- return ComputeMetricNearestNeighbor(uIndex1, uIndex2);\r
-\r
- case JOIN_NeighborJoining:\r
- return ComputeMetricNeighborJoining(uIndex1, uIndex2);\r
- }\r
- Quit("Clust::ComputeMetric");\r
- return 0;\r
- }\r
-\r
-float Clust::ComputeMetricNeighborJoining(unsigned i, unsigned j) const\r
- {\r
- float ri = Calc_r(i);\r
- float rj = Calc_r(j);\r
- float dij = GetDist(i, j);\r
- float dMetric = dij - (ri + rj);\r
- return (float) dMetric;\r
- }\r
-\r
-float Clust::ComputeMetricNearestNeighbor(unsigned i, unsigned j) const\r
- {\r
- return (float) GetDist(i, j);\r
- }\r
-\r
-float Clust::GetMinMetricBruteForce(unsigned *ptruIndex1, unsigned *ptruIndex2) const\r
- {\r
- unsigned uMinLeftNodeIndex = uInsane;\r
- unsigned uMinRightNodeIndex = uInsane;\r
- float dMinMetric = PLUS_INFINITY;\r
- for (unsigned uLeftNodeIndex = GetFirstCluster(); uLeftNodeIndex != uInsane;\r
- uLeftNodeIndex = GetNextCluster(uLeftNodeIndex))\r
- {\r
- for (unsigned uRightNodeIndex = GetNextCluster(uLeftNodeIndex);\r
- uRightNodeIndex != uInsane;\r
- uRightNodeIndex = GetNextCluster(uRightNodeIndex))\r
- {\r
- float dMetric = ComputeMetric(uLeftNodeIndex, uRightNodeIndex);\r
- if (dMetric < dMinMetric)\r
- {\r
- dMinMetric = dMetric;\r
- uMinLeftNodeIndex = uLeftNodeIndex;\r
- uMinRightNodeIndex = uRightNodeIndex;\r
- }\r
- }\r
- }\r
- *ptruIndex1 = uMinLeftNodeIndex;\r
- *ptruIndex2 = uMinRightNodeIndex;\r
- return dMinMetric;\r
- }\r
-\r
-float Clust::GetMinMetric(unsigned *ptruIndex1, unsigned *ptruIndex2) const\r
- {\r
- return GetMinMetricBruteForce(ptruIndex1, ptruIndex2);\r
- }\r