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

📄 fuzzyclust.cs

📁 FuzzyClust 模糊聚类 用C#语言描述.聚类方式包括:全部,按λ值,按规定类别数
💻 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 + -