#include "fcbo_no_ny_breadth1.h"
void find_all_intents(void);
void insert_node(unsigned long * intent, unsigned long * extent, int start_int, int start_bit);
void generate_from_node(unsigned long *intent, unsigned long *extent, int start_int, int start_bit);
struct queue_node_t
{
unsigned long *intent;
unsigned long *extent;
int start_int;
int start_bit;
queue_node_t* next;
};
struct queue_node_concept
{
queue_node_t* front;
queue_node_t* rear;
} concept_queue = { NULL, NULL};
int main(int argc, char **argv)
{
//in_file = fopen("cdat_nursery.dat", "rb");
in_file = fopen("cdat_hebingAE_cuxin.dat", "rb");
out_file = fopen("out_file", "wb");
if (in_file == NULL)
return -1;
read_file(in_file);//
create_context();//
free(buff);//
fclose(in_file);//
initialize_output();//
sort_context();//
initialize_algorithm();//
clock_t start = clock();
find_all_intents();
clock_t finish = clock();
fclose(out_file);
printf("概念個數:%d, 時間%f秒\n",countNum,(finish-start)*1.0/CLOCKS_PER_SEC);
system("pause");
return 0;
}
/*
層次遍歷? “類”層次遍歷吧 因爲儘管是層次遍歷,但是對構成的格來說不是走的層次
空
空:01 2 3 4
01:012 0134 014
2:
3:34
4:
012:01234 0124
0134:
014:
34:
01234:
0124:
概念個數:11, 時間0.008000秒
*/
void find_all_intents(void)
{
unsigned long *extent;
unsigned long *intent;
intent = (unsigned long *)malloc(BYTE_COUNT_A + BYTE_COUNT_O);
extent = intent + int_count_a;
compute_closure(intent, extent, NULL, NULL);
print_attributes(intent,true);
//print_objects(extent,true);
if (intent[int_count_a - 1] & BIT)
return;
//新建queue_node_t類型指針p,tmp
queue_node_t *p, *tmp;
p = concept_queue.front = concept_queue.rear = (queue_node_t*)malloc(sizeof(struct queue_node_t));
p->intent = intent; p->extent = extent;
p->start_int = 0; p->start_bit = ARCHBIT;
p->next = NULL;
while (p)
{
generate_from_node(p->intent, p->extent, p->start_int, p->start_bit);
tmp = p;//暫存當前指針p
p = p->next;//p指向下next
free(tmp->intent);
free(tmp);
}
}
// 去掉新條件Ny(即implied),只有cbo原始條件;廣度;單結點、單概念分配內存,用完釋放
void generate_from_node(unsigned long *intent, unsigned long *extent, int start_int, int start_bit)
{
printf("\n\n當前父概念:"); print_attributes(intent,false);
//print_objects(extent, false);
unsigned long *new_extent, *new_intent; int i, total;
total = start_int * (ARCHBIT + 1) + (ARCHBIT - start_bit);//即剩餘屬性個數。。。
for (; start_int < int_count_a; start_int++)
{
for (; start_bit >= 0; start_bit--)
{
if (total >= attributes)//遍歷完了
goto skipout;
if (intent[start_int] & (BIT << start_bit))
goto skip;
new_intent = (unsigned long *)malloc(BYTE_COUNT_A + BYTE_COUNT_O);//重新申請內存。。。
new_extent = new_intent + int_count_a;
compute_closure(new_intent, new_extent, extent, cols[total]);//計算閉包
if ((new_intent[start_int] ^ intent[start_int]) & upto_bit[start_bit])//BnYj不屬於DnYj
goto skiptoelse;
for (i = 0; i < start_int; i++)//BnYj不屬於DnYj
if (new_intent[i] ^ intent[i])
goto skiptoelse;
print_attributes(new_intent,true);//打印概念的內涵
//print_objects(new_extent,true);
if (start_bit == 0)
insert_node(new_intent, new_extent, start_int + 1, ARCHBIT);//注意這不是遞歸,而是自己的方法
else
insert_node(new_intent, new_extent, start_int, start_bit - 1);
goto skip;
skiptoelse:
free(new_intent);
skip:
total++;
}
start_bit = ARCHBIT;
}
skipout:
return;
}
//自己的insert_node方法,僅僅更新概念指針concept_queue
void insert_node(unsigned long * intent, unsigned long * extent, int start_int, int start_bit)
{
queue_node_t* current= (queue_node_t*)malloc(sizeof(struct queue_node_t));//新建queue_node_t類型指針,並申請相應大小的內存
current->intent = intent;current->extent = extent;
current->start_int = start_int; current->start_bit = start_bit;
current->next = NULL;
concept_queue.rear->next = current;
concept_queue.rear = current;
return;
}
fcbo_no_ny_breadth1.h:
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BIT ((unsigned long) 1)
#define NULL_LONG ((unsigned long) 0)
#define INT_SIZE (sizeof (int))
#define LONG_SIZE (sizeof (unsigned long))
#define ARCHBIT ((LONG_SIZE * 8) - 1)
#define BYTE_COUNT_A (LONG_SIZE * int_count_a)
#define BYTE_COUNT_O (LONG_SIZE * int_count_o)
#define BUFFER_BLOCK 1024
struct stats_t
{
int total; int closures; int fail_canon; int fail_fcbo; int fail_support;
} stats = { 0, 0, 0, 0, 0 };
int *buff = NULL;
int buff_index = 0;
size_t buff_size = BUFFER_BLOCK;
int attributes = 0;
int objects = 0;
int int_count_a = 0;
int int_count_o = 0;
int table_entries = 0;
int min_support = 0;
unsigned long *context;
unsigned long **cols;
int *supps;
int *attrib_numbers;
unsigned long upto_bit[ARCHBIT + 1];
int attr_offset = 0;
FILE *in_file;
FILE *out_file;
int verbosity_level = 1;
int get_next_integer(FILE *file, int *value)
{
int ch = ' ';
*value = -1;
while ((ch != EOF) && ((ch < '0') || (ch > '9')))
{
ch = fgetc(file);
if (ch == '\n')
return 1;
}
if (ch == EOF)
return 0;
*value = 0;
while ((ch >= '0') && (ch <= '9'))
{
*value *= 10;
*value += ch - '0';
ch = fgetc(file);
}
ungetc(ch, file);
*value -= attr_offset;
return 1;
}
void allocate_buffer(int **buffer, int size)
{
if (*buffer)
*buffer = (int *)realloc(*buffer, INT_SIZE * size);
else
*buffer = (int *)malloc(INT_SIZE * size);
if (!*buffer)
{
fprintf(stderr, "Cannot reallocate buffer, quitting.");
exit(3);
}
}
#define PUSH_NEW_INTEGER(__value) \
{ \
if (buff_index >= buff_size) { \
buff_size += BUFFER_BLOCK; \
allocate_buffer (&buff, buff_size); \
} \
buff [buff_index] = (__value); \
buff_index ++; \
}
void read_file(FILE *file)
{
int last_value = -1, value = 0, last_attribute = -1, last_object = -1;
allocate_buffer(&buff, buff_size);
while (get_next_integer(file, &value))
{
if ((value < 0) && (last_value < 0))
continue;
if (value < 0)
{
last_object++;
PUSH_NEW_INTEGER(-1);
}
else
{
if (value > last_attribute)
last_attribute = value;
PUSH_NEW_INTEGER(value);
}
last_value = value;
}
if (last_value >= 0)
{
last_object++;
PUSH_NEW_INTEGER(-1);
}
objects = last_object + 1;
attributes = last_attribute + 1;
}
void create_context(void)
{
int i = 0, row = 0;
int_count_a = (attributes / (ARCHBIT + 1)) + 1;
int_count_o = (objects / (ARCHBIT + 1)) + 1;
context = (unsigned long *)malloc(LONG_SIZE * int_count_a * objects);
if (!context)
{
fprintf(stderr, "Cannot allocate bitcontext, quitting.");
exit(5);
}
memset(context, 0, LONG_SIZE * int_count_a * objects);
supps = (int *)malloc(sizeof(int) * attributes);
memset(supps, 0, sizeof(int) * attributes);
for (i = 0; i < buff_index; i++)
{
if (buff[i] < 0)
{
row++;
continue;
}
context[row * int_count_a + (buff[i] / (ARCHBIT + 1))] |= (BIT << (ARCHBIT - (buff[i] % (ARCHBIT + 1))));
supps[buff[i]]++;
table_entries++;
}
if (verbosity_level >= 2)
fprintf(stderr, "objects: %6i\nattributes: %4i\nentries: %8i\n", objects, attributes, table_entries);
}
void initialize_output(void)
{
int i;
attrib_numbers = (int *)malloc(sizeof(int) * attributes);
for (i = 0; i < attributes; i++)
attrib_numbers[i] = i;
}
void print_attributes(unsigned long *set, size_t supp)
{
int i, j, c;
int first = 1;
if (verbosity_level <= 0)
return;
for (c = j = 0; j < int_count_a; j++)
{
for (i = ARCHBIT; i >= 0; i--)
{
if (set[j] & (BIT << i))
{
if (!first)
fprintf(out_file, " ");
fprintf(out_file, "%i", attrib_numbers[c]);
first = 0;
}
c++;
if (c >= attributes)
goto out;
}
}
out:
fprintf(out_file, "\n");
}
int cols_compar(void *a, 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(void *a, void *b)
{
int i;
for (i = 0; i < int_count_a; 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(void)
{
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 = int_count_a;
int_count_a = (attributes / (ARCHBIT + 1)) + 1;
new_context = (unsigned long *)malloc(LONG_SIZE * int_count_a * objects);
memset(new_context, 0, LONG_SIZE * int_count_a * 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 += int_count_a)
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_COUNT_A, rows_compar);
}
void initialize_algorithm(void)
{
int i, j, k, x, y;
unsigned long *ptr, mask, *cols_buff;
for (i = 0; i <= ARCHBIT; i++)
{
upto_bit[i] = NULL_LONG;
for (j = ARCHBIT; j > i; j--)
upto_bit[i] |= (BIT << j);
}
cols_buff = (unsigned long *)malloc(LONG_SIZE * int_count_o * attributes);
memset(cols_buff, 0, LONG_SIZE * int_count_o * attributes);
cols = (unsigned long **)malloc(sizeof(unsigned long *) * attributes);
ptr = cols_buff;
for (k = j = 0; j < int_count_a; j++)
for (i = ARCHBIT; i >= 0; i--, k++)
{
if (k >= attributes)
return;
mask = (BIT << i);
cols[k] = ptr;
for (x = 0, y = j; x < objects; x++, y += int_count_a)
if (context[y] & mask)
ptr[x / (ARCHBIT + 1)] |= BIT << (x % (ARCHBIT + 1));
ptr += int_count_o;
}
}
void compute_closure(unsigned long *intent, unsigned long * extent, unsigned long * prev_extent, unsigned long * attr_extent, int * supp)
{
int i, j, k, l;
stats.closures++;
memset(intent, 0xFF, BYTE_COUNT_A);
if (attr_extent)
{
*supp = 0;
for (k = 0; k < int_count_o; k++)
{
extent[k] = prev_extent[k] & attr_extent[k];
if (extent[k])
for (l = 0; l <= ARCHBIT; l++)
{
if (extent[k] >> l)
{
if ((extent[k] >> l) & BIT)
{
(*supp)++;
for (i = 0, j = int_count_a * (k * (ARCHBIT + 1) + l); i < int_count_a; i++, j++)
intent[i] &= context[j];
}
}
else
break;
}
}
}
else
{
memset(extent, 0xFF, BYTE_COUNT_O);
for (j = 0; j < objects; j++)
{
for (i = 0; i < int_count_a; i++)
intent[i] &= context[int_count_a * j + i];
}
}
}