📄 connectivity.cpp
字号:
//提供二次开发人员进行连通性分析的接口功能
//2002.10.11---------------------------Start.
#include "stdafx.h"
#include "AVInfoAPI.h"
#include "AVInfoKernel.h"
#include <afxtempl.h>
#ifdef __cplusplus
extern "C"{
#endif
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////全局变量////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//连通性分析所需全局变量
typedef CArray<int,int&>CIntArray;
int **g_pMatrixNodeOrigin = NULL; //连通性分析原始节点矩阵
int **g_pMatrixNodePrev = NULL; //连通性分析结果节点矩阵(前一状态)
int **g_pMatrixNodeCurrent = NULL; //连通性分析结果节点矩阵(当前状态)
int **pMatrixLocal = NULL;//本来是临时变量,但因分配内存占用时间太长故声明成全局变量(wxg_03.12.9)
//源于拓扑分析接口模块的全局变量
extern AV_NET_MODEL g_netModel;
typedef CMap<int,int,AV_COMPONENT_INFO*,AV_COMPONENT_INFO*>CMapComponentToID;
extern CMapComponentToID g_mapComponentID;
//外部函数声明
extern AV_COMPONENT_INFO* GetComponentInfoByID(AV_KEY_INFO* tagKey);
/*节点数目为n的矩阵结构描述
节点ID 0 1 2... i-1 i i-1... n-1 n(行所在的子集标志) n+1(源计数)
0 1 取值为100~100+(n-1) 0或1
1 1
2 1
... ...
i-1 1
i 1
i+1 1
... ...
n-1 1
矩阵结构描述*/
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////内部使用函数/////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//刷新指定元件
void RefreshComponentPower(AV_COMPONENT_INFO* pComponent,int nPower)
{
ASSERT(pComponent);
AV_TAG_VALUE tagValue;
tagValue.nValue = nPower;
if(pComponent->nTopoColorTagID >= 0)
::AVSetTagVal(pComponent->nTopoColorTagID,&tagValue);
else if(pComponent->nTopoColorTagID == -1)
{
char szBuffer[INFOKEY_LENGTH+1];
AV_TAG_NAME tagName;
strcpy(szBuffer,"@\0");
strcat(szBuffer,pComponent->keyInfo.chKey);
strcpy(tagName,szBuffer);
::AVGetTagID(tagName,(ULONG*)&pComponent->nTopoColorTagID);
if(pComponent->nTopoColorTagID == -1)
pComponent->nTopoColorTagID = -2;
else
::AVSetTagVal(pComponent->nTopoColorTagID,&tagValue);
}
//Sleep(1);//加延时为了使图形拓朴着色“显示”正确(数据是对的)wxg20070314注去,认为没有必要
}
//刷新指定子集的元件拓扑着色
void RefreshSubsetPower(int* pNodeArray,int nPower)
{
//获取nodeArray代表的连通子集当中的所有元件
typedef CTypedPtrList<CPtrList,AV_COMPONENT_INFO*>CComponentInfoList;
CComponentInfoList componentInfoList;
BOOL bSinglePort;
for(int i=0; i<g_netModel.nNodeSum; i++)
{
if(*(pNodeArray+i) != 1) continue;
AV_NODE_INFO* pNodeInfo = g_netModel.pNodeInfo + i;
for(int j=0; j<pNodeInfo->nComponentSum; j++)
{
//此处元件的由于需要考虑拓扑状态,因此必须到元件集中查找
AV_COMPONENT_INFO* pComponent = NULL;
pComponent = GetComponentInfoByID(pNodeInfo->pKeyInfo+j);
if(!pComponent) continue;
//拓扑状态为1的元件必然在此子集内
if(pComponent->nState == 1)
{
//需要注意的是在此节点上的元件若其对应端子为独立端子则不应进行拓扑着色
//BOOL bNotSinglePort = TRUE;
bSinglePort = false;//wxg20070314
for(int k=0; k<pComponent->nPortSum; k++)
{
if((pComponent->pPortInfo+k)->nNode == i)
{
if((pComponent->pPortInfo+k)->nType == PORT_TYPE_SINGLE)
{
//bNotSinglePort = FALSE;
bSinglePort = true; //wxg20070314
}
break;//wxg20070314加
/*else
{
bNotSinglePort = TRUE;
break;
}*/
}
}
if(bSinglePort) continue;
if(!componentInfoList.Find(pComponent))
componentInfoList.AddTail(pComponent);
}
}
}
//刷新每一个元件的拓扑着色
POSITION pos = componentInfoList.GetHeadPosition();
while(pos)
{
AV_COMPONENT_INFO* pComponent = (AV_COMPONENT_INFO*) componentInfoList.GetNext(pos);
RefreshComponentPower(pComponent,nPower);
}
}
//拷贝矩阵
void CopyNodeMatrix(int **pNodeMatrixTag, int **pNodeMatrixRef)
{
ASSERT(pNodeMatrixTag && pNodeMatrixRef);
for(int i=0; i<g_netModel.nNodeSum; i++)
memcpy(*(pNodeMatrixTag+i),*(pNodeMatrixRef+i),sizeof(int)*(g_netModel.nNodeSum+2));
}
//对矩阵进行全局计算
void CalcNodeMatrix(int** pNodeMatrix)
{
int nCount = g_netModel.nNodeSum;
int i,j,k,m;
i = j = k = m = 0;
BOOL bConnect = FALSE,bFlag=FALSE;
//矩阵线性相关计算
DWORD nStart = ::GetTickCount();
for(i=0;i<nCount;i++)
{
if(*(*(pNodeMatrix+i)+nCount) != 0) continue;//加过就不再加
bConnect = false;
for(m=i+1;m<nCount;m++)
{
bFlag = false;
for(j=i+1;j<nCount;j++)//线性相关的和线性无关的
{
if(*(*(pNodeMatrix+j)+nCount) != 0) continue;//加过就不再加
for(k=0; k<j+1; k++)
{
if(*(*(pNodeMatrix+i)+k) ==1 && *(*(pNodeMatrix+j)+k) == 1)
{
bConnect = true;
bFlag = true;
*(*(pNodeMatrix+j)+nCount) = -1;
for(k=0; k<j+1; k++)//for(k=0; k<nCount; k++)
{
if(*(*(pNodeMatrix+j)+k) == 1)
*(*(pNodeMatrix+i)+k) = 1;
//*(*(pNodeMatrix+i)+k) = *(*(pNodeMatrix+i)+k) || *(*(pNodeMatrix+j)+k);
}
break;
}
}
}
if(!bFlag) break;
}
if(*(*(pNodeMatrix+i)+nCount) == 0)
*(*(pNodeMatrix+i)+nCount) = 100+i;
if(bConnect)
{
for(j=i+1; j<nCount; j++)//拷贝
{
if(*(*(pNodeMatrix+j)+nCount) == -1)
{
memcpy(*(pNodeMatrix+j),*(pNodeMatrix+i),sizeof(int)*(nCount+2));
}
}
}
}
/* for(i=0; i<nCount; i++)
{
for(j=i+1; j<nCount; j++)
{
if(*(*(pNodeMatrix+j)+nCount) == -1) continue;//如第j行与第i行已经线性相关并待进一步处理则返回继续
else if(*(*(pNodeMatrix+j)+nCount) == 100+i)//第j行与第i行在0~i-1行的分析过程中已经确定线性相关了,则赋待处理标志
{
*(*(pNodeMatrix+j)+nCount) = -1;
continue;
}
else if(*(*(pNodeMatrix+i)+nCount) != 0 && *(*(pNodeMatrix+i)+nCount) == *(*(pNodeMatrix+j)+nCount))
{
*(*(pNodeMatrix+j)+nCount) = -1;
continue;
}
else
{
//判断第i行第j行是否线性相关
bConnect = FALSE;
for(k=0; k<nCount; k++)
{
if(*(*(pNodeMatrix+i)+k) ==1 && *(*(pNodeMatrix+j)+k) == 1)
{
for(k=0; k<nCount; k++)
{
if(*(*(pNodeMatrix+i)+k) == 1 || *(*(pNodeMatrix+j)+k) == 1)
*(*(pNodeMatrix+i)+k) = 1;
}
bConnect = TRUE;
break;
}
}
if(bConnect)
{
if(*(*(pNodeMatrix+j)+nCount) != 0)
{
//若第j行的线性相关标志不为0,表明还有很多行与其相关,即这些行也与第i行线性相关,即赋待处理标志
for(k=0; k<i; k++)
{
if(*(*(pNodeMatrix+k)+nCount) == *(*(pNodeMatrix+j)+nCount))
*(*(pNodeMatrix+k)+nCount) = -1;
}
}
*(*(pNodeMatrix+j)+nCount) = -1;
}
}
}
if(*(*(pNodeMatrix+i)+nCount) == 0)
*(*(pNodeMatrix+i)+nCount) = 100+i;
for(j=0; j<nCount; j++)
{
if(*(*(pNodeMatrix+j)+nCount) == -1)
memcpy(*(pNodeMatrix+j),*(pNodeMatrix+i),sizeof(int)*(nCount+2));
}
}*/
nStart = ::GetTickCount()-nStart;
//循环节点确定每一子集的源计数
for(i=0; i<nCount; i++)
{
if((g_netModel.pNodeInfo+i)->nPower >= 1)
{
//第i个节点的源计数>=1,则在包含i节点的行中计入该节点的源计数
for(int j=0; j<nCount; j++)
if(*(*(pNodeMatrix+i)+j) == 1)
*(*(pNodeMatrix+j)+(nCount+1)) += (g_netModel.pNodeInfo+i)->nPower;
}
}
//更新连通子集拓扑着色
CIntArray subsetArray;
for(i=0; i<nCount; i++)
{
if(*(*(pNodeMatrix+i)+(nCount+1)) >= 1)
{
BOOL bFind = FALSE;
for(int j=0; j<subsetArray.GetSize(); j++)
{
if(subsetArray[j] == *(*(pNodeMatrix+i)+nCount))
{
bFind = TRUE;
break;
}
}
if(!bFind)
{
subsetArray.Add(*(*(pNodeMatrix+i)+nCount));
//刷新连通子集*(pNodeMatrix+i)拓扑着色为有源
RefreshSubsetPower(*(pNodeMatrix+i),1);
}
}
}
}
//元件由断开到闭合而合并其节点所在的连通子集
void UnionConnectiveSubsetByComponent(AV_COMPONENT_INFO* pComponent)
{
CIntArray subsetArray;
CIntArray indexArray;
int nNodeRef = -1;
int nPower = 0;
int nCount = g_netModel.nNodeSum;
//首先收集该元件所有节点所在的所有subset的索引ID,并进行源计数
for(int i=0; i<pComponent->nPortSum; i++)
{
//若该端子是独立端子则不考虑拓扑问题
if((pComponent->pPortInfo+i)->nType == PORT_TYPE_SINGLE) continue;
nNodeRef = (pComponent->pPortInfo+i)->nNode;
if(nNodeRef < 0 || nNodeRef >= g_netModel.nNodeSum) continue;
BOOL bFind = FALSE;
for(int j=0; j<subsetArray.GetSize(); j++)
{
if(*(*(g_pMatrixNodeCurrent+nNodeRef)+nCount) == subsetArray[j])
{
bFind = TRUE;
break;
}
}
if(!bFind)
{
subsetArray.Add(*(*(g_pMatrixNodeCurrent+nNodeRef)+nCount));
indexArray.Add(nNodeRef);
nPower += *(*(g_pMatrixNodeCurrent+nNodeRef)+(nCount+1));
}
}
//如果源计数>=1,则首先查找所有这些子集中源计数=0的子集更新其拓扑着色
if(nPower >= 1)
{
for(i=0; i<indexArray.GetSize(); i++)
{
nNodeRef = indexArray[i];
if(*(*(g_pMatrixNodeCurrent+nNodeRef)+(nCount+1)) == 0)
{
//更新连通子集*(g_pMatrixNodeCurrent+nNodeRef)拓扑着色为有源
RefreshSubsetPower(*(g_pMatrixNodeCurrent+nNodeRef),1);
}
}
RefreshComponentPower(pComponent,1);
}
//把所有这些子集合并到第indexArray[0]行上
int nIndex = indexArray[0];
for(i=1; i<indexArray.GetSize(); i++)
{
int nIndex1 = indexArray[i];
for(int j=0; j<g_netModel.nNodeSum; j++)
{
if((*(*(g_pMatrixNodeCurrent+nIndex)+j) == 0) && (*(*(g_pMatrixNodeCurrent+nIndex1)+j) == 1))
*(*(g_pMatrixNodeCurrent+nIndex)+j) = 1;
}
}
//等同所有这些子集
*(*(g_pMatrixNodeCurrent+nIndex)+(nCount+1)) = nPower;
for(i=0; i<subsetArray.GetSize(); i++)
{
int nSubsetID = subsetArray[i];
for(int j=0; j<nCount; j++)
{
if(*(*(g_pMatrixNodeCurrent+j)+nCount) == nSubsetID && (j != nIndex))
memcpy(*(g_pMatrixNodeCurrent+j),*(g_pMatrixNodeCurrent+nIndex),sizeof(int)*(nCount+2));
}
}
}
//元件由闭合到断开而拆分其所在的连通子集
void BreakConnectiveSubsetByComponent(AV_COMPONENT_INFO* pComponent)
{
int nNodeRef = pComponent->pPortInfo->nNode;
if(nNodeRef < 0 || nNodeRef >= g_netModel.nNodeSum) return;
//获取元件连通前所在的连通子集所有节点的原始连接矩阵
int nPower = *(*(g_pMatrixNodeCurrent+nNodeRef)+(g_netModel.nNodeSum+1));
CIntArray nodeArray;
for(int i=0; i<g_netModel.nNodeSum; i++)
{
if(*(*(g_pMatrixNodeCurrent+nNodeRef)+i) == 1)
nodeArray.Add(i);
}
int nLocalCount = nodeArray.GetSize();
//int **pMatrixLocal = new int*[nLocalCount];
for(i=0; i<nLocalCount; i++)
{
//*(pMatrixLocal+i) = new int[g_netModel.nNodeSum+2];
memcpy(*(pMatrixLocal+i),*(g_pMatrixNodeOrigin+nodeArray[i]),sizeof(int)*(g_netModel.nNodeSum+2));
}
//对该局部矩阵进行连通性分析计算
int j,k,m;
int bConnect,bFlag;
for(i=0;i<nLocalCount;i++)
{
if(*(*(pMatrixLocal+i)+g_netModel.nNodeSum) != 0) continue;//加过就不再加
bConnect = false;
for(m=i+1;m<nLocalCount;m++)
{
bFlag = false;
for(j=i+1;j<nLocalCount;j++)//线性相关的和线性无关的
{
if(*(*(pMatrixLocal+j)+g_netModel.nNodeSum) != 0) continue;//加过就不再加
for(k=0; k<g_netModel.nNodeSum; k++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -