📄 fuzzyclust.cs
字号:
using System;
using System.Collections;
using System.Data;
namespace KarstModel
{
/// <summary>
/// FuzzyClust 的摘要说明。
/// </summary>
//模糊聚类类
public class TFuzzyClust:TFuzzyMatrix,IModel
{
private double [,]sourseData;//原始数据矩阵
private double [,]standardData;//标准化矩阵
private new int row;
private new int col;
private bool isDimension=true;//数据是否有量纲
private long m_demarcateID=1;//数据标定方式代号
//coputerMethod运算方式。全部:用clust聚类;
//如果是一个真小数(0,1)之间,则用clust(level)聚类,如果是一个整数,则用clust(nType)聚类
private long computerMethod;
private Hashtable parameter;//输入参数,为Hashtable
private CollectionND result=new CollectionND();//聚类结果;运算结果
private bool runed;//是否已执行模型
private bool hasPara;//是否已设置模型所需要的参数
private double level;//按λ值聚类时的λ值
private long nType;//按规定类别数聚类时的类别数
private int[] GoeID;//地理元素编号
//返回以表格形式存储的结果,为了地理元素编号与结果联系的原因
private DataTable GetResultTableFrom2D()
{
//取得Sample表结构
DataTable myDataTable=DbfSample.GetDbfSample();
DataRow myDataRow;
//在myDataTable中增加记录行
int i;
if(GoeID!=null)
{
for(i=0;i<result.Count;i++)
{
foreach(object oIndex in (Collection1D)result[i])
{
myDataRow = myDataTable.NewRow();
myDataRow["GoeID"]=GoeID[Convert.ToInt32(oIndex)];
myDataRow["result"]=i+1;
myDataTable.Rows.Add(myDataRow);
}
}
}
else
{
for(i=0;i<result.Count;i++)
{
foreach(object oIndex in (Collection1D)result[i])
{
myDataRow = myDataTable.NewRow();
myDataRow["GoeID"]=Convert.ToInt32(oIndex);
myDataRow["result"]=i+1;
myDataTable.Rows.Add(myDataRow);
}
}
}
return myDataTable;
}
private DataTable GetResultTableFrom3D()
{
//取得Sample表结构
DataTable myDataTable = new DataTable("result");
DataColumn myDataColumn;
//增加编号列
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.Int32");
myDataColumn.ColumnName = "GoeID";
myDataColumn.Caption="编号";
myDataTable.Columns.Add(myDataColumn);
//增加结果值列:]
int iCol,iRow;
for(iCol=0;iCol<result.Count;iCol++)
{
myDataColumn = new DataColumn();
myDataColumn.DataType = System.Type.GetType("System.Int32");
myDataColumn.ColumnName = "result"+Convert.ToString(iCol);
myDataColumn.Caption="结果";
myDataTable.Columns.Add(myDataColumn);
}
DataRow myDataRow;
//在myDataTable中增加记录行
//int i;
if(GoeID!=null)
{
for(iRow=0;iRow<GoeID.Length;iRow++)
{
myDataRow = myDataTable.NewRow();
myDataRow["GoeID"]=GoeID[iRow];
for(iCol=0;iCol<result.Count;iCol++)
{
int iClass=((CollectionND)result[iCol]).AtIndex(iRow);
myDataRow["result"+Convert.ToString(iCol)]=iClass;//((CollectionND)result[iCol]).AtIndex(iRow);
};
myDataTable.Rows.Add(myDataRow);
}
}
else
{
for(iRow=0;iRow<row;iRow++)
{
myDataRow = myDataTable.NewRow();
myDataRow["GoeID"]=iRow;
for( iCol=0;iCol<result.Count;iCol++)
{
int iClass=((CollectionND)result[iCol]).AtIndex(iRow);
myDataRow["result"+Convert.ToString(iCol)]=iClass;//((CollectionND)result[iCol]).AtIndex(iRow);
};
myDataTable.Rows.Add(myDataRow);
}
}
return myDataTable;
}
public DataTable GetResultAsTable()
{
if ((computerMethod==1&&level>0&&level<1)||(computerMethod==2&&nType>1))
{
return GetResultTableFrom2D();
}
else
return GetResultTableFrom3D();
}
//返回一二维数组第K列的最小者
private double minOfArray(double [,]a,int k)
{
double min=a[0,k];
for(int i=1;i<row;i++)//row为数组的行数
if(min>a[i,k])
min=a[i,k];
return min;
}
//返回一二维数组第K列的最大者
private double maxOfArray(double [,]a,int k)
{
double max=a[0,k];
for(int i=1;i<row;i++)
if(max<a[i,k])
max=a[i,k];
return max;
}
//在二维数组中查找第n大的数
private double maxNOfArray(double [,]a,int n)
{
double max=a[0,0];
int maxN=0;
for(int i=0;i<row;i++)
for(int j=0;j<=i;j++)
if(max<a[i,j])
max=a[i,j];
maxN++;
if(maxN!=n)
{
for(int i=0;i<row;i++)
for(int j=0;j<=i;j++)
if(a[i,j]==max)
a[i,j]=-1;
maxNOfArray(a,n-1);
}
return max;
}
//第二步:数据标准化,将原始数据sourseData[,]转化为标准化的[0,1]数据
private void Standard()
{
double []xk=new double[col];
double []sk=new double[col];
double min,max;
standardData=new double[row,col];
//displaySourseData();////测试用,过后删除
//首先,如果原始数据有量纲,则做平移,标准差变换平移,标准差变换,分三步
if (isDimension==true)
{
//第一步,计算Xk(平均值)
for(int k=0;k<col;k++)
{
xk[k]=0;
for(int i=0;i<row;i++)
xk[k]=xk[k]+sourseData[i,k];
xk[k]=xk[k]/row;
}
//第二步,计算Sk;
for(int k=0;k<col;k++)
{
sk[k]=0;
for(int i=0;i<row;i++)
sk[k]=sk[k]+(sourseData[i,k]-xk[k])*(sourseData[i,k]-xk[k]);
sk[k]=Math.Sqrt(sk[k]/row);
}
//第三步:计算Xik
for(int i=0;i<row;i++)
for(int k=0;k<col;k++)
if(sk[k]!=0)//如果标准差为0(所有数据都是一样)则不变换(所有数据都是一样)
standardData[i,k]=(sourseData[i,k]-xk[k])/sk[k];
//然后,平移,极差变换,先行后列
for(int k=0;k<col;k++)
{
min=minOfArray(standardData,k);
max=maxOfArray(standardData,k);
for(int i=0;i<row;i++)
if(max>min)
standardData[i,k]=(standardData[i,k]-min)/(max-min);
else//所有数据都是一样
standardData[i,k]=1;
}
}
else//如果没有量纲,则直接复制原始数据到标准数据
{
standardData=(double[,])sourseData.Clone();
}
}
//第三步:标定,建立模糊相似矩阵
private void Demarcate()
{
switch(m_demarcateID)
{
case 1:
default:
{//数量积法
double M=0;
//计算rij,不包括1/M;以及求出M
for(int i=0;i<row;i++)
for(int j=0;j<=i;j++)
{
if(i==j)
mat[i,j]=1;
else
{
mat[i,j]=0;
for(int k=0;k<col;k++)
mat[i,j]=mat[i,j]+standardData[i,k]*standardData[j,k];
mat[j,i]=mat[i,j];
if(M<mat[i,j])
M=mat[i,j];
}
}
//对i!=j者,用Rij/M
for(int i=0;i<row;i++)
for(int j=0;j<row;j++)
if(i!=j)
mat[i,j]=mat[i,j]/(1.05*M);//修改为1.05*M,以免出现自己除自己得1
break;
}
}
}
//按设定的λ-截矩阵中的λ水平level进行聚类
//返回分类类别集合
public CollectionND ClustL(double level)
{
CollectionND clustList=new CollectionND();
int index1,index2;
for(int i=0;i<row;i++)
{
Collection1D c1=new Collection1D();
c1.Add(i);
clustList.Add(c1);
}
TFuzzyMatrix C=new TFuzzyMatrix(row,row);
C=section(level);
//Console.WriteLine("λ={0}时的λ-截矩阵为:",level);
//C.display();
for(int i=0;i<row;i++)
for(int j=0;j<=i;j++)
{
if(C[i,j]==1)//若i行与j列交叉数据为1,刚合并 元素i+1,j+1所在的两个集合.
{
index1=clustList.AtIndex(i);//index1为i+1所在集合下标
index2=clustList.AtIndex(j);//index2为j+1所在集合下标
if(index1!=index2)
clustList.Unite(index1,index2);// 合并
}
}
return clustList;
}
//按设定的λ-截矩阵中的λ水平level进行聚类
//返回分类类别集合(用多维集合)
public CollectionND ClustN(long nType)
{
CollectionND clust2List=new CollectionND();
double level;
int typeNum;
int nmax=1;
//用一数组存储模糊矩阵mat,否则在做level=maxNOfArray(a,nmax++)
//时会修改了mat ,但后面的clust2List=clust(level);要用到原来的mat,
//做用a代替mat,修改不到mat.
double [,]a=new double[row,row];
for(int i=0;i<row;i++)
for(int j=0;j<row;j++)
a[i,j]=mat[i,j];
do
{
level=maxNOfArray(a,nmax++);//在mat中查找第nmax大的数据
clust2List=ClustL(level);
typeNum=clust2List.Count;
}while(typeNum>nType);
return clust2List;
}
//全部聚类,从n类一直聚到全是一类
public CollectionND Clust()
{
CollectionND clust3List=new CollectionND();
CollectionND clust2List=new CollectionND();
double level;
int nmax=1;
//用一数组存储模糊矩阵mat,否则在做level=maxNOfArray(a,nmax++)
//时会修改了mat ,但后面的clust2List=clust(level);要用到原来的mat,
//做用a代替mat,修改不到mat.
double [,]a=new double[row,row];
a=(double [,])mat.Clone();
do
{
level=maxNOfArray(a,nmax++);//在mat中查找第nmax大的数据
clust2List=ClustL(level);
clust3List.Add(clust2List);
}while(nmax<=row);
return clust3List;
}
public TFuzzyClust()
{}
//参数意义:row原始数据的行数,即为分类对象个数;模糊矩阵mat大小便为row*row
//col原始数据的列数,原始数据和标准化数据的大小均为:row*col
//isDimension:原始数据是否有量纲,
//methodOfMaxMin:取大取小运算的编号
//demarcateID:标定的方法编号
//sdata:原始数据
public TFuzzyClust(double [,]soursedata,bool isDimension,int methodOfMaxMin,int demarcateID):base(soursedata.GetUpperBound(0)+1,soursedata.GetUpperBound(0)+1,methodOfMaxMin)
{
this.col=soursedata.GetUpperBound(1)+1;
this.row=soursedata.GetUpperBound(0)+1;
this.isDimension=isDimension;
this.sourseData=new double[row,col];
this.standardData=new double[row,col];
this.demarcateID=demarcateID;
//第一步:用输入参数soursedata给本对象soursedata赋值
this.sourseData=(double[,])sourseData.Clone();
//第二步:标准化
Standard();
//第三步:标定
Demarcate();
}
public void displaySourseData()//输出函数
{
for( int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
Console.Write("\t{0:}",sourseData[i,j]);
Console.WriteLine();
}
}
public void displaystandardData()//输出函数
{
for( int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
Console.Write("\t{0:}",standardData[i,j]);
Console.WriteLine();
}
}
public long demarcateID
{
get
{
return m_demarcateID;
}
set
{
m_demarcateID=value;
}
}
#region Model 成员
public void run()
{
if(hasPara)
{
//第二步,标准化
Standard();
//第三步:标定
Demarcate();
if(computerMethod==0)
{result=Clust();runed=true;}
else if (computerMethod==1&&level>0&&level<1)
{result=ClustL(level);runed=true;}
else if(computerMethod==2&&nType>1)
{result=ClustN(nType);runed=true;}
else
runed=false;
}
else runed=false;
}
public bool setParameters(System.Collections.Hashtable para)
{
parameter=para;
try
{
sourseData=(double [,])para["sourseData"];
isDimension=(bool)para["isDimension"];
methodOfMaxMin=(long)para["methodOfMaxMin"];
demarcateID=(long)para["demarcateID"];
computerMethod=(long)para["computerMethod"];
GoeID=(int[])para["GoeID"];
if (computerMethod==1)
level=(double)para["level"];
else if (computerMethod==2)
nType=Convert.ToInt32(para["nType"]);
row=sourseData.GetUpperBound(0)+1;
col=sourseData.GetUpperBound(1)+1;
SetData(row,row,methodOfMaxMin);
hasPara=true;
return true;
}
catch{return false;}
}
public System.Collections.Hashtable GetParameters()
{
// TODO: 添加 TFuzzyClust.GetParameters 实现
return null;
}
public System.Collections.Hashtable GetResult()
{
if (runed)
{
Hashtable ans=new Hashtable();
ans.Add("result",result);
return ans;
}
return null;
}
public string ResultToString()
{
// TODO: 添加 TFuzzyClust.ResultToString 实现
string ans=result.Output(1);
return ans;
}
public string GetKeywords()
{
// TODO: 添加 TFuzzyClust.GetKeywords 实现
return null;
}
public string GetDiscription()
{
// TODO: 添加 TFuzzyClust.GetDiscription 实现
return null;
}
public string GetSubjects()
{
// TODO: 添加 TFuzzyClust.GetSubjects 实现
return null;
}
public IModel[] GetChildren()
{
// TODO: 添加 TFuzzyClust.GetChildren 实现
return null;
}
public ParaData[] GetParaData()
{
ParaData[] ans=new ParaData[7];
ans[0]=new ParaData(-1,"sourseData","源数据二维矩阵",2,"double","源数据二维矩阵","");
ans[1]=new ParaData(-1,"isDimension","源数据是否有量纲",3,"bool","源数据是否有量纲","有,没有");
ans[2]=new ParaData(-1,"methodOfMaxMin","模糊取大取小方式",3,"long","模糊取大取小方式","Zadeh算子,环和乘积算子,有界算子,取大乘积算子,有界和取不算子, 有界和乘积算子,Enstain算子,Hamacher算子,Yager算子");
ans[3]=new ParaData(-1,"demarcateID","数据标定方式代号",3,"long","数据标定方式代号","数量积法,夹角全系弦法,相关系统法,指数相似系数法,最大最小法, 算术平均法,几何平均最小法");
ans[4]=new ParaData(-1,"computerMethod","聚类方式",3,"long","聚类方式:全部,按λ值,按规定类别数","全部,按λ值,按规定类别数");
ans[5]=new ParaData(-1,"level","按λ值聚类时的λ值",0,"double","按λ值聚类的λ值","");
ans[6]=new ParaData(-1,"nType","按规定类别数聚类时的类别数",0,"long","按规定类别数聚类时的类别数","");
return ans;
}
public ModelData GetModelData()
{
// TODO: 添加 TFuzzyClust.GetModelData 实现
ModelData ans=new ModelData();
ans.name="TFuzzyClust";
ans.classes=5;
ans.description="模糊聚类";
ans.filename="Model.dll";
ans.keyWords="模糊聚类,谢季坚";
ans.realName="模糊聚类";
ans.useMethod="按向导输入运行";
ans.uses="模糊聚类,谢季坚";
return ans;
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -