#include "function_c.h"
int AequalC(unsigned long *C, unsigned long *A);
void CtoD(unsigned long *D, unsigned long *C);
void CCNtoD(unsigned long *D, unsigned long *C, unsigned long *CN);
long long com_num = 0;
long long conceptNum = 0;
void InClose(unsigned long *B, unsigned long *A, unsigned long *AN, unsigned long start_ulong, int start_bit_j, int *start_ulongFlag, unsigned long **N, unsigned long ***N_stack);
clock_t start, finish;
void out_TWconcepts(unsigned long *setC, unsigned long *setCN, unsigned long *setD);
char choice='y',sort_choice;
int BisEmpty(unsigned long *D);
unsigned long concept_temp[2000000];
void MyTWconcepts(unsigned long*, long);
int file_out_num = 0;
int ANjtoCN(unsigned long *CN, unsigned long *AN, unsigned long *cols);
void out_easy_TWconcepts(unsigned long *setD);
void out_test_TWconcepts(unsigned long *setC, unsigned long *setCN, unsigned long *setD);
int i_temp = 0;
typedef struct {
double start;
double stop;
} stopWatch;
class CStopWatch {
private:
stopWatch timer;
double frequency;
double LIToSecs(double & L);
public:
CStopWatch();
void startTimer();
void stopTimer();
double getElapsedTime();
};
int main(int argc, char ** argv)
{
out_file = fopen("out_file.txt", "w");
/* = 456654456464;
printf("%d\t",sizeof(long long));
printf("%d\t", sizeof(int));
printf("com_num个数:%lld, ", com_num);
printf("概念个数:%lld\n", conceptNum);*/
system("color F0");
read_file();
printf("约简否?排序否(eg:y,y):");
getchar();//读取上次输入余下的换行符????。。。
scanf("%c,%c", &choice, &sort_choice);//少了取地址,数组才不用取地址。。。 且不可以scanf("%c\n", &choice);加回车。。。。
create_context(); free(mybuf);//背景中32位每一位都有用,可是queue_Flag那块是为何可以用属性列的最后一位???????
//现在可忽略背景的创建了,,,基本同自己的context,这儿只是单指针罢了。。。。//0-31context[row * anum_longSize+0], 32-63context[row * anum_longSize+1],,,...context[row * anum_longSize+anum_LongSize-1]//这种思想自己用过。。。。
initialize_output();
///WWWang排序背景。。。。。。。。。。。。
/*if (sort_choice == 'y')
sort_context();*/
initialize_algorithm(); //用于给cols赋值 cols[0]..cols[onum_longSize-1]放属性1和所有对象的关系。。。cols[onum_longSize]..cols[2*onum_longSize-1]放属性2和所有对象的关系,并初始化输出即attributes[]
unsigned long *A; unsigned long *AN; unsigned long *B; unsigned long *pA; int *start_ulongFlag;
B = (unsigned long *)malloc(byte_anumLongSize + 2*byte_onumLongSize); /* 分配一个概念占用的空间,包括内涵与外延 */
A = B + anum_longSize; /* 外延的起始位置 */
AN = A + onum_longSize;
memset(A, 0xFF, byte_onumLongSize);有问题。。。要再去掉对象为空的那几个1。。。。
memset(AN, 0xFF, byte_onumLongSize);
for (int i = objects % (ARCHBIT + 1); i <ARCHBIT + 1; i++)//重要,确保A AN C CN多余的那几位全为0
{
A[onum_longSize-1] -= (BIT << i);//重要
AN[onum_longSize - 1] -= (BIT << i);//重要
}
memset(B, 0, byte_anumLongSize);//WWWang位全置0
start_ulongFlag = (int *)malloc(sizeof(int) * (attributes + 1) * attributes);
unsigned long **N; unsigned long ***N_stack;
N = (unsigned long **)malloc(sizeof(unsigned long *) * attributes);
/* 存储指向算法中的queue_Flag(即新生成且重复的内涵D)的地址。所用空间在本函数之外分配,只有一次调用所需空间,
一个属性对应一个地址,共计n个单元。上层调用的地址信息保存在N_stack中,在递归返回时通过N_stack恢复 */
memset(N, 0, sizeof(unsigned long *) * attributes);
N_stack = (unsigned long ***)malloc(sizeof(unsigned long **) * (attributes + 1) * attributes);
/* 堆栈,用于递归返回时恢复N。逻辑结构域大小同starts。
共有n+...+1=n(n+1)/2组,每组2个单元;第一单元存储 当前属性对应的N单元的地址,第二单元存储其值 */
start = clock();
InClose(B, A,AN,0, ARCHBIT, start_ulongFlag, N, N_stack);
finish = clock();
FILE *out_result;
out_result = fopen("wwwResults.txt", "a");
if (sort_choice == 'y')
{
printf("排序后:");
fprintf(out_result, "排序后:");
}
else
{
printf("不排序:");
fprintf(out_result, "不排序:");
}
if (choice == 'y')
{
printf("约简:");
fprintf(out_result, "约简:");
}
else
{
printf("全部:");
fprintf(out_result, "全部:");
}
printf("%s:%d*%d, ", fname, objects, attributes);
printf("时间:%lf秒, ", (double)(finish - start) / CLOCKS_PER_SEC);
printf("com_num个数:%lld, ", com_num);
printf("概念个数:%lld\n", conceptNum);
fprintf(out_result, "TWInClose: %s:%d*%d, ", fname, objects, attributes);
fprintf(out_result, "时间:%lf秒, ", (double)(finish - start) / CLOCKS_PER_SEC);
fprintf(out_result, "com_num个数:%lld, ", com_num);
fprintf(out_result, "概念个数:%lld\n", conceptNum);
fclose(out_result);
fclose(out_file);
system("pause");
return 0;
}
/*
请输入文件名:cdat_lung-cancer.dat
约简否?排序否(eg:y,y):y,y
supp:10
supp:100
supp:1000
supp:10000
supp:100000
supp:200000
supp:300000
supp:400000
supp:500000
supp:600000
supp:700000
supp:800000
supp:900000
supp:1000000
supp:1100000
!!!:概念格式:(({0,1,2,3},{0,1,2,3}),{})
排序后:约简:cdat_lung-cancer.dat:32*162, 时间:10.115000秒, com_num个数:3127560, 概念个数:1120807
请按任意键继续. . .
//不输出概念的话:
排序后:约简:cdat_lung-cancer.dat:32*162, 时间:1.284000秒, com_num个数:3127560, 概念个数:1120807
*/
void MyTWconcepts(unsigned long*concept, long num)
{
for (int k = 0; k < num; k++)
{
int i, j, c;
int first = 1;
fprintf(out_file, "(({");
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (concept[j + (onum_longSize * 2 + anum_longSize)*k] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "},{");
first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (concept[j + (onum_longSize * 2 + anum_longSize)*k +onum_longSize] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "}),{");
//int i, j, c;
//int first = 1;
//printf(", ConceptNum=%d,%x:", conceptNum, setD[0]);
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
int flag_wan = 0;
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (concept[j + (onum_longSize * 2 + anum_longSize)*k +onum_longSize*2] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "})");
fprintf(out_file, "\n");
}
}
void InClose(unsigned long *B, unsigned long *A, unsigned long *AN, unsigned long start_ulong, int start_bit_j, int *start_ulongFlag, unsigned long **N, unsigned long ***N_stack)// start_ulong ,start_bit_j 二者组合在一起表示本次调用的起始属性,即算法中的y。 start_ulong是y所在单元(一个unsigned long),start_bit_j是y的位序号
{
int i, j_numAttri; unsigned long *C,*CN, *D, *temp_D; int *start_ulongFlagtemp = start_ulongFlag;
j_numAttri = start_ulong * (ARCHBIT + 1) + (ARCHBIT - start_bit_j);//WWWang,赋初值OK了。。。j_numAttri为当前属性的序号(也表示前面已经处理了j_numAttri个属性)
unsigned long *D_head;
D = temp_D = D_head = (unsigned long *)malloc((byte_anumLongSize + byte_onumLongSize*2) * (attributes - j_numAttri));
C = D + anum_longSize; //第一个概念的外延的起始位置。。。
CN = C + onum_longSize;
unsigned long ***N_stack_temp = N_stack;
for (; start_ulong < anum_longSize; start_ulong++)//遍历所有属性。。。
{
com_num++;
int flag_bianliwan = 0;
for (; start_bit_j >= 0; start_bit_j--, j_numAttri++)//遍历每个longSize(32个对象)中的所有对象。。。
{
if (j_numAttri >= attributes) //因为最后一个longSize空间中放的属性个数很可能不满,所以特殊处理下。。。。
{
flag_bianliwan = 1;
break;
}
if (!(B[start_ulong] & (BIT << start_bit_j))) /* 算法中的j属于B */
{
int flag_imply = 0;
if (N[j_numAttri] != NULL)//若为空,则直接计算新概念进入一般测试
{
if (N[j_numAttri][start_ulong] & ~(B[start_ulong]) & Yj[start_bit_j])
{ //若集合A的某些元素不在集合B中,则A一定不包含于B。判断Nj是否包含于B。Yj[start_bit_j]用于屏蔽start_bit_j及start_bit_j右边的bit
flag_imply = 1;
}
if (flag_imply == 0)
{
for (i = 0; i < start_ulong; i++)
{
if (N[j_numAttri][i] & ~(B[i]))
{
flag_imply = 1;
break;
}
}
}
}
if (flag_imply == 0)
{
printf("j=%d\n", j_numAttri);
int result1 = AjtoC(C, A, cols[j_numAttri]);
if (result1 == 2)
continue;
//if (result1 != 2)//表示C不空,C大小>0.。。。。
{
int result2 = ANjtoCN(CN, AN, cols[j_numAttri]);
if (result2 == 2)
continue;
//if (result2 != 2)//表示CN不空,CN大小>0.。。。。
{
if ((result1 == 1) && (result2 == 1))
{
B[start_ulong] |= (BIT << start_bit_j);//将属性j加入B中。。。。
}
if (AjtoC(C, A, cols[j_numAttri]) == 2)
if ((result1 == 0) || (result2 == 0))//((result1 == 1) && (result2 == 1))不成立。。
{
//CtoD(D, C);//WWWang 为了求D。。。。。
CCNtoD(D, C, CN);
if (!((D[start_ulong] ^ B[start_ulong]) & Yj[start_bit_j]))//初步判断最接近j的那个longSize的B和D中属性的关系是否满足Bqueue_Flagj等于Dqueue_Flagj...,自己分步试了,没问题。。。
{
int flag_skiptoelse = 1;
for (i = 0; i < start_ulong; i++)//为了测试剩余属性0,1...(start_ulong-1)*4中的属性是否有:Bqueue_Flagj=Dqueue_Flagj成立与否。。。WWWang*********
{
if (D[i] ^ B[i])//B和D不同,因为D[i]和B[i]中的属性都在Yj中,所以有Bqueue_Flagj不等于Dqueue_Flagj
{
flag_skiptoelse = 0;
*N_stack_temp = &(N[j_numAttri]);
N_stack_temp++;
*N_stack_temp = (unsigned long **)N[j_numAttri];//强制类型转换
N_stack_temp++;
N[j_numAttri] = D;
D[anum_longSize - 1] |= BIT;// //WWWang 初始化时anum_longSize多给了(1位到31位,就是为了这里queue_Flag用的最右边那个标志位。。。)
break;
}
}
if (flag_skiptoelse == 1)
{
//**************入队。。。。。。。。。
//入队对应的start_ulong,start_bit值。。。。。
//当然D通过标志位queueFlag,,,初始化全0即都入队,当正则检测失败时置为1,表示不入队。。。。
*start_ulongFlagtemp = start_ulong; start_ulongFlagtemp++;
*start_ulongFlagtemp = start_bit_j; start_ulongFlagtemp++;
}
}
else//正则检测失败。。。。。。。。。
{
*N_stack_temp = &(N[j_numAttri]);
N_stack_temp++;
*N_stack_temp = (unsigned long **)N[j_numAttri];//强制类型转换
N_stack_temp++;
N[j_numAttri] = D;
D[anum_longSize - 1] |= BIT; //WWWang 初始化时anum_longSize多给了(1位到31位,就是为了这里queue_Flag用的最右边那个标志位。。。)
}
D = CN + onum_longSize;//D指向新概念的起始地址。。。。
C = D + anum_longSize;//C在D地址上加anum_longSize,同初始化解释。。。WWWang
CN = C + onum_longSize;
}
}
}
}
}
/j_numAttri++;//统计已遍历属性的个数,主要为了控制最后一个anum_longSize中的属性,因为它很可能不满,不等遍历32个就要退出。。。
}
if (flag_bianliwan == 1)//通过j_numAttri和attribe比对,判断属性遍历完否。。。
break;
else
start_bit_j = ARCHBIT;//下一个anum_longSize中的起始位,设置为31。。。。。
}
if (choice=='y')
{
//out_easy_TWconcepts(B);
out_TWconcepts(A, AN, B);
conceptNum++;
if (conceptNum <= 100000)
{
if (conceptNum == 10 * countConcept)
{
printf("supp:%lld\n", conceptNum);
countConcept *= 10;
}
}
else
{
i_temp++;
if (i_temp == 100000)
{
printf("supp:%lld\n", conceptNum);
i_temp = 0;
}
}
}
if (choice == 'n')
{
//out_easy_TWconcepts(B);
out_TWconcepts(A, AN, B);
conceptNum++;
if (conceptNum <= 100000)
{
if (conceptNum == 10 * countConcept)
{
printf("supp:%lld\n", conceptNum);
countConcept *= 10;
}
}
else
{
i_temp++;
if (i_temp == 100000)
{
printf("supp:%lld\n", conceptNum);
i_temp = 0;
}
}
}
for (; temp_D != D; temp_D = CN + onum_longSize)//temp_D != D这个条件用于处理所有的计算出的概念
{
C = temp_D + anum_longSize;//队列中的第一个概念外延
CN = C + onum_longSize;
if (temp_D[anum_longSize - 1] & BIT) //WWWang 当前概念没有入队,所以不用遍历子概念。。。。是queue_Flag中的失败概念,即树中的方块节点,不递归
continue;
//执行InClose的D=BUj 但是j没有入队啊。。。。当时的j如何保存,,额有了*(start_ulongFlag + 1)就是了。。。。
//当时的D[Bchildren[0]]即D[*start_ulongFlag], D[Bchildren[1]]即D[*(start_ulongFlag+2)],D[Bchildren[j]]即D[*(start_ulongFlag+2*j)]当然 *start_ulongFlag,*(start_ulongFlag+2)等可能相等
temp_D[*start_ulongFlag] = B[*start_ulongFlag] | (BIT << *(start_ulongFlag + 1));//刚开始两个D只有一个改为temp_D,两一个忘记改,一定程度影响com_num
if (*(start_ulongFlag + 1) == 0)
InClose(temp_D, C, CN, *start_ulongFlag + 1, ARCHBIT, start_ulongFlagtemp, N, N_stack_temp);//走下一anum_longSize,ARCHBIT为下一anum_longSize中的属性31,
else //还没到longSize的最后一位,start_ulong不变,start_bit_j-1即可
InClose(temp_D, C, CN, *start_ulongFlag, *(start_ulongFlag + 1) - 1, start_ulongFlagtemp, N, N_stack_temp);//看下一个属性即start_bit_j-1,即*(start_ulongFlag + 1) - 1
start_ulongFlag += 2;//WWWang(指向下一个,为了和D0,D1,D2等的切换一直,切换到同一个概念。。。。
}
for (; N_stack != N_stack_temp; N_stack += 2)
{
**N_stack = (unsigned long *)*(N_stack + 1); /* 把N恢复到刚进入本次调用时的状态,注意这里必须强制转换回来 */
}
free(D_head);
return;
}
int BisEmpty(unsigned long *B)
{
for (int k = 0; k < anum_longSize; k++)
{
if (B[k]>0)
return 0;
}
return 1;
}
int AjtoC(unsigned long *C, unsigned long *A, unsigned long *cols)//cols初始值为cols[j_numAttri]
{
int i, j, k;
int flag = 1;
int flagC_empty = 0;
if (cols)//cols属性外延即为j',也即程序中的cols[j_numAttri]????但有问题啊,cols[0...onumLongsize-1]才是属性1和所有对象的关系。。
{
for (k = 0; k < onum_longSize; k++)//为了遍历cols[j_numAttri+0],cols[j_numAttri+1],..cols[j_numAttri+onum_longSize-1]
{
///printf("cols[%d]:%x\n:",k,cols[k]);
C[k] = A[k] & (cols[k]);//A与j'的交集,计算新的外延
if ((choice == 'y') && (C[k] == 0))
{
flagC_empty++;
}
if ((flag == 1) && (C[k]!=A[k]))//如果二者不相等。。。
{
flag = 0;
}
}
}
if (flag == 1)//A等于C
return 1;
else //A不等于C
{
if (flagC_empty == onum_longSize)//C为空。。。不进行正则判断
return 2;
else //C不空。。进行正则判断
return 0;
}
}
int ANjtoCN(unsigned long *CN, unsigned long *AN, unsigned long *cols)//cols初始值为cols[j_numAttri]
{
int i, j, k;
int flag = 1;
int flagC_empty = 0;
if (cols)//cols属性外延即为j',也即程序中的cols[j_numAttri]????但有问题啊,cols[0...onumLongsize-1]才是属性1和所有对象的关系。。
{
for (k = 0; k < onum_longSize; k++)//为了遍历cols[j_numAttri+0],cols[j_numAttri+1],..cols[j_numAttri+onum_longSize-1]
{
///printf("cols[%d]:%x\n:",k,cols[k]);
CN[k] = AN[k] & (~cols[k]);//AN与jn'的交集,计算新的外延
if ((choice == 'y') && (CN[k] == 0))
{
flagC_empty++;
}
if ((flag == 1) && (CN[k] != AN[k]))//如果二者不相等。。。
{
flag = 0;
}
}
}
if (flag == 1)//A等于C
return 1;
else //A不等于C
{
if (flagC_empty == onum_longSize)//C为空。。。不进行正则判断
return 2;
else //C不空。。进行正则判断*/
return 0;
}
}
void CCNtoD(unsigned long *D, unsigned long *C, unsigned long *CN)
{
int i, j, k, l;
memset(D, 0xFF, byte_anumLongSize);//WWWang位全置1
if (D[anum_longSize - 1] % 2 == 1)//如果最后一位位1则初始为0,即默认入队的。。。。??? 但考虑到作者没写,且程序几个数据的结果都没问题,暂时不加
D[anum_longSize - 1]--;
for (k = 0; k < onum_longSize; k++)
{
if (C[k])//如果外延不为空,求C'即D
{
for (l = 0; l <= ARCHBIT; l++)//该循环实现了外延中的所有对象属性相交
{
if (C[k] >> l)//如果移位后为0,则没有更多的对象处理,跳出for循环
{
if ((C[k] >> l) & BIT)//对外延中的对象l处理
{
for (i = 0, j = anum_longSize * (k * (ARCHBIT + 1) + l); i < anum_longSize; i++, j++)
{
D[i] = D[i] & (context[j]);
}
}
}
else
{
break;
}
}
}
if (CN[k])//如果外延不为空,求CN'即D
{
for (l = 0; l <= ARCHBIT; l++)//该循环实现了外延中的所有对象属性相交
{
if (CN[k] >> l)//如果移位后为0,则没有更多的对象处理,跳出for循环
{
if ((CN[k] >> l) & BIT)//对外延中的对象l处理
{
for (i = 0, j = anum_longSize * (k * (ARCHBIT + 1) + l); i < anum_longSize; i++, j++)
{
D[i] = D[i] & (~context[j]);
}
}
}
else
{
break;
}
}
}
}
}
void CtoD(unsigned long *D, unsigned long *C)//cols初始值为cols[j_numAttri]
{
int i, j, k, l;
memset(D, 0xFF, byte_anumLongSize);//WWWang位全置1
if (D[anum_longSize - 1] % 2 == 1)//如果最后一位位1则初始为0 但考虑到作者没写,且程序几个数据的结果都没问题,暂时不加
D[anum_longSize - 1]--;
for (k = 0; k < onum_longSize; k++)
{
if (C[k])//如果外延不为空,求C'即D
{
for (l = 0; l <= ARCHBIT; l++)//该循环实现了外延中的所有对象属性相交
{
if (C[k] >> l)//如果移位后为0,则没有更多的对象处理,跳出for循环
{
if ((C[k] >> l) & BIT)//对外延中的对象l处理
{
for (i = 0, j = anum_longSize * (k * (ARCHBIT + 1) + l); i < anum_longSize; i++, j++)
{
D[i] = D[i] & (context[j]);
}
}
}
else
{
break;
}
}
}
}
}
function_c.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define BIT ((unsigned long) 1)
#define zero_LONG ((unsigned long) 0)
#define INT_SIZE (sizeof (int))
#define LONG_SIZE (sizeof (unsigned long))
#define ARCHBIT ((LONG_SIZE * 8) - 1) /* 最高位序号 */
#define byte_anumLongSize (LONG_SIZE * anum_longSize) // 属性占用的字节数,一个属性一bit,对的其实就是4*(attributes/32+1)
#define byte_onumLongSize (LONG_SIZE * onum_longSize)
#define bufBlock1024 1024
int attributes = 0; //属性的总个数
int objects = 0; //对象的总个数
int anum_longSize = 0; //存储属性所需要的LONG_SIZE个数
int onum_longSize = 0; //存储对象所需要的LONG_SIZE个数
int table_ones = 0;//形式背景表格中1的个数
int intData[1000];
unsigned long *context;//用于存储形式背景的指针
/*宏定义一个函数用来存储形式背景中1对应的属性,存储在mybuf开始的地址空间中*/
FILE *in_file;
FILE *out_file;
int *mybuf = NULL;//一个一维数组,大小除了多存放行结束标志-1则该多少是多少,一点不多malloc.
int mybuf_index = 0;
int mybuf_size = bufBlock1024;
void create_context();
void read_file();
void allocate_mybufer(int **mybufer, int size);
int getNextInt(FILE *file, int *value);
void initialize_algorithm();
unsigned long **cols;//属性列,双指针。。。
unsigned long Yj[ARCHBIT + 1]; /* 第i个元素的右边i位全是0,从第i+1位向左全为1。用于屏蔽右边i位 。为了实现和集合Yj的相交*/
int AjtoC(unsigned long *C, unsigned long *A, unsigned long *cols);
int *attrib_numbers,*object_numbers;
long long countConcept = 1;
#define PushNewInterger(__value) \
{ \
if (mybuf_index >= mybuf_size) { \
mybuf_size += bufBlock1024; \
allocate_mybufer (&mybuf, mybuf_size); \
} \
mybuf[mybuf_index] = (__value); \
mybuf_index ++; \
}
void print_concepts(unsigned long *setC, unsigned long *setD);
void print_A(unsigned long *setA);
void print_B(unsigned long *setB);
void out_concepts(unsigned long *setC, unsigned long *setD);
char fname[100];
void sort_context();
int min_support = 0;
int *supps;
int rows_compar(const void *a, const void *b);
int cols_compar(const void *a, const void *b);
void initialize_output();
void initialize_output()
{
//初始化输出。。。。
int q;
attrib_numbers = (int *)malloc(sizeof(int) * attributes);
for (q = 0; q < attributes; q++)
attrib_numbers[q] = q;
int p;
object_numbers = (int *)malloc(sizeof(int) * objects);
for (p = 0; p < objects; p++)
object_numbers[p] = p;
}
void initialize_algorithm()
{
//用于给cols赋值。。。。
cols[0]..cols[onum_longSize-1]放属性1和所有对象的关系。。。cols[onum_longSize]..cols[2*onum_longSize-1]放属性2和所有对象的关系
int i, j, k, x, y;
unsigned long *temp_colmybuf, mask, *cols_mybuf;
for (i = 0; i <= ARCHBIT; i++)//下面两个for循环对Yj[i]初始化
{
Yj[i] = zero_LONG;//zero_LONG是unsigned long型的0
for (j = ARCHBIT; j > i; j--)
{
Yj[i] |= (BIT << j); //通过for循环、或的作用。。。 第i个元素的右边i位全是0,从第i+1位向左全为1,因为Bit是unsigned long型1。。。。
}
}
//Yj[i]现在第i个元素的右边i位全是0,从第i+1位向左全为1。用于屏蔽右边i位 。为了实现和集合Yj的相交*/
cols_mybuf = (unsigned long *)malloc(LONG_SIZE * onum_longSize * attributes);//单指针。。。。存储背景,这时换成。。。以列为单位
memset(cols_mybuf, 0, LONG_SIZE * onum_longSize * attributes);//初始化为0
cols = (unsigned long **)malloc(sizeof(unsigned long *) * attributes);//双指针。。。。 存储列地址
temp_colmybuf = cols_mybuf;
for (k = j = 0; j < anum_longSize; j++)//anum_longSize属性用的long的个数。。。
{
for (i = ARCHBIT; i >= 0; i--, k++)
{
if (k >= attributes)//如果所有属性处理完毕,则退出
return;
mask = (BIT << i);//mask=1左移i位。。。即1*2^i
cols[k] = temp_colmybuf;
for (x = 0, y = j; x < objects; x++, y += anum_longSize)
{
if (context[y] & mask)//判断x对象是否具有属性i????
{
temp_colmybuf[x / (ARCHBIT + 1)] |= BIT << (x % (ARCHBIT + 1));//对象x是否具有属性i....
}
}
temp_colmybuf += onum_longSize;//cols[0]..cols[onum_longSize-1]放属性1和所有对象的关系。。。cols[onum_longSize]..cols[2*onum_longSize-1]放属性2和所有对象的关系
//与context不同,cols[0][0]中的存放12345678,1放对象28-31,2放对象24-27,3放对象20-23,4放。。。7放4-7位,8放对象0-3 但是也是32位全用来存放有效的属性。。。 为何queue_Flag中要用属性列的最后一位作标志位判断重复失败与否。。。
//printf("cols[%d][0]:%x\n", k, cols[k][0]);
//printf("cols[%d][1]:%x\n", k, cols[k][1]);
}
}
}
void read_file()//读取形式背景文件
{
printf("请输入文件名:");
scanf("%s", fname);
FILE *file = fopen(fname, "r");
int last_value = -1, value = 0, last_attribute = -1, last_object = -1;
allocate_mybufer(&mybuf, mybuf_size);//为mybuf重新申请更大的空间。。。
while (getNextInt(file, &value))//依次获得文件中的属性值 每次仅读取一个数字。。。
{
if ((value < 0) && (last_value < 0))//某一行为空,不作处理,不影响。。。
continue;
if (value < 0)//行末情况发生,last_object计数加1,用-1来分割地址中不同对象的属性
{
last_object++;//统计非空行的行数,即对象的个数。。。。
PushNewInterger(-1);
}
else
{
if (value > last_attribute)
{
last_attribute = value;//为了找到最大的属性值,即属性的个数。。。。
}
PushNewInterger(value);
}
last_value = value;
}
if (last_value >= 0)
{
last_object++;
PushNewInterger(-1);//地址中最后一个元素赋值为-1
}
objects = last_object + 1;//
attributes = last_attribute + 1;//所有属性从0开始。。。。 背景从0开始
//attributes = last_attribute;
fclose(file);
}
int getNextInt(FILE *file, int *value)
{
//通过value传值,return仅仅返回真假,是否读取到了数值。。。。
int ch = ' ';
*value = -1;//初始化为-1,若ch到行末但不是文件尾,那么value为默认值-1
while ((ch != EOF) && ((ch < '0') || (ch > '9')))//文件没到末尾且ch不为数字,即空格时
{
ch = fgetc(file);
if (ch == '\n')
return 1;//走到行尾了。。。。
}
if (ch == EOF)
return 0;//走到文件尾了。。。。
*value = 0;
while ((ch >= '0') && (ch <= '9'))//ch为数字的情况,计算value的值
{
*value *= 10;
*value += ch - '0';
ch = fgetc(file);
}
//能走到这说明正好走到一个数字又读取了一个字符,该ch应放回文件流中,待下次判断。。。
ungetc(ch, file);//相当于撤销上一次的fgetc调用
return 1;
}
///********************************************************************************************************
int cols_compar(const void *a, const void *b)
{
int x, y;
x = supps[*(int const *)a];
y = supps[*(int const *)b];
if (x >= min_support)
{
if (y >= min_support)
return (x < y) ? -1 : ((x > y) ? 1 : 0);
else
return -1;
}
else
{
if (y >= min_support)
return 1;
else
return (x < y) ? -1 : ((x > y) ? 1 : 0);
}
}
int rows_compar(const void *a,const void *b)
{
int i;
for (i = 0; i < anum_longSize; i++)
if (((unsigned long *)a)[i] < ((unsigned long *)b)[i])
return -1;
else if (((unsigned long *)a)[i] > ((unsigned long *)b)[i])
return 1;
return 0;
}
void sort_context()
{
int i, j, k, x, y, z, ii, jj, a, aa;
unsigned long *new_context;
for (a = i = 0; i < attributes; i++)
if (supps[i] >= min_support)
a++;
qsort(attrib_numbers, attributes, sizeof(int), cols_compar);
aa = attributes;
attributes = a;
a = anum_longSize;
anum_longSize = (attributes / (ARCHBIT + 1)) + 1;
new_context = (unsigned long *)malloc(LONG_SIZE * anum_longSize * objects);
memset(new_context, 0, LONG_SIZE * anum_longSize * objects);
for (k = jj = 0, ii = ARCHBIT; k < aa; k++)
{
if (supps[attrib_numbers[k]] < min_support)
continue;
j = attrib_numbers[k] / (ARCHBIT + 1);
i = ARCHBIT - (attrib_numbers[k] % (ARCHBIT + 1));
for (x = 0, y = j, z = jj; x < objects; x++, y += a, z += anum_longSize)
if (context[y] & (BIT << i))
new_context[z] |= (BIT << ii);
if (ii > 0)
ii--;
else
{
ii = ARCHBIT;
jj++;
}
}
free(context);
context = new_context;
qsort(context, objects, byte_anumLongSize, rows_compar);
}
void create_context()//用位数组存储背景
{
int i = 0, row = 0;
//31个属性的话就用1个longSize.queue_Flag标志位(用1位),多给了(32-31)=1位,用于queue_Flag,最佳空间利用的很好
//32个属性的话就用2个longSize.本来一个就Ok了,为了queue_Flag标志位(用1位),多给了(32)=32位,用于queue_Flag
//33个属性的话就用2个longSize.queue_Flag标志位(用1位),多给了(32-1)=31位,用于queue_Flag
anum_longSize = (attributes / (ARCHBIT + 1)) + 1;//WWWang 这里多给了(1位到32位,就是为了queue_Flag用的最右边那个标志位。。。)计算存储属性需要的LONG_SIZE个数
//onum_longSize = (objects / (ARCHBIT + 2))+1;//WWWang计算存储对象需要的LONG_SIZE个数,1位也不多给。。。
onum_longSize = (objects / (ARCHBIT + 1)) + 1;//这个也多给了(1-32位。。。目前没作用,但是先不动它。。)
context = (unsigned long *)malloc(LONG_SIZE * anum_longSize * objects);//context是一维数组哈。。。。例如context[0]=??
supps = (int *)malloc(sizeof(int) * attributes);
memset(supps, 0, sizeof(int) * attributes);
if (!context)
{
fprintf(stderr, "不能给背景申请空间.\n");
exit(5);
}
memset(context, 0, LONG_SIZE * anum_longSize * objects);//先初始化为0
//memset(contextN, 0xFF, LONG_SIZE * anum_longSize * objects);
for (i = 0; i < mybuf_index; i++)//对mybuf数组中的每个元素处理
{
if (mybuf[i] < 0)//-1的情况说明一个对象的属性处理完毕,也就是文件中的一行属性处理完毕
{
row++;
continue;
}
//0-31context[row * anum_longSize+0], 32-63context[row * anum_longSize+1],,,...context[row * anum_longSize+anum_LongSize-1]//这种思想自己用过。。。。
context[row * anum_longSize + (mybuf[i] / (ARCHBIT + 1))] |= (BIT << (ARCHBIT - (mybuf[i] % (ARCHBIT + 1)))); //(ARCHBIT - (mybuf[i] % (ARCHBIT + 1)))属性0对应31-0 30对应31-30 31对应31-31。。。
supps[mybuf[i]]++;
table_ones++;
//背景是属性0代表31位,属性1代表30位。。。。属性31代表0位。。 属性32代表31位(因为32%32=0)。。。。
//printf("context[%d]:%x\n", row * anum_longSize + (mybuf[i] / (ARCHBIT + 1)),context[row * anum_longSize + (mybuf[i] / (ARCHBIT + 1))]);
}
}
void allocate_mybufer(int **mybufer, int size)//该函数为*mybufer开始的地址分配空间
{
if (*mybufer)
{
*mybufer = (int *)realloc(*mybufer, INT_SIZE * size);
}
else
{
*mybufer = (int *)malloc(INT_SIZE * size);
}
if (!*mybufer)
{
fprintf(stderr, "不能重新分配内存\n");
exit(3);
}
}
void print_A(unsigned long *setA)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
for (i = 0; i <= ARCHBIT; i++)
{
if (setA[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(" ");
}
printf("%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
break;
}
}
}
}
void print_B(unsigned long *setB)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
printf("%x,", setB[0]);
int i, j, c;
int first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
for (i = ARCHBIT; i >= 0; i--)
{
if (setB[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(" ");
}
printf("%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
break;
}
}
}
printf("\n");
}
void out_concepts(unsigned long *setC, unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
out_file = fopen("out_file.txt", "a");
int i, j, c;
int first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
for (i = 0; i <= ARCHBIT; i++)
{
if (setC[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
fprintf(out_file, " , ");
break;
}
}
}
//int i, j, c;
//int first = 1;
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
for (i = ARCHBIT; i >= 0; i--)
{
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
}
fprintf(out_file, "%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
fprintf(out_file, "\n");
fclose(out_file);
}
}
}
}
void print_concepts(unsigned long *setC, unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setC[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(" ");
}
printf("%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
printf(" , ");
break;
}
}
if (flag_wan == 1)
break;
}
//int i, j, c;
//int first = 1;
//printf(", ConceptNum=%d,%x:", conceptNum, setD[0]);
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(" ");
}
printf("%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
printf("\n");
break;
}
}
}
}
void print_TWconcepts(unsigned long *setC, unsigned long *setCN, unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
printf("(({");
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setC[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(",");
}
printf("%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
printf("},{");
first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setCN[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(",");
}
printf("%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
printf("}),{");
//int i, j, c;
//int first = 1;
//printf(", ConceptNum=%d,%x:", conceptNum, setD[0]);
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
int flag_wan = 0;
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
printf(",");
}
printf("%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
printf("})");
printf("\n");
}
void out_TWconcepts(unsigned long *setC, unsigned long *setCN, unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
fprintf(out_file, "(({");
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setC[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "},{");
first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setCN[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "}),{");
//int i, j, c;
//int first = 1;
//printf(", ConceptNum=%d,%x:", conceptNum, setD[0]);
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
int flag_wan = 0;
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, ",");
}
fprintf(out_file, "%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "})");
fprintf(out_file, "\n");
}
void out_TWconcepts_C_CN_D(unsigned long *setC, unsigned long *setCN, unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
fprintf(out_file, "");
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setC[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, ",");
first = 1;
for (c = j = 0; j < onum_longSize; j++)
{
int flag_wan = 0;
for (i = 0; i <= ARCHBIT; i++)
{
if (setCN[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
}
fprintf(out_file, "%d", object_numbers[c]);
first = 0;
}
c++;//每处理一个对象c要加一
if (c >= objects)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "|");
//int i, j, c;
//int first = 1;
//printf(", ConceptNum=%d,%x:", conceptNum, setD[0]);
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
int flag_wan = 0;
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
}
fprintf(out_file, "%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "\n");
}
void out_TWconcepts_D(unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int i, j, c;
int first = 1;
fprintf(out_file, "|");
//printf("|");
first = 1;
for (c = j = 0; j < anum_longSize; j++)
{
int flag_wan = 0;
for (i = ARCHBIT; i >= 0; i--)
{
//printf("BIT<<i:%x, ",BIT<<i);
if (setD[j] & (BIT << i))//先移位,处理的是第ARCHBIT-i属性
{
if (!first)//标志位,输出空格
{
fprintf(out_file, " ");
//printf(" ");
}
fprintf(out_file, "%d", attrib_numbers[c]);
//printf("%d", attrib_numbers[c]);
first = 0;
}
c++;//每处理一个属性c要加一
if (c >= attributes)//所有的属性处理完毕,则输出回车符,打印完毕
{
flag_wan = 1;
break;
}
}
if (flag_wan == 1)
break;
}
fprintf(out_file, "\n");
//printf("\n");
}
void out_easy_TWconcepts(unsigned long *setD)//输出概念的属性,也就是内涵。set指针指向的就是内涵的地址,通过位运算来输出背景中为1的属性
{
int j, num_str = 0;
for (j = 0; j < anum_longSize; j++)
{
fprintf(out_file, "%x ", setD[j]);
}
fprintf(out_file, "\n");
/*int j,num_str = 0;
for (j = 0; j < anum_longSize; j++)
{
intData[num_str++] = setD[j];
}
for (int i = 0; i < num_str; i++)
fprintf(out_file, "%x ", intData[i]);
fprintf(out_file, "\n");*/
}