Apriori算法

/*Apriori算法*/

#include <iostream>

#include <vector>

#include <map>

#include <string>

#include <algorithm>

#include <cmath>

using namespace std;

 

vector<string> T;                   //保存初始输入的事务集

double minSup,minConf;              //用户设定的最小支持度和置信度

map<string,int> mp;                //保存项目集中每个元素在事务集中出现的次数

vector< vector<string> >F;       //存放频繁项目集

vector<string> R;                 //存放关联规则

 

 

void initTransactionSet()       //获取事务集

{

   int n;

   cout<<"请输入事务集的个数:"<<endl;

   cin>>n;

   getchar();

   cout<<"请输入事务集:"<<endl;

   while(n--)

    {

       string str;

       getline(cin,str);          //输入的事务集中每个元素以空格隔开,并且只能输入数字

        T.push_back(str);

    }

   cout<<"请输入最小支持度和置信度:"<<endl;      //支持度和置信度为小数表示形式

   cin>>minSup>>minConf;

}

 

 

vector<string> split(string str,charch)

{

   vector<string> v;

   int i,j;

   i=0;

   while(i<str.size())

    {

       if(str[i]==ch)

           i++;

       else

       {

           j=i;

           while(j<str.size())

           {

                if(str[j]!=ch)

                    j++;

                else

                    break;

           }

           string temp=str.substr(i,j-i);

           v.push_back(temp);

           i=j+1;

       }

    }

   return v;

}

 

void genarateOneFrequenceSet()          //生成1-频繁项目集

{

   int i,j;

   vector<string> f;                //存储1-频繁项目集

    for(i=0;i<T.size();i++)

    {

       string t = T[i];

       vector<string> v=split(t,' ');       //将输入的事务集进行切分,如输入1 2 3,切分得到"1","2","3"

       for(j=0;j<v.size();j++)            //统计每个元素出现的次数,注意map默认按照key的升序排序

        {

           mp[v[j]]++;            

       }

    }

   

   for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++)    //剔除不满足最小支持度要求的项集

   {   

       if( (*it).second >= minSup*T.size())

       {

           f.push_back((*it).first);

       }

    }

   F.push_back(T);                 //方便用F[1]表示1-频繁项目集

   if(f.size()!=0)

    {

       F.push_back(f);                 

    }

}

 

bool judgeItem(vector<string>v1,vector<string> v2) //判断v1和v2是否只有最后一项不同

{

   int i,j;

   i=0;

   j=0;

   while(i<v1.size()-1&&j<v2.size()-1)

    {

       if(v1[i]!=v2[j])

           return false;

        i++;

       j++;

    }

   return true;

}

 

bool judgeSubset(vector<string>v,vector<string> f)        //判断v的所有k-1子集是否在f中

{

   int i,j;

   bool flag=true;

   for(i=0;i<v.size();i++)

    {

       string str;

       for(j=0;j<v.size();j++)

       {

           if(j!=i)

                str+=v[j]+" ";

       }

       str=str.substr(0,str.size()-1);

       vector<string>::iterator it=find(f.begin(),f.end(),str);

       if(it==f.end())

           flag=false;

    }

   return flag;

}

 

int calculateSupportCount(vector<string>v)      //计算支持度计数

{

   int i,j;

   int count=0;

   for(i=0;i<T.size();i++)

    {

       vector<string> t=split(T[i],' ');

       for(j=0;j<v.size();j++)

       {

           vector<string>::iterator it=find(t.begin(),t.end(),v[j]);

           if(it==t.end())

                break;

       }

       if(j==v.size())

           count++;

    }

   return count;   

}

 

 

bool judgeSupport(vector<string>v)                  //判断一个项集的支持度是否满足要求

{

   int count=calculateSupportCount(v);

   if(count >= ceil(minSup*T.size()))

       return true;

   return false;

}

 

 

void generateKFrequenceSet()        //生成k-频繁项目集

{

   int k;

   for(k=2;k<=mp.size();k++)

    {

       if(F.size()< k)           //如果Fk-1为空,则退出

           break;

       else                      //根据Fk-1生成Ck候选项集   

       {               

           int i,j;

           vector<string> c;

           vector<string> f=F[k-1];

           for(i=0;i<f.size()-1;i++)

           {

                vector<string>v1=split(f[i],' ');

                for(j=i+1;j<f.size();j++)

                {

                    vector<string>v2=split(f[j],' ');

                    if(judgeItem(v1,v2))       //如果v1和v2只有最后一项不同,则进行连接

                    {

                        vector<string>tempVector=v1;

                       tempVector.push_back(v2[v2.size()-1]);

                       sort(tempVector.begin(),tempVector.end());     //对元素排序,方便判断是否进行连接

                                       

                            //剪枝的过程

                            //判断 v1的(k-1)的子集是否都在Fk-1中以及是否满足最低支持度

                           if(judgeSubset(tempVector,f)&&judgeSupport(tempVector)) 

                        {

                            int p;

                           string tempStr;

                           for(p=0;p<tempVector.size()-1;p++)

                               tempStr+=tempVector[p]+" ";

                           tempStr+=tempVector[p];

       

                            c.push_back(tempStr);

                        }

                    }

                }

           }

           if(c.size()!=0)

                F.push_back(c);

       }

    }

}

 

 

 

vector<string>removeItemFromSet(vector<string> v1,vector<string> v2)    //从v1中剔除v2

{

   int i;

   vector<string> result=v1;

   for(i=0;i<v2.size();i++)

    {

       vector<string>::iterator it=find(result.begin(),result.end(),v2[i]);

       if(it!=result.end())

           result.erase(it);

    }

   return result;

}

 

string getStr(vector<string>v1,vector<string> v2)        //根据前件和后件得到规则

{

   int i;

   string rStr;

   for(i=0;i<v1.size();i++)

       rStr+=v1[i]+" ";

   rStr=rStr.substr(0,rStr.size()-1);

   rStr+="->";

   

   for(i=0;i<v2.size();i++)

       rStr+=v2[i]+" ";

   rStr=rStr.substr(0,rStr.size()-1);

   return rStr;   

}

 

void ap_generateRules(string fs)

{

   int i,j,k;

   vector<string> v=split(fs,' ');

   vector<string> h;                          

   vector< vector<string> > H;                   //存放所有的后件

   int fCount=calculateSupportCount(v);         //f的支持度计数

    

   for(i=0;i<v.size();i++)                    //先生成1-后件关联规则

    {

       vector<string> temp=v;

       temp.erase(temp.begin()+i);

       

       int aCount=calculateSupportCount(temp);

       

       if( fCount >= ceil(aCount*minConf))        //如果满足置信度要求

        {

           h.push_back(v[i]);

           string tempStr;

           for(j=0;j<v.size();j++)

           {

                if(j!=i)

                   tempStr+=v[j]+"";

           }

           tempStr=tempStr.substr(0,tempStr.size()-1);

           tempStr+="->"+v[i];

           R.push_back((tempStr));

       }

    }

   

   H.push_back(v);

   if(h.size()!=0)

       H.push_back(h);

       

   for(k=2;k<v.size();k++)             //生成k-后件关联规则

    {

       h=H[k-1];

       vector<string> addH;

       for(i=0;i<h.size()-1;i++)

       {

           vector<string> v1=split(h[i],' ');

           for(j=i+1;j<h.size();j++)

           {

                vector<string>v2=split(h[j],' ');

           

                if(judgeItem(v1,v2))

                {

                    vector<string>tempVector=v1;                   

                   tempVector.push_back(v2[v2.size()-1]);                       //得到后件集合

                      sort(tempVector.begin(),tempVector.end());

                   

                    vector<string>filterV=removeItemFromSet(v,tempVector);     //得到前件集合

                       int aCount=calculateSupportCount(filterV);                   //计算前件支持度计数

                       if(fCount >=ceil(aCount*minConf))                          //如果满足置信度要求

                       {

                        stringrStr=getStr(filterV,tempVector);                  //根据前件和后件得到规则

                       

                            string hStr;

                        for(ints=0;s<tempVector.size();s++) 

                           hStr+=tempVector[s]+" ";

                       hStr=hStr.substr(0,hStr.size()-1);

                        addH.push_back(hStr);                                    //得到一个新的后件集合

                       

                            R.push_back(rStr);

                    }

                }

           }

       }

       if(addH.size()!=0)                                                       //将所有的k-后件集合加入到H中

           H.push_back(addH);

    }

}

 

 

void generateRules()               //生成关联规则

{

   int i,j,k;

   for(k=2;k<F.size();k++)

    {

       vector<string> f=F[k];

       for(i=0;i<f.size();i++)

       {

           string str=f[i];

           ap_generateRules(str);

       }

   }   

}

 

 

void outputFrequenceSet()          //输出频繁项目集

{

   int i,k;

   if(F.size()==1)

    {

       cout<<"无频繁项目集!"<<endl;

       return;

   }   

   for(k=1;k<F.size();k++)

    {

       cout<<k<<"-频繁项目集:"<<endl;

       vector<string> f=F[k];

       for(i=0;i<f.size();i++)

           cout<<f[i]<<endl;

    }

}

 

void outputRules()              //输出关联规则

{

   int i;

   cout<<"关联规则:"<<endl;

   for(i=0;i<R.size();i++)

    {

       cout<<R[i]<<endl;

    }

}

 

void Apriori()

{

   initTransactionSet();

   genarateOneFrequenceSet();

   generateKFrequenceSet();

   outputFrequenceSet();

   generateRules();

   outputRules();

}

 

 

int main(int argc, char *argv[])

{

   Apriori();

   return 0;

}

 

测试数据:

7

1 2 3

1 4

4 5

1 2 4

1 2 6 4 3

2 6 3

2 3 6

0.3 0.8

运行结果:

1-频繁项目集:
1
2
3
4
6
2-频繁项目集:
1 2
1 4
2 3
2 6
3 6
3-频繁项目集:
2 3 6
关联规则:
3->2
2->3
6->2
6->3
3 6->2
2 6->3
6->2 3

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值