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

📄 apriori_k.c

📁 基于可拓学的apriori,另加超市购物数据
💻 C
字号:
/*基于可拓学的apriori,用于数据关联规则挖掘
开发者:Ever Jian(Email:yongjunjian@gmail.com,QQ:282543459)
版本:
v0.1 2009.2.20
参与文献:<<基于可拓理论的关联规则应用研究>>,郭志强
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>

#define MAX_ELEM_NUM 100000000
//可接受的最大元素数.可以手动修改
#define MAX_STR_NUM 100//元素名称中可接受的最大字符数.可以手动修改
#define MAX_LINE_NUM 10000//每一行可接受的最大数目
//#define DEBUG

void storeElem();
void apriori_k();
long compare (const void * a, const void * b);
void help();

char *elem[MAX_ELEM_NUM];//用于保存所有的元素名称
long elemNum=0;//实际元素的个数
long itemsNum=0;//总的记录数
char *conceptStr=NULL;//概念描述
char *concepts[MAX_ELEM_NUM];//用于记录所用的概念描述
long conceptsNum=0;//用于记录概念的数目
FILE *inputFile=NULL;//用于储存输入数据的文件名
FILE *outputFile=NULL;//用于保存输出结果的文件名
double support=0.2;//支持度.默认为0.2
double confidence=0.8;//置信度.默认为0.8
long *setsH=NULL;//指向由大征集相交生成的征集
long Hdegree=0;//表示Hdegree元征集
long Hnum=0;//表示征集的个数
double *Xnum;//征集中某一字句在记录中出现的次数
double *XYnum;//征集与概念描述组合在记录中出现的次数
long *setsL=NULL;//指向由征集运算经过删除运算后生成的大征集
long Lnum=0;//记录大征集的个数
long Ldegree=0;//表示Ldegree元大征集
long rulesCount=0;//记录得到的总的关联规则数

void storeElem(){//保存输入文件中的所有元素名
	char str[MAX_STR_NUM];
	long i=0;
	long count=0;
	elemNum=0;
#ifndef DEBUG
	printf("\nReading all elements:\n");
#endif
	rewind(inputFile);
	while(!feof(inputFile)){
#ifndef DEBUG
	printf("\r%d\t\t%d",count, elemNum);
#endif
		fscanf(inputFile,"%s",str);
		count++;
		if(strcmp(str,conceptStr)){//排除概念元素
			for(i=0;i<elemNum;i++){//判断该元素是否已经被保存
				if(!strcmp(str,elem[i])){
					break;
				}
			}
			if(i==elemNum){
				elem[elemNum]=(char*)malloc(strlen(str)+1);
				strcpy(elem[elemNum],str);
				elemNum++;
			}
		}
	}
	printf("\n");
	/*for(i=0;i<elemNum;i++){
		printf("%s\n",elem[i]);
	}
	**/
}
void storeConcepts(){//将所有的元素作为概念描述保存
	char str[MAX_STR_NUM];
	long i;
	long count=0;
	conceptsNum=0;
#ifndef DEBUG
	printf("Reading all concepts from file.....\n");
#endif
	rewind(inputFile);
	while(!feof(inputFile)){
#ifndef DEBUG
	printf("\r%d\t\t%d",count, conceptsNum);
#endif
		fscanf(inputFile,"%s",str);
		count++;
		for(i=0;i<conceptsNum;i++){//判断该元素是否已经被保存
			if(!strcmp(str,concepts[i])){
				break;
			}
		}
		if(i==conceptsNum){
			concepts[conceptsNum]=(char*)malloc(strlen(str)+1);
			strcpy(concepts[conceptsNum],str);
			conceptsNum++;
		}
	}
	printf("\n");
	/*for(i=0;i<elemNum;i++){
		printf("%s\n",elem[i]);
	}
	**/
}

void apriori_k(){
	long i=0,j=0,k=0;	
	char line[MAX_LINE_NUM];//用于储存一行字串
	long num=0;//一行字串中字符的个数
	long capacity=0;//用于记录
	itemsNum=0;

#ifndef DEBUG
	printf("Start computing rules associated with the concept '%s'......\n",conceptStr);
	printf("accociate degree:");
#endif
	Hdegree=1;//一元征集
	setsH=calloc(elemNum,sizeof(long));
	for(i=0;i<elemNum;i++){//构造一元征集H1
		setsH[i]=i;	
	}	
	Hnum=i;
	Xnum=calloc(Hnum,sizeof(double));
	XYnum=calloc(Hnum,sizeof(double));
	rewind(inputFile);
#ifndef DEBUG
	printf("1\40");
#endif
	while(!feof(inputFile)){//统计数据,用于计算征集的支持度和置信度		
		fgets(line,MAX_LINE_NUM,inputFile);//读取一行记录
		itemsNum++;
		for(i=0;i<Hnum;i++){
			if(strstr(line,elem[i])!=NULL){
				Xnum[i]++;
				if(strstr(line,conceptStr)!=NULL){
					XYnum[i]++;
				}
			}
		}		
	}
	Lnum=0;
#ifdef DEBUG
	printf("H1:\n");
#endif
	for(i=0;i<Hnum;i++){//进行删除运算,准备构造大征集
#ifdef DEBUG
		printf("%s%s\t",elem[setsH[i]],conceptStr);
		printf("%f\t",XYnum[i]/itemsNum);
		printf("%f\n",XYnum[i]/Xnum[i]);
#endif
		if((XYnum[i]/itemsNum)<support){
			Xnum[i]=-1;//置-1表示将对应的征集删除
		}
		else{
			if(XYnum[i]/Xnum[i]>=confidence){//输出规则
				rulesCount++;
				fprintf(outputFile,"%s<--%s(%.2f,%.2f)\n",conceptStr,elem[i],XYnum[i]/itemsNum,XYnum[i]/Xnum[i]);//输出关联规则
				Xnum[i]=-1;//将些征集删除是为了避免规则冗余
			}else{
				Lnum++;
			}
		}
	}
	if(Lnum>0){
		Ldegree=1;
		setsL=calloc(Lnum,sizeof(long));
		j=0;
#ifdef DEBUG
		printf("L1:\n");
#endif
		for(i=0;i<Hnum;i++){//构造一元大征集,用于进行征集的交运算
			if(Xnum[i]!=-1){
				setsL[j]=setsH[i];
				j++;
#ifdef DEBUG
				printf("%s%s\t",elem[setsH[i]],conceptStr);
				printf("%f\t",XYnum[i]/itemsNum);
				printf("%f\n",XYnum[i]/Xnum[i]);
#endif
			}
		}
	}
	while(Lnum>1){//当大征集中元素个数大于1时,进行交运算
		Hnum=0;
		Hdegree++;
		capacity=1000;
		setsH=calloc(1000,sizeof(long)*Hdegree);//预分配容纳1000个Hdegree元征集的空间,以后不够用时,按100递增
		for(i=0;i<Lnum-1;i++){//大征集的相交运算
			for(j=i+1;j<Lnum;j++){
				for(k=0;k<Ldegree;k++){//判断两个征集是否能够进行交运算(即除最后一个元素不同外,其它元素都相同)
					if(setsL[i*Ldegree+k]!=setsL[j*Ldegree+k]){
						break;
					}
				}
				if(k==Ldegree-1){//满足相交的条件
					if((Hnum+1)>capacity){//空间不够用
						setsH=realloc(setsH,(capacity+100)*sizeof(long)*Hdegree);//增加100个单位的空间
						capacity=capacity+100;
					}
					for(k=0;k<Ldegree-1;k++){//进行相交运算
						setsH[Hnum*Hdegree+k]=setsL[i*Ldegree+k];
					}
					setsH[Hnum*Hdegree+Ldegree-1]=setsL[i*Ldegree+Ldegree-1];
					setsH[Hnum*Hdegree+Ldegree]=setsL[j*Ldegree+Ldegree-1];
					Hnum++;
				}
			}
		}
		if(Hnum>0){//对征集进行删除运算,构造大征集
			Xnum=calloc(Hnum,sizeof(double));
			XYnum=calloc(Hnum,sizeof(double));
			rewind(inputFile);
#ifndef DEBUG
			printf("%d\40",Hdegree);//输出计算的层次
#endif
			while(!feof(inputFile)){//统计数据,用于计算征集的支持度和置信度				
				fgets(line,MAX_LINE_NUM,inputFile);//读取一行记录
				for(i=0;i<Hnum;i++){
					for(j=0;j<Hdegree;j++){
						if(strstr(line,elem[setsH[i*Hdegree+j]])==NULL){
									break;		
						}					
					}
					if(j==Hdegree){//记录中包含该征集
						Xnum[i]++;	
						if(strstr(line,conceptStr)!=NULL){
							XYnum[i]++;
						}
					}					
					
				}		
			}
			Lnum=0;
#ifdef DEBUG
			printf("H%d:\n",Hdegree);
#endif
			for(i=0;i<Hnum;i++){//进行删除运算,准备构造大征集
#ifdef DEBUG
				for(j=0;j<Hdegree;j++){
					printf("%s",elem[setsH[i*Hdegree+j]]);
				}
				printf("%s\t%f\t",conceptStr,XYnum[i]/itemsNum);
				printf("%f\n",XYnum[i]/Xnum[i]);
#endif
				if((XYnum[i]/itemsNum)<support){
					Xnum[i]=-1;//置-1表示将其删除
				}
				else{
					if(XYnum[i]/Xnum[i]>=confidence){//输出关联规则
						rulesCount++;
						fprintf(outputFile,"%s<--",conceptStr);//输出关联规则
						for(j=0;j<Hdegree-1;j++){
							fprintf(outputFile,"%s\40",elem[setsH[i*Hdegree+j]]);
						}
						fprintf(outputFile,"%s",elem[setsH[i*Hdegree+j]]);
						fprintf(outputFile,"(%.2f,%.2f)\n",XYnum[i]/itemsNum,XYnum[i]/Xnum[i]);
						Xnum[i]=-1;//将该征集删除,避免规则冗余
					}else{
						Lnum++;					
					}
				}
			}
			if(Lnum>0){
				Ldegree++;
				setsL=calloc(Lnum,sizeof(long)*Ldegree);
				j=0;
#ifdef DEBUG
				printf("L%d:\n",Ldegree);
#endif
				for(i=0;i<Hnum;i++){//构造大征集,用于进行征集的交运算
					if(Xnum[i]!=-1){
#ifdef DEBUG
						for(k=0;k<Hdegree;k++){
							printf("%s",elem[setsH[i*Hdegree+k]]);
						}
						printf("%s\t%f\t",conceptStr,XYnum[i]/itemsNum);
						printf("%f\n",XYnum[i]/Xnum[i]);
#endif
						for(k=0;k<Ldegree;k++){
							setsL[j*Ldegree+k]=setsH[i*Ldegree+k];
						}
						qsort(setsL+j*Ldegree,Ldegree,sizeof(long),compare);//对每一个大征集进行排序处理,接下来用于检验可否相关
						j++;					
					}
				}
			}
		}else{
			Lnum=0;
		}
	}
}
long compare (const void * a, const void * b)//qsort()的辅助函数
{
  return ( *(long*)a - *(long*)b );
}

void help(){//输出帮助信息
	printf("useage:apriori_k inFile outFile [options]\n");
	printf("-s\tminmum support\n");
	printf("-c\tminmum confidence\n");
	printf("-d\tconcepts list\n");
	printf("--all\ttreat each element in the inFile as concept\n\n");
	printf("Find associated rules based on apriori algorithm using extension theory.\n");
	printf("\tversion 0.1(2009.2.20)\t(c)2009 Ever Jian(yongjunjian@gmail.com)\n");
	printf("\t\t\t\t(:Have Fun:)\n");
}

void main(long argc,char*argv[]){
	clock_t start,begin;
	//long diff;
	long i=0;
	char *inputFileName=NULL;
	char *outputFileName=NULL;
	
	begin=clock();
	if(argc<3){//当参数少于2个时,只输出帮助信息
		help();
		exit(0);
	}	
	inputFileName=argv[1];//第一个参数为输入文件名
	outputFileName=argv[2];//第二个参数为输出文件名
	inputFile=fopen(inputFileName,"rt");
	outputFile=fopen(outputFileName,"wt");		
	i=3;
	conceptsNum=0;
	while(i<argc){
		if(!strcmp(argv[i],"-d")){//输入的为概念描述
			i++;
			while(i<argc){
				if(strcmp(argv[i],"-d")&&strcmp(argv[i],"-c")&&strcmp(argv[i],"-s")&&strcmp(argv[i],"--all")){
					concepts[conceptsNum]=argv[i];
					conceptsNum++;
					i++;
				}else{
					i--;
					break;
				}
			}			
		}else if(!strcmp(argv[i],"-c")){//输入的为置信度
			i++;
			confidence=atof(argv[i]);
			i++;
		}else if(!strcmp(argv[i],"-s")){//输入的为置信度
			i++;
			support=atof(argv[i]);
			i++;
		}else if(!strcmp(argv[i],"--all")){//将每一个元素都作为一个概念描述
			start=clock();
			storeConcepts();
#ifndef DEBUG
			printf("Time eclipsed:%.3fs\n",(double)(clock()-start)/CLOCKS_PER_SEC);
#endif
			i++;
		}else{
			printf("参数无法识别!");
			exit(-1);
		}
	}
	if(conceptsNum==0){
		storeConcepts();
	}

	for(i=0;i<conceptsNum;i++){//对每一个概念进行计算
		conceptStr=concepts[i];
		start=clock();
		storeElem();//先将所有的元素保存起来,使得一个元素与一个数组下标对应起来
#ifndef DEBUG
		printf("\nTime eclipsed:%.3fs\n",(double)(clock()-start)/CLOCKS_PER_SEC);
#endif
		start=clock();
		apriori_k();
#ifndef DEBUG
		printf("\nTime eclipsed:%.3fs\n",(double)(clock()-start)/CLOCKS_PER_SEC);
#endif
	}
#ifndef DEBUG
	printf("\nFind %d rules in %s within %0.3f seconds.\n",rulesCount,outputFileName,(double)(clock()-begin)/CLOCKS_PER_SEC);
#endif
	fclose(inputFile);
	fclose(inputFile);

}

⌨️ 快捷键说明

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