import java.io.*;
import java.util.*;
public class Apriori {
static String filePath = "d:\\3.txt";
static ArrayList<ArrayList<Integer>> D = new ArrayList<ArrayList<Integer>>();// 事务数据库
//static HashSet<HashSet<Integer>> D_side = new HashSet<HashSet<Integer>>();
static HashMap<ArrayList<Integer>, Double> C = new HashMap<ArrayList<Integer>, Double>();// 项目集
static HashMap<ArrayList<Integer>, Double> L = new HashMap<ArrayList<Integer>, Double>();// 候选集
static int D_size = 0;
static double min_support =0.01;// 最小支持度
//static double min_confident = 0.1;// 最小置信度
static HashMap<ArrayList<Integer>, Double> L_ALL = new HashMap<ArrayList<Integer>, Double>();//存储所有频繁集合
static int sum = 0;
/*public static boolean containsAll_Set_List(HashSet<Integer> c,HashSet<Integer> e) {
for (Integer m : e) {
if (!c.contains(m))
return false;
}
return true;
}*/
public static ArrayList<ArrayList<Integer>> getSubsett(ArrayList<Integer> L) {
if (L.size() > 0) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < Math.pow(2, L.size()); i++) {// 集合子集个数=2的该集合长度的乘方
ArrayList<Integer> subSet = new ArrayList<Integer>();
int index = i;// 索引从0一直到2的集合长度的乘方-1
for (int j = 0; j < L.size(); j++) {
// 通过逐一位移,判断索引那一位是1,如果是,再添加此项
if ((index & 1) == 1) {// 位与运算,判断最后一位是否为1
subSet.add(L.get(j));
}
index >>= 1;// 索引右移一位
}
result.add(subSet); // 把子集存储起来
}
result.remove(L);
return result;
} else {
return null;
}
}
//排序函数
/*Comparator<ArrayList<Integer>> myComparator = new Comparator<ArrayList<Integer>>() {
@Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
Collections.sort(o1);
Collections.sort(o2);
int leng = 1;
while(leng<=o1.size()&&leng<=o2.size()) {
if(o1.get(leng-1)-o2.get(leng-1)!=0) {
return o1.get(leng-1)-o2.get(leng-1);
}else {
leng++;
}
}
if((leng-1)==o1.size()&&(leng-1)==o2.size()) {
return 0;
}
else {
return o1.size()-o2.size();
}
}
};*/
//所有子集
public static ArrayList<ArrayList<Integer>> getSubset(ArrayList<Integer> L) {
if (L.size() > 0) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < Math.pow(2, L.size()); i++) {// 集合子集个数=2的该集合长度的乘方
ArrayList<Integer> subSet = new ArrayList<Integer>();
int index = i;// 索引从0一直到2的集合长度的乘方-1
for (int j = 0; j < L.size(); j++) {
// 通过逐一位移,判断索引那一位是1,如果是,再添加此项
if ((index & 1) == 1) {// 位与运算,判断最后一位是否为1
subSet.add(L.get(j));
}
index >>= 1;// 索引右移一位
}
result.add(subSet); // 把子集存储起来
}
result.remove(L);
return result;
} else {
return null;
}
}
//判断子集是否频繁
public static boolean IF_Son(ArrayList<ArrayList<Integer>> k) {
ArrayList<Integer> sub = new ArrayList<Integer>();
k.remove(sub);
boolean flagg = true;
for(ArrayList<Integer> te : k) {
if(!L_ALL.keySet().contains(te)) {
flagg = false;
break;
}
}
return flagg;
}
//判等函数
public static boolean Comparex (int t,ArrayList<Integer> k1,ArrayList<Integer> k2) {
boolean flag = true;
for(int i=0;i<t-1;i++) {
if(k1.get(i)!=k2.get(i)) {
flag = false;
break;
}
}
return flag;
}
// 两个整数集求并集
public static ArrayList<Integer> arrayListUnion( ArrayList<Integer> arraylist1, ArrayList<Integer> arraylist2) {
ArrayList<Integer> arraylist = new ArrayList<Integer>();
arraylist.addAll(arraylist1);
arraylist.addAll(arraylist2);
arraylist = new ArrayList<Integer>(new HashSet<Integer>(arraylist));
return arraylist;
}
// 剪枝,删去C少于最小支持度的元素,形成L
public static void pruning(HashMap<ArrayList<Integer>, Double> C, HashMap<ArrayList<Integer>, Double> L) {
L.clear();
// 根据项目集生成候选集
L.putAll(C);
// 删除少于最小支持度的元素
ArrayList<ArrayList<Integer>> temp_delete = new ArrayList<ArrayList<Integer>>(L.keySet());
for(int i=0;i<temp_delete.size();i++) {
if(L.get(temp_delete.get(i))<min_support)
L.remove(temp_delete.get(i));
}
System.out.println(L.size());
System.out.println("Arrive3");
L_ALL.putAll(L);
//System.out.println(L.size());
/*if(L.size()!=0) {
for(int i=D.size()-1;i>=0;i--) {
boolean fla = true;
ArrayList<ArrayList<Integer>> yy = new ArrayList<ArrayList<Integer>>(L.keySet());
for(int j=0;j<yy.size();j++) {
if(D.get(i).containsAll(yy.get(j))) {
fla = false;break;
}
}
if(fla==true) D.remove(i);
}
}*/
}
//循环求Lk(K>=2)的频繁项集并返回
public static HashMap<ArrayList<Integer>, Double> iteration( HashMap<ArrayList<Integer>, Double> C,HashMap<ArrayList<Integer>, Double> L) {
HashMap<ArrayList<Integer>, Double> L_temp = new HashMap<ArrayList<Integer>, Double>();// 用于判断是否结束剪枝的临时变量
int t = 1;// 迭代次数
while (L.size() > 0) {// 一旦被剪枝后剪干净,剪枝之前则是最终要求的结果。
t++;
L_temp.clear();
L_temp.putAll(L);
// 一、连接步
C.clear();
// 1.将L中的项以一定的规则两两匹配
ArrayList<ArrayList<Integer>> L_key = new ArrayList<ArrayList<Integer>>(L.keySet());
System.out.println("Arrive1");
Collections.sort(L_key,new Comparator<ArrayList<Integer>>() {//进行排序
@Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
int leng = 1;
while(leng<=o1.size()&&leng<=o2.size()) {
if(o1.get(leng-1)-o2.get(leng-1)!=0) {
return o1.get(leng-1)-o2.get(leng-1);
}else {
leng++;
}
}
if((leng-1)==o1.size()&&(leng-1)==o2.size()) {
return 0;
}
else {
return o1.size()-o2.size();
}
}
});
//System.out.println(L_key);
for (int i = 0; i < L_key.size(); i++) {
for (int j = i + 1; j < L_key.size(); j++) {
if(Comparex(t-1, L_key.get(i), L_key.get(j))) {
ArrayList<Integer> C_item = new ArrayList<Integer>();
C_item = new ArrayList<Integer>(arrayListUnion(L_key.get(i),L_key.get(j)));
//if (C_item.size() == t) {
C.put(C_item, 0.0);// 频繁项集的所有非空子集都必须是频繁的
//}
}else break;
}
}System.out.println("Arrive4");
//修剪
ArrayList<ArrayList<Integer>> temp_L = new ArrayList<ArrayList<Integer>>(C.keySet());
for(int i=0;i<temp_L.size();i++) {
if(!IF_Son(getSubset(temp_L.get(i)))) {
C.remove(temp_L.get(i));
}
}
System.out.println("Arrive5");
// 2.通过扫描D,计算此项的支持度
for (ArrayList<Integer> key : C.keySet()) {
for (int i = 0; i < D.size(); i++) {
//HashSet<Integer> pp1 = new HashSet<Integer>(D.get(i));
//HashSet<Integer> pp2 = new HashSet<Integer>(key);
//if (pp1.containsAll(pp2)) {
//if(containsAll_Set_List(new HashSet<Integer>(D.get(i)), new HashSet<Integer>(key))) {
if(D.get(i).containsAll(key)) {
C.put(key, C.get(key) + 1.0 / D_size);
}
}
}
System.out.println("Arrive6");
// System.out.println(C);
// 二、剪枝步
pruning(C, L);
// System.out.println(L);
// System.out.println("===");
}
return L_temp;
}
public static void main(String[] args) {
ArrayList<ArrayList<String>> T = new ArrayList<ArrayList<String>>();
try {
Scanner scanner = new Scanner(new File(filePath)); //指定读入文件
while(scanner.hasNext()) {
T.add(new ArrayList<String>(Arrays.asList(scanner.nextLine().split(" "))));
}
scanner.close();
}catch (FileNotFoundException e) {
// TODO: handle exception
System.out.println("文件不存在,请重新输入");
}
int num ;
for(int i=0;i<T.size();i++) {
ArrayList<Integer> te= new ArrayList<Integer>();
for(int j=0;j<T.get(i).size();j++) {
num = Integer.valueOf(T.get(i).get(j));
te.add(num);
}
D.add(new ArrayList<Integer>(te));
te.clear();
}long start=System.currentTimeMillis();
/* int mxaa=-1;int ii=0;int jj=0;
for(int i=0;i<D.size();i++) {
for(int j=0;j<D.get(i).size();j++) {
if(D.get(i).get(j)>mxaa) {mxaa=D.get(i).get(j);
ii=i;jj=j;
}
}
}System.out.print(mxaa+" "+ii+" "+jj);*/
D_size = D.size();
// 扫描事务数据库。生成项目集,支持度=改元素在事务数据库出现的次数/事务数据库的事务数
for (int i = 0; i < D.size(); i++) {
for (int j = 0; j < D.get(i).size(); j++) {
int e = D.get(i).get(j) ;
ArrayList<Integer> item = new ArrayList<Integer>(Arrays.asList(e));
if (!C.containsKey(item)) {
C.put(item, 1.0 / D_size);
} else {
C.put(item, C.get(item) + 1.0 / D_size);
}
}
}
pruning(C, L);// 剪枝
/*
* System.out.println(D); System.out.println(C); System.out.println(L);
* System.out.println("===");
*/
L = iteration(C, L);
//System.out.println(L_ALL);
System.out.println("频繁项集总数:"+L_ALL.size());
//System.out.println("===");
long end=System.currentTimeMillis();
System.out.println("程序运行时间: "+(end-start)+"ms");
}
}
Apriori频繁模式挖掘算法
于 2021-11-13 16:13:55 首次发布