• C#实现Apriori算法(源代码) - [学习动态]

    2007-12-27 | Tag:数据挖掘 Apriori 算法 源代码

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://uestcguagua.blogbus.com/logs/12790785.html

     (由于时间有限,只做了找到所有频繁项集的部分)

    由于复制过来的代码没有缩进和部分缺失等原因,我将这两个文件传到了空间里,有兴趣可以到这里下载:

    http://www.adrive.com/public/1f63e8a59e27d1f1cd95c1e3f190c88b6e18a9db5b0effd7265fcd513820843e.html

    ItemSet.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;

    namespace testApriori1
    {
    public class ItemSet
    {
    private string items;
    private int sup;
    public string Items
    {
    get { return items; }
    set { items = value; }
    }
    public int Sup
    {
    get { return sup; }
    set { sup = value; }
    }
    public ItemSet()//对象初始化
    {
    items = null;
    sup = 0;
    }
    }
    }

    TestApriori.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    using System.Text.RegularExpressions;
    using System.Collections;

    namespace testApriori1
    {
    public class TestApriori
    {
    static void Main(string[] args)
    {
    Console.Write(DateTime.Now);
    ArrayList D = GetEventsFromDB();//事务数据集
    ArrayList I = GetItems1FromDB();//初始项目集合
    float s = 0.01f;//支持度

    List L = new List();//所有频繁项集
    L = Apriori(D, I, s);

    for (int i = 0; i < L.Count; i++)
    {
    Console.WriteLine(L[i].Items);
    Console.WriteLine(L[i].Sup);
    }
    Console.Write(DateTime.Now);
    Console.Read();
    }

    #region-----用Apriori算法进行迭代-----
    ///
    /// 用Apriori算法进行迭代
    ///
    ///
    ///
    ///
    ///
    static List Apriori(ArrayList D,ArrayList I,float sup)
    {
    List L = new List();//所有频繁项集
    if (I.Count == 0) return L;
    else
    {
    int[] Icount = new int[I.Count];//初始项集计数器,初始化为0
    ArrayList Ifrequent = new ArrayList();//初始项集中的频繁项集

    //遍历事务数据集,对项集进行计数
    Regex r=new Regex(",");
    for (int i = 0; i < D.Count; i++)
    {
    string[] subD=r.Split(D[i].ToString());
    for (int j = 0; j < I.Count;j++ )
    {
    string[] subI = r.Split(I[j].ToString());
    bool subIInsubD=true;
    for(int m=0;m
    {
    bool subImInsubD=false;
    for(int n=0;n
    if (subI[m] == subD[n])
    {
    subImInsubD = true;
    continue;
    }
    if(subImInsubD==false) subIInsubD=false;
    }
    if(subIInsubD==true) Icount[j]++;
    }
    }

    //从初始项集中将支持度大于给定值的项转到L中
    for (int i = 0; i < Icount.Length;i++ )
    {
    if (Icount[i] >= sup * D.Count)
    {
    Ifrequent.Add(I[i]);
    ItemSet iSet = new ItemSet();
    iSet.Items=I[i].ToString();
    iSet.Sup = Icount[i];
    L.Add(iSet);
    }
    }

    I.Clear();
    I = AprioriGen(Ifrequent);

    L.AddRange(Apriori(D, I, sup));
    return L;
    }
    }
    #endregion-----用Apriori算法进行迭代-----

    #region-------Apriori-gen生成候选项集---------
    ///
    /// Apriori-gen生成候选项集
    ///
    ///
    ///
    static ArrayList AprioriGen(ArrayList L)
    {
    ArrayList Lk=new ArrayList();
    Regex r=new Regex(",");
    for(int i=0;i
    {
    string[] subL1 = r.Split(L[i].ToString());
    for(int j=i+1;j
    {
    string[] subL2 = r.Split(L[j].ToString());
    //比较L中的两个项集将它们的并集暂存于temp中
    string temp = L[j].ToString();//存储两个项集的并集
    for(int m=0;m
    {
    bool subL1mInsubL2=false;
    for(int n=0;n
    {
    if (subL1[m] == subL2[n]) subL1mInsubL2 = true;
    }
    if (subL1mInsubL2 == false) temp = temp + "," + subL1[m];
    }
    //当temp包含的项为(L中项集的大小)+1并且所求候选项集中没有与temp一样的项集
    string[] subTemp = r.Split(temp);
    if (subTemp.Length == subL1.Length + 1)
    {
    bool isExists = false;
    for (int m = 0; m < Lk.Count; m++)
    {
    bool isContained = true;
    for (int n = 0; n < subTemp.Length; n++)
    {
    if (!Lk[m].ToString().Contains(subTemp[n])) isContained=false;
    }
    if (isContained == true) isExists = true;
    }
    if(isExists==false) Lk.Add(temp);
    }

    }
    }
    return Lk;
    }
    #endregion-------Apriori-gen生成候选项集---------

    #region-------从数据库中得到候选一项集---------
    ///
    /// 从数据库中得到候选一项集
    ///
    ///
    static ArrayList GetItems1FromDB()
    {
    string commandString = "select distinct Model from dbo.vAssocSeqLineItems";
    DataSet ds = ExcuteDataSetByCommandString(commandString);

    int countItems1 = 0;
    countItems1 = ds.Tables[0].Rows.Count;

    ArrayList Items1 = new ArrayList();
    for (int i = 0; i < countItems1; i++)
    Items1.Add(ds.Tables[0].Rows[i]["Model"].ToString());
    return Items1;
    }
    #endregion-------从数据库中得到候选一项集---------

    #region--------从数据库中获得事务集--------
    ///
    /// 从数据库中获得事务集
    ///
    ///
    static ArrayList GetEventsFromDB()
    {
    string commandString="select count(OrderNumber) from vAssocSeqOrders";
    DataSet ds=ExcuteDataSetByCommandString(commandString);
    int countEvent = Convert.ToInt32(ds.Tables[0].Rows[0][0]);//获得事务的数目


    ArrayList events=new ArrayList();
    string temp=null;

    string orderNumber=null;//暂存数据表中的OrderNumber,用来判断是否是同一个Order
    //获得所有的事务
    commandString = "select OrderNumber,Model from vAssocSeqLineItems";
    ds = ExcuteDataSetByCommandString(commandString);

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
    if (orderNumber == null)//第一次读数据
    {
    orderNumber = ds.Tables[0].Rows[i]["OrderNumber"].ToString();
    temp = ds.Tables[0].Rows[i]["Model"].ToString();
    }
    else if (orderNumber == ds.Tables[0].Rows[i]["OrderNumber"].ToString())//读同一个Order中的数据
    {
    temp = temp +","+ ds.Tables[0].Rows[i]["Model"];
    }
    else//读到另一个Order中的数据
    {
    events.Add(temp);
    orderNumber = ds.Tables[0].Rows[i]["OrderNumber"].ToString();
    temp=ds.Tables[0].Rows[i]["Model"].ToString();
    }
    if (i == ds.Tables[0].Rows.Count - 1) events.Add(temp);

    }
    return events;
    }
    #endregion--------从数据库中获得事务集--------

    #region-----由指定的commandString从数据库中获得数据------
    ///
    /// 由指定的commandString从数据库中获得数据
    ///
    ///
    ///
    static DataSet ExcuteDataSetByCommandString(string commandString)
    {
    string connectionString = "server=.;database=AdventureWorksDW;trusted_connection=true";
    SqlConnection sqlCon = new SqlConnection(connectionString);
    sqlCon.Open();

    SqlCommand sqlCmd = new SqlCommand();
    sqlCmd.Connection = sqlCon;
    sqlCmd.CommandText = commandString;

    DataSet ds = new DataSet();
    SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCmd);
    sqlAdapter.Fill(ds);

    sqlCon.Close();
    return ds;
    }
    #endregion-----由指定的commandString从数据库中获得数据------
    }
    }


    历史上的今天:


    收藏到:Del.icio.us




    引用地址:

    评论

  • 后发现程序的问题在于if (Icount[i] >= sup * D.Count),其中sup是float变量,D.count是int变量运算后得出的结果直接参与比较时会出错。后将该句程序改为如下两句:float Result = sup * D.Count;
    if (Icount[i] >= Result)
    问题解决。
    问题虽然解决了,但是还是不知道出现这种问题的原因,希望楼主或者广大网友有知情者大家一起交流,谢谢!
  • 楼主你好,在用的算法是发现 //从初始项集中将支持度大于给定值的项转到L中
    for (int i = 0; i < Icount.Length; i++)
    {
    if (Icount[i] >= sup * D.Count)
    {
    Ifrequent.Add(I[i]);
    ItemSet iSet = new ItemSet();
    iSet.Items = I[i].ToString();
    iSet.Sup = Icount[i];
    L.Add(iSet);
    }
    这一段在判断时, if (Icount[i] >= sup * D.Count),大于的数据能正确,但是等于的数据就被直接过滤掉了,不明白什么原因,望赐教,谢谢!
    以下是我根据你的算法修改的一个测试程序:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Text.RegularExpressions;
    using System.Collections;


    namespace TestApriori
    {
    class TestApriori
    {
    static void Main(string[] args)
    {
    Console.Write(DateTime.Now); //显示当前时间

    ArrayList D = new ArrayList();//事务数据集
    D.Add("A,B,C,D");
    D.Add("B,C,E");
    D.Add("A,B,C,E");
    D.Add("B,D,E");
    D.Add("A,B,C,D");

    ArrayList I = new ArrayList();//初始项目集合
    I.Add("A");
    I.Add("B");
    I.Add("C");
    I.Add("D");
    I.Add("E");

    float s = 0.4f;//支持度

    List<ItemSet> L = new List<ItemSet>();//所有频繁项集 /*************************
    L = Apriori(D, I, s);

    for (int i = 0; i < L.Count; i++) //显示最终结果
    {
    Console.WriteLine(L[i].Items);
    Console.WriteLine(L[i].Sup);
    }
    Console.Write(DateTime.Now);
    Console.Read();
    }

    #region-----用Apriori算法进行迭代-----
    ///
    /// 用Apriori算法进行迭代
    ///
    ///
    ///
    ///
    ///
    static List<ItemSet> Apriori(ArrayList D, ArrayList I, float sup) /************************************/
    {
    List<ItemSet> L = new List<ItemSet>();//所有频繁项集 ///**************************
    if (I.Count == 0) return L;
    else
    {
    int[] Icount = new int[I.Count];//初始项集计数器,初始化为0
    ArrayList Ifrequent = new ArrayList();//初始项集中的频繁项集

    //遍历事务数据集,对项集进行计数
    Regex r = new Regex(",");
    for (int i = 0; i < D.Count; i++)
    {
    string[] subD = r.Split(D[i].ToString()); //将事务数据集转换为字符串数组
    for (int j = 0; j < I.Count; j++)
    {
    string[] subI = r.Split(I[j].ToString()); //将项目集转换为字符串数组
    bool subIInsubD = true;
    for (int m = 0; m < subI.Length; m++) ///***********
    {
    bool subImInsubD = false;
    for (int n = 0; n < subD.Length; n++) /////************
    if (subI[m] == subD[n])
    {
    subImInsubD = true;
    continue;
    }
    if (subImInsubD == false) subIInsubD = false;
    }
    if (subIInsubD == true) Icount[j]++;
    }
    }

    //从初始项集中将支持度大于给定值的项转到L中
    for (int i = 0; i < Icount.Length; i++)
    {
    if (Icount[i] >= sup * D.Count)
    {
    Ifrequent.Add(I[i]);
    ItemSet iSet = new ItemSet();
    iSet.Items = I[i].ToString();
    iSet.Sup = Icount[i];
    L.Add(iSet);
    }
    }

    I.Clear();
    I = AprioriGen(Ifrequent);

    L.AddRange(Apriori(D, I, sup));
    return L;
    }
    }
    #endregion-----用Apriori算法进行迭代-----

    #region-------Apriori-gen生成候选项集---------
    ///
    /// Apriori-gen生成候选项集
    ///
    ///
    ///
    static ArrayList AprioriGen(ArrayList L)
    {
    ArrayList Lk = new ArrayList();
    Regex r = new Regex(",");
    for (int i = 0; i < L.Count; i++) //////*********************
    {
    string[] subL1 = r.Split(L[i].ToString());
    for (int j = i + 1; j < L.Count; j++) //////////+++++++++
    {
    string[] subL2 = r.Split(L[j].ToString());
    //比较L中的两个项集将它们的并集暂存于temp中
    string temp = L[j].ToString();//存储两个项集的并集
    for (int m = 0; m < subL1.Length; m++) ////////////////++++++++++++++++
    {
    bool subL1mInsubL2 = false;
    for (int n = 0; n < subL2.Length; n++) ////////////+++++++++++++++++
    {
    if (subL1[m] == subL2[n]) subL1mInsubL2 = true;
    }
    if (subL1mInsubL2 == false) temp = temp + "," + subL1[m];
    }
    //当temp包含的项为(L中项集的大小)+1并且所求候选项集中没有与temp一样的项集
    string[] subTemp = r.Split(temp);
    if (subTemp.Length == subL1.Length + 1)
    {
    bool isExists = false;
    for (int m = 0; m < Lk.Count; m++)
    {
    bool isContained = true;
    for (int n = 0; n < subTemp.Length; n++)
    {
    if (!Lk[m].ToString().Contains(subTemp[n])) isContained = false;
    }
    if (isContained == true) isExists = true;
    }
    if (isExists == false) Lk.Add(temp);
    }

    }
    }
    return Lk;
    }
    #endregion-------Apriori-gen生成候选项集---------
    }
    }
  • LZ你好,看了你的apriori和k-means算法,想下载下来研究下,可是发现你给的连接无法下载,能否发一份给我,我的邮箱:dc0112@163.com 万分感谢!!
  • 你好,能不能给我一份Apriori基于支持度与置信度的源代码呢,你的这份好像做过修改了,c#语言我学的不好,拜托了,毕设接近尾声了,谢谢~另外能不能告诉我如何在visual studio中实现该算法,跪谢~可以发我邮箱,wangyu19870908@126.com
  • LZ你好,你发的源代码空间显示The file you are trying to access is no longer available publicly.
    能再发一遍么,万分感谢。
    回复wychenshuo说:
    已修改
    2009-05-07 00:05:51
  • lz把数据库文件发一份给我,电脑上SQL 2005装不了,谢谢啊
  • 我的电脑上SQL2005装不起来,什么乱码,不符合最低硬件要求等限制很多
  • lz你好,能否把数据库文件也发一份给我,十分感谢,我的邮箱wanwei120@126.com,QQ是460168975可以加一下认识认识吗,我毕业设计做的就是关于这方面的内容,希望lz可以指导指导,谢谢!
    回复wanwei1209说:
    数据库用的是SQL SERVER 2005的示例数据库,装SQL SERVER 2005的时候选择就有了,adventure work DW
    2009-03-09 00:12:33
  • 请问博主可否将完整的代码发到我邮箱一份呢?非常感谢。:)
    回复琪琪说:
    代码我提供了下载的地址了,可能要把数据库访问的地方改一下,用微软SQL SERVER 2005的示例数据库
    2009-01-03 15:31:46
  • 你好!看到你的关于数据挖掘方面的文章,我是名研究生,毕业论文方向就是这个,有些问题想向你请教!呵呵,盼回复!谢谢!
    回复vicky说:
    不好意思哈,我学得很浅,可能解答不了你的问题哈。。
    2008-12-24 22:23:42
  • 能不能把你的数据库文件也发给我一下啊?谢谢了
  • 我在.net2003下改了几个地方,像List泛型类在.framework 1.1中不支持,但是最终运行出结果很慢,要8分钟多,不知道问题具体是哪里,还是我机子慢的原因.

    using System;
    //using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    using System.Text.RegularExpressions;
    using System.Collections;

    namespace testApriori1
    {
    public class TestApriori
    {
    static void Main(string[] args)
    {
    Console.WriteLine(DateTime.Now);
    ArrayList D = GetEventsFromDB();//事务数据集
    //Console.WriteLine (D[1]);
    ArrayList I = GetItems1FromDB();//初始项目集合
    //Console.WriteLine (I[1]);
    float s = 0.01f;//支持度
    ArrayList F=Apriori(D,I,s);//初始项目集合
    for(int i=0;i<F.Count ;i++)
    Console.WriteLine (F[i].ToString ());
    Console.WriteLine(DateTime.Now);
    Console.Read();
    }
    #region----------Apriori-----------
    static ArrayList Apriori(ArrayList D,ArrayList I,float sup)
    {
    ArrayList L=new ArrayList ();//所有频繁项
    if(I.Count ==0)return L;
    else
    {
    int[] Icount=new int [I.Count ];//初始项集计数器,初始化为0
    ArrayList Ifrequent = new ArrayList ();//初始项集中的频繁项集
    //遍历事务数据集,对项集进行计数
    Regex r=new Regex (",");
    for(int i=0;i<D.Count ;i++)
    {
    string[] subD=r.Split (D[i].ToString ());
    for(int j=0;j<I.Count ;j++)
    {
    string[] subI=r.Split (I[j].ToString ());
    bool subIInsubD=true;
    for(int m=0;m<subI.Length ;m++)
    {
    bool subImInsubD=false;
    for(int n=0;n<subD.Length ;n++)
    if(subI[m]==subD[n])
    {
    subImInsubD=true;
    continue;
    }
    if(subImInsubD==false)subIInsubD=false;
    }
    if(subIInsubD==true)Icount[j]++;
    }
    }
    //初始项集中支持度大于等于最小支持数的项转如L中
    for(int i=0;i<Icount.Length ;i++)
    {
    if(Icount[i]>=sup*D.Count )
    {
    Ifrequent.Add (I[i]);
    L.Add (I[i].ToString ()+":"+Icount[i].ToString ());//频繁项集:支持数
    }
    }

    I.Clear ();
    I=AprioriGen(Ifrequent);
    L.AddRange (Apriori(D,I,sup));
    return L;
    }
    }
    #endregion----------Apriori-----------
    #region----------AprioriGen------------
    static ArrayList AprioriGen(ArrayList L)
    {
    ArrayList Lk=new ArrayList ();
    Regex r=new Regex (",");
    for(int i=0;i<L.Count ;i++)
    {
    string[] subL1=r.Split (L[i].ToString ());
    for(int j=i+1;j<L.Count ;j++)
    {
    string[] subL2=r.Split (L[j].ToString ());
    //比较L中两个项集将它们不并集暂存在temp中
    string temp=L[j].ToString ();
    for(int m=0;m<subL1.Length ;m++)
    {
    bool subL1mInsubL2=false;
    for(int n=0;n<subL2.Length ;n++)
    {
    if(subL1[m]==subL2[m])subL1mInsubL2=true;
    }
    if(subL1mInsubL2==false)temp=temp+","+subL1[m];
    }
    //当temp中包含的项为L中项集大小+1并且所求侯选项集中没有与temp一样的项集
    string[] subTemp=r.Split (temp);
    if(subTemp.Length ==subL1.Length +1)
    {
    bool isExists=false;
    for(int m=0;m<Lk.Count ;m++)
    {
    bool isContained=true;
    for(int n=0;n<subTemp.Length ;n++)
    {
    bool c=false;
    string[] subLkc=r.Split (Lk[m].ToString ());
    for(int p=0;p<subLkc.Length ;p++)
    {
    if(subLkc[p]==subTemp[n])
    c=true;
    }
    if(c==false)
    isContained=false;
    }
    if (isContained == true) isExists = true;
    }
    if(isExists==false) Lk.Add(temp);
    }
    }
    }
    return Lk;
    }
    #endregion----------AprioriGen------------



    #region-------从数据库中得到候选一项集---------
    /// <summary>
    /// 从数据库中得到候选一项集
    /// </summary>
    /// <returns></returns>
    static ArrayList GetItems1FromDB()
    {
    string commandString = "select distinct Model from dbo.vAssocSeqLineItems";
    DataSet ds = ExcuteDataSetByCommandString(commandString);

    int countItems1 = 0;
    countItems1 = ds.Tables[0].Rows.Count;

    ArrayList Items1 = new ArrayList();
    for (int i = 0; i < countItems1; i++)
    Items1.Add(ds.Tables[0].Rows[i]["Model"].ToString());
    return Items1;
    }
    #endregion-------从数据库中得到候选一项集---------

    #region--------从数据库中获得事务集--------
    /// <summary>
    /// 从数据库中获得事务集
    /// </summary>
    /// <returns></returns>
    static ArrayList GetEventsFromDB()
    {
    string commandString="select count(OrderNumber) from vAssocSeqOrders";
    DataSet ds=ExcuteDataSetByCommandString(commandString);
    int countEvent = Convert.ToInt32(ds.Tables[0].Rows[0][0]);//获得事务的数目


    ArrayList events=new ArrayList();
    string temp=null;

    string orderNumber=null;//暂存数据表中的OrderNumber,用来判断是否是同一个Order
    //获得所有的事务
    commandString = "select OrderNumber,Model from vAssocSeqLineItems";
    ds = ExcuteDataSetByCommandString(commandString);

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
    if (orderNumber == null)//第一次读数据
    {
    orderNumber = ds.Tables[0].Rows[i]["OrderNumber"].ToString();
    temp = ds.Tables[0].Rows[i]["Model"].ToString();
    }
    else if (orderNumber == ds.Tables[0].Rows[i]["OrderNumber"].ToString())//读同一个Order中的数据
    {
    temp = temp +","+ ds.Tables[0].Rows[i]["Model"];
    }
    else//读到另一个Order中的数据
    {
    events.Add(temp);
    orderNumber = ds.Tables[0].Rows[i]["OrderNumber"].ToString();
    temp=ds.Tables[0].Rows[i]["Model"].ToString();
    }
    if (i == ds.Tables[0].Rows.Count - 1) events.Add(temp);

    }
    return events;
    }
    #endregion--------从数据库中获得事务集--------

    #region-----由指定的commandString从数据库中获得数据------
    /// <summary>
    /// 由指定的commandString从数据库中获得数据
    /// </summary>
    /// <param name="commandString"></param>
    /// <returns></returns>
    static DataSet ExcuteDataSetByCommandString(string commandString)
    {
    string connectionString = "server=.;database=AdventureWorksDW;trusted_connection=true";
    SqlConnection sqlCon = new SqlConnection(connectionString);
    sqlCon.Open();

    SqlCommand sqlCmd = new SqlCommand();
    sqlCmd.Connection = sqlCon;
    sqlCmd.CommandText = commandString;

    DataSet ds = new DataSet();
    SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCmd);
    sqlAdapter.Fill(ds);

    sqlCon.Close();
    return ds;
    }
    #endregion-----由指定的commandString从数据库中获得数据------
    }
    }
  • 呵呵!那你在用sql 2000设计出那个简单挖掘模型后又做了什么处理呢?
    回复zxl说:
    丢掉。。。
    2008-08-23 10:46:36
  • 谢谢你的回复!
    另外,还想问下:你的这个挖掘算法是对关系数据库中视图的挖掘吧?
    我还看了你设计的简单数据挖掘模型那篇日志,你是在sql 2000 ananlysis services 中做的模型,但在回复别人说你的后续工作的时候,说是在2005下,你是把该模型由2000导入到2005的吗?还有apriori算法可以对数据仓库进行挖掘吗?
    回复zxl说:
    我没有把模型导入,因为那个模型没有足够多的数据来挖掘,因此我选择了sql server 2005的示例数据库adventure work DW,我写的aprior算法也不是基于之前的那个模型的,是针对adventure work DW的,apriori算法可以对数据仓库进行挖掘,但是效率不高,我知道的效率更高的是“频繁树”算法,至于其它的算法我也没有了解过。
    2008-08-23 10:33:06
  • 你这代码是在vs.net 2005下执行的吗?我用的是vs.net2003,数据库是sql server 2000的,现在做的跟你很相像,希望能与你取得联系!
    my qq 215806654
    回复zxl说:
    我用的是vs.net 2005+sql server 2005,两个主要的程序文件都传到空间了,注意一下数据库的访问路径,另外我用的是sql server 2005的示例数据库
    2008-08-20 07:28:08
  • 呵呵,死循环for循环里面的计数器+错了。
  • 我修改后的代码:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;
    using System.Text.RegularExpressions;

    namespace cdi
    {
    public partial class TestApriori : Form
    {
    public DataAccess oDac = new DataAccess("cdidb");
    public TestApriori()
    {
    InitializeComponent();

    }

    #region-----用Apriori算法进行迭代-----

    //用Apriori算法进行迭代
    public List<ItemSet> Apriori(ArrayList D, ArrayList I, float sup)
    {
    List<ItemSet> L = new List<ItemSet>();//所有频繁项集
    if (I.Count == 0)
    {
    return L;
    }
    else
    {
    int[] Icount = new int[I.Count];//初始项集计数器,初始化为0
    ArrayList Ifrequent = new ArrayList();//初始项集中的频繁项集

    //遍历事务数据集,对项集进行计数
    Regex r = new Regex(",");
    for (int i = 0; i < D.Count; i++)
    {
    string[] subD = r.Split(D[i].ToString());
    for (int j = 0; j < I.Count; j++)
    {
    string[] subI = r.Split(I[j].ToString());

    bool subIInsubD = true;

    for (int m = 0; m < subI.Length; m++)
    {
    bool subImInsubD = false;
    for (int n = 0; n < subD.Length; n++)
    {
    if (subI[m] == subD[n])
    {
    subImInsubD = true;
    continue;
    }
    }

    if (!subImInsubD)
    {
    subIInsubD = false;
    }
    }

    if (subIInsubD)
    {
    Icount[j]++;
    }
    }
    }

    //从初始项集中将支持度大于给定值的项转到L中
    for (int i = 0; i < Icount.Length; i++)
    {
    if (Icount[i] >= sup * D.Count)
    {
    Ifrequent.Add(I[i]);
    ItemSet iSet = new ItemSet();
    iSet.Items = I[i].ToString();
    iSet.Sup = Icount[i];
    L.Add(iSet);
    }
    }

    I.Clear();
    I = AprioriGen(Ifrequent);

    L.AddRange(Apriori(D, I, sup));
    return L;
    }
    }
    #endregion-----用Apriori算法进行迭代-----

    #region-------Apriori-gen生成候选项集---------
    ///
    /// Apriori-gen生成候选项集
    ///
    ///
    ///
    static ArrayList AprioriGen(ArrayList L)
    {
    ArrayList Lk = new ArrayList();
    Regex r = new Regex(",");
    for (int i = 0; i < L.Count; i++)
    {
    string[] subL1 = r.Split(L[i].ToString());
    for (int j = i + 1; j < L.Count; i++)
    {
    string[] subL2 = r.Split(L[j].ToString());
    //比较L中的两个项集将它们的并集暂存于temp中
    string temp = L[j].ToString();//存储两个项集的并集
    for (int m = 0; m < subL1.Length; m++)
    {
    bool subL1mInsubL2 = false;
    for (int n = 0; n < subL2.Length; n++)
    {
    if (subL1[m] == subL2[n]) subL1mInsubL2 = true;
    }

    if (!subL1mInsubL2)
    {
    temp = temp + "," + subL1[m];
    }
    }
    //当temp包含的项为(L中项集的大小)+1并且所求候选项集中没有与temp一样的项集
    string[] subTemp = r.Split(temp);
    if (subTemp.Length == subL1.Length + 1)
    {
    bool isExists = false;
    for (int m = 0; m < Lk.Count; m++)
    {
    bool isContained = true;
    for (int n = 0; n < subTemp.Length; n++)
    {
    if (!Lk[m].ToString().Contains(subTemp[n])) isContained = false;
    }
    if (isContained) isExists = true;
    }

    if (!isExists) Lk.Add(temp);
    }
    }
    }
    return Lk;
    }
    #endregion-------Apriori-gen生成候选项集---------

    #region-------从数据库中得到候选一项集---------
    ///
    /// 从数据库中得到候选一项集
    ///
    ///
    public ArrayList GetItems1FromDB()
    {
    DataSet ds = oDac.ExecuteQuery("select distinct i from evt");
    int countItems1 = ds.Tables[0].Rows.Count;
    ArrayList Items1 = new ArrayList();

    for (int i = 0; i < countItems1; i++)
    {
    Items1.Add(ds.Tables[0].Rows[i]["i"].ToString());
    }
    return Items1;
    }
    #endregion-------从数据库中得到候选一项集---------

    #region--------从数据库中获得事务集--------
    ///
    /// 从数据库中获得事务集
    ///
    ///
    public ArrayList GetEventsFromDB()
    {
    DataSet ds = oDac.ExecuteQuery("select count(*) from evt");
    int countEvent = ds.Tables[0].Rows.Count;
    ArrayList events = new ArrayList();
    string temp = null;
    string orderNumber = null;//暂存数据表中的OrderNumber,用来判断是否是同一个Order
    //获得所有的事务
    ds = this.oDac.ExecuteQuery("select t,i FROM evt");

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
    if (orderNumber == null)//第一次读数据
    {
    orderNumber = ds.Tables[0].Rows[i]["t"].ToString();
    temp = ds.Tables[0].Rows[i]["i"].ToString();
    }
    else if (orderNumber == ds.Tables[0].Rows[i]["t"].ToString())//读同一个Order中的数据
    {
    temp = temp + "," + ds.Tables[0].Rows[i]["i"];
    }
    else//读到另一个Order中的数据
    {
    events.Add(temp);
    orderNumber = ds.Tables[0].Rows[i]["t"].ToString();
    temp = ds.Tables[0].Rows[i]["i"].ToString();
    }

    if (i == ds.Tables[0].Rows.Count - 1)
    {
    events.Add(temp);
    }
    }
    return events;
    }
    #endregion--------从数据库中获得事务集--------

    private void button1_Click(object sender, EventArgs e)
    {
    lblStartTime.Text = DateTime.Now.ToString();
    ArrayList D = GetEventsFromDB();//事务数据集
    for (int i = 0; i < D.Count; i++)
    {
    listBox1.Items.Add(D[i]);
    }

    ArrayList I = GetItems1FromDB();//初始项目集合

    for (int i = 0; i < I.Count; i++)
    {
    listBox2.Items.Add(I[i]);
    }


    float s = 0.022f;//支持度
    List<ItemSet> L = new List<ItemSet>();//所有频繁项集
    L = Apriori(D, I, s);
    for (int i = 0; i < L.Count; i++)
    {
    listBox3.Items.Add(L);
    }

    lblEndTime.Text = DateTime.Now.ToString();
    }
    }
    }
  • 这个函数的返回值类型有问题,我感觉应该这样写
    static List<ItemSet> Apriori(ArrayList D,ArrayList I,float sup)
    否则编译都通不过。
    下面也也一样。
  • for(int n=0;n
    这样的语句缺失。我根据下面的语句补齐了,正在运行,但是太慢。23行记录的数据很久没见出来,估计等到明太看看有没有结果。
    回复eclus说:
    我的编译是通过的:)
    我试过用sql server2005的示例数据库Adventure Work DW(从实现上来讲跟官方文档中的频繁项集的示例是一样的),找出所有频繁项集用的时间是60秒,这在在另一篇文档里有说明,由于这个blog没有缩进,所以代码贴上来很难看,真难得你还看得这么仔细:)
    2008-06-07 17:42:25