There are command buttons:
item textbox
min textbox
max textbox
Add Item
Delete Item
Add Transaction
Edit Transaction
Delete Transaction
Clear All Transactions
and Solve cmd button.
Besides is are 2 Listbox for for item the other for transactions.
By default there are four items in the 1st list box (a,b,c,d).
If u recall u helped in modifying the Add item event to accept both alphabets and numerals from this method:
" private void txt_Item_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsLetterOrDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back;
}"
Normally if u select any two items randomly and click add transaction, the items would immediately be listed in the transaction listbox. So on entering say 50% and 80% respectively in the lower textboxes called min and max and click solve, the algorithm would then generate some frequencies of itemsets based on a transaction. Thats all.
The problem Im faced with now is where the index is overflowing. You were quite right by indicating that one of the methods is recalling itself. The question now is how can I stop it from doing so. so that the indexed items greater than 3 such as CSC444, CSC555, CSC222 can be transacted with? Below is a summary of the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Apriori
{
public partial class frmMain : Form
{
#region Global Variables
Dictionary
Dictionary
int m_nLastTransId = 1;
#endregion
public frmMain()
{
InitializeComponent();
}
private void btn_AddItem_Click(object sender, EventArgs e)
{
if (ValidateInput(txt_Item, false))
{
string strNewItem = txt_Item.Text;
foreach (ListViewItem lvItem in lv_Items.Items)
{
if (lvItem.Text == strNewItem)
{
MessageBox.Show("Item (" + strNewItem + ") already exists", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
txt_Item.Text = string.Empty;
return;
}
}
lv_Items.Items.Add(strNewItem);
txt_Item.Text = string.Empty;
}
}
private void btn_DeleteItem_Click(object sender, EventArgs e)
{
if (lv_Items.CheckedItems.Count > 0)
{
for (int i = lv_Items.CheckedItems.Count - 1; i >= 0; i--)
{
List
string strItemtoDelete = lv_Items.CheckedItems[i].ToString();
if (ItemIsRemovable(strItemtoDelete, ref lst_Transactions))
{
lv_Items.Items.Remove(lv_Items.CheckedItems[i]);
}
else
{
string strTransactions = string.Empty;
foreach (int nTransactionId in lst_Transactions)
{
strTransactions += nTransactionId.ToString() + ",";
}
strTransactions = strTransactions.Remove(strTransactions.Length - 1);
MessageBox.Show("Can not delete item " + strItemtoDelete + ", item exists in transactions " + strTransactions, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
else
MessageBox.Show("please choose items to add", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
private bool ValidateInput(TextBox txtBox, bool bIsNumber)
{
if (txtBox.Text.Length == 0)
{
errorProvider1.SetError(txtBox, "please enter value");
return false;
}
else
{
if (bIsNumber && int.Parse(txtBox.Text) > 100)
{
errorProvider1.SetError(txtBox, "please enter value between 0 and 100");
return false;
}
else
{
errorProvider1.SetError(txtBox, "");
return true;
}
}
}
private void btn_AddTrans_Click(object sender, EventArgs e)
{
if (lv_Items.CheckedItems.Count <= 0)
{
MessageBox.Show("please choose items to add", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
string strTransactiondic;
string strTransactionLV = GetTransactionFromListView(out strTransactiondic);
ListViewItem lvi = new ListViewItem(m_nLastTransId.ToString());
lvi.Tag = m_nLastTransId;
lvi.SubItems.Add(strTransactionLV);
lv_Transactions.Items.Add(lvi);
m_dicTransactions.Add(m_nLastTransId, strTransactiondic);
m_nLastTransId++;
}
private void btn_EditTrans_Click(object sender, EventArgs e)
{
int nChosenTransactions = lv_Transactions.CheckedItems.Count;
if (nChosenTransactions > 1 || nChosenTransactions == 0)
{
MessageBox.Show("please choose one transaction to modify", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
EnableControls(false);
int nTransId = (int)lv_Transactions.CheckedItems[0].Tag;
string strTransaction = m_dicTransactions[nTransId];
foreach (ListViewItem lvi in lv_Items.Items)
{
lvi.Checked = false;
}
foreach (char cItem in strTransaction)
{
for (int i = 0; i < lv_Items.Items.Count; i++)
{
if (lv_Items.Items[i].Text == cItem.ToString())
{
lv_Items.Items[i].Checked = true;
}
}
}
}
private void btn_EndEdit_Click(object sender, EventArgs e)
{
EnableControls(true);
int nTransId = (int)lv_Transactions.CheckedItems[0].Tag;
string strTransactiondic;
string strTransactionLV = GetTransactionFromListView(out strTransactiondic);
m_dicTransactions[nTransId] = strTransactiondic;
ListViewItem lvi = lv_Transactions.CheckedItems[0];
lvi.SubItems.Clear();
lvi.SubItems[0].Text = nTransId.ToString();
lvi.SubItems.Add(strTransactionLV);
}
private void btn_DeleteTrans_Click(object sender, EventArgs e)
{
int nChosenTransactions = lv_Transactions.CheckedItems.Count;
if (nChosenTransactions < 1)
{
MessageBox.Show("please choose at least one transaction to delete", "Alert", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
for (int i = 0; i < lv_Transactions.CheckedItems.Count; i++)
{
m_dicTransactions.Remove((int)lv_Transactions.CheckedItems[i].Tag);
lv_Transactions.Items.Remove(lv_Transactions.CheckedItems[i]);
}
}
private void btn_ClearTransactions_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Clear All Transactions ?", "Apriori", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)
{
m_nLastTransId = 1;
lv_Transactions.Items.Clear();
m_dicTransactions.Clear();
}
}
private void btn_Solve_Click(object sender, EventArgs e)
{
#region validation
if (!ValidateInput(txt_Support, true) || !ValidateInput(txt_Confidence, true))
{
return;
}
if (lv_Transactions.Items.Count <= 0)
{
MessageBox.Show("Enter Transactions first", "Apriori", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
#endregion
Solve();
}
private void txt_Confidence_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back;
}
private void txt_Item_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsLetterOrDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back;
}
private string GetTransactionFromListView(out string strTransactiondic)
{
strTransactiondic = string.Empty;
string strTransactionReturn = string.Empty;
foreach (ListViewItem lviCheckedItem in lv_Items.CheckedItems)
{
strTransactiondic += lviCheckedItem.Text;
strTransactionReturn += lviCheckedItem.Text + ",";
}
strTransactionReturn = strTransactionReturn.Remove(strTransactionReturn.Length - 1);
return strTransactionReturn;
}
private void Solve()
{
double dMinSupport = double.Parse(txt_Support.Text) / 100;
double dMinConfidence = double.Parse(txt_Confidence.Text) / 100;
////Scan the transaction database to get the support S of each 1-itemset,
Dictionary
Dictionary
Dictionary
do
{
dic_Candidates = GenerateCandidates(dic_FrequentItems);
dic_FrequentItems = GetFrequentItems(dic_Candidates, dMinSupport);
}
while (dic_Candidates.Count != 0);
Dictionary
List
List
List
frmOutput objfrmOutput = new frmOutput(m_dicAllFrequentItems,
dicClosedItemSets,
lstMaximalItemSets,
lstStrongRules);
objfrmOutput.ShowDialog();
}
private Dictionary
{
Dictionary
Dictionary
for (int i = 0; i < m_dicAllFrequentItems.Count; i++)
{
string strChild = m_dicAllFrequentItems.Keys.ElementAt(i);
dicParents = GetItemParents(strChild, i + 1);
if (IsClosed(strChild, dicParents))
dicClosedItemSetsReturn.Add(strChild, dicParents);
}
return dicClosedItemSetsReturn;
}
private List
{
List
Dictionary
foreach (string strItem in dicClosedItemSets.Keys)
{
dicParents = dicClosedItemSets[strItem];
if (dicParents.Count == 0)
lstMaximalItemSetsReturn.Add(strItem);
}
return lstMaximalItemSetsReturn;
}
private bool IsClosed(string strChild, Dictionary
{
foreach (string strParent in dicParents.Keys)
{
if (m_dicAllFrequentItems[strChild] == m_dicAllFrequentItems[strParent])
{
return false;
}
}
return true;
}
private Dictionary
{
Dictionary
for (int j = nIndex; j < m_dicAllFrequentItems.Count; j++)
{
string strParent = m_dicAllFrequentItems.Keys.ElementAt(j);
if (strParent.Length == strChild.Length + 1)
{
if (IsSubstring(strChild, strParent))
{
dicParents.Add(strParent, m_dicAllFrequentItems[strParent]);
}
}
}
return dicParents;
}
private List
{
List
foreach (clssRules Rule in lstRules)
{
string strXY = Alphabetize(Rule.X + Rule.Y);
AddStrongRule(Rule, strXY, ref lstStrongRulesReturn, dMinConfidence);
}
lstStrongRulesReturn.Sort();
return lstStrongRulesReturn;
}
private void AddStrongRule(clssRules Rule, string strXY, ref List
{
double dConfidence = GetConfidence(Rule.X, strXY);
clssRules NewRule;
if (dConfidence >= dMinConfidence)
{
NewRule = new clssRules(Rule.X, Rule.Y, dConfidence);
lstStrongRulesReturn.Add(NewRule);
}
dConfidence = GetConfidence(Rule.Y, strXY);
if (dConfidence >= dMinConfidence)
{
NewRule = new clssRules(Rule.Y, Rule.X, dConfidence);
lstStrongRulesReturn.Add(NewRule);
}
}
private double GetConfidence(string strX, string strXY)
{
double dSupport_X, dSupport_XY;
dSupport_X = m_dicAllFrequentItems[strX];
dSupport_XY = m_dicAllFrequentItems[strXY];
return dSupport_XY / dSupport_X;
}
private List
{
List
foreach (string strItem in m_dicAllFrequentItems.Keys)
{
if (strItem.Length > 1)
{
int nMaxCombinationLength = strItem.Length / 2;
GenerateCombination(strItem, nMaxCombinationLength, ref lstRulesReturn);
}
}
return lstRulesReturn;
}
private void GenerateCombination(string strItem, int nCombinationLength, ref List
{
int nItemLength = strItem.Length;
if (nItemLength == 2)
{
AddItem(strItem[0].ToString(), strItem, ref lstRulesReturn);
return;
}
else if (nItemLength == 3)
{
for (int i = 0; i < nItemLength; i++)
{
AddItem(strItem[i].ToString(), strItem, ref lstRulesReturn);
}
return;
}
else
{
for (int i = 0; i < nItemLength; i++)
{
GetCombinationRecursive(strItem[i].ToString(), strItem, nCombinationLength, ref lstRulesReturn);
}
}
}
private void AddItem(string strCombination, string strItem, ref List
{
string strRemaining = GetRemaining(strCombination, strItem);
clssRules Rule = new clssRules(strCombination, strRemaining, 0);
lstRulesReturn.Add(Rule);
}
private string GetCombinationRecursive(string strCombination, string strItem, int nCombinationLength, ref List
{
AddItem(strCombination, strItem, ref lstRulesReturn);
char cLastTokenCharacter = strCombination[strCombination.Length - 1];
int nLastTokenCharcaterIndex = strCombination.IndexOf(cLastTokenCharacter);
int nLastTokenCharcaterIndexInParent = strItem.IndexOf(cLastTokenCharacter);
char cNextCharacter;
char cLastItemCharacter = strItem[strItem.Length - 1];
if (strCombination.Length == nCombinationLength)
{
if (cLastTokenCharacter != cLastItemCharacter)
{
strCombination = strCombination.Remove(nLastTokenCharcaterIndex, 1);
cNextCharacter = strItem[nLastTokenCharcaterIndexInParent + 1];
string strNewToken = strCombination + cNextCharacter;
return (GetCombinationRecursive(strNewToken, strItem, nCombinationLength, ref lstRulesReturn));
}
else
{
return string.Empty;
}
}
else
{
if (strCombination != cLastItemCharacter.ToString())
{
cNextCharacter = strItem[nLastTokenCharcaterIndexInParent + 1];
string strNewToken = strCombination + cNextCharacter;
return (GetCombinationRecursive(strNewToken, strItem, nCombinationLength, ref lstRulesReturn));
}
else
{
return string.Empty;
}
}
}
private string GetRemaining(string strChild, string strParent)
{
for (int i = 0; i < strChild.Length; i++)
{
int nIndex = strParent.IndexOf(strChild[i]);
strParent = strParent.Remove(nIndex, 1);
}
return strParent;
}
private Dictionary
{
Dictionary
for (int i = dic_Candidates.Count - 1; i >= 0; i--)
{
string strItem = dic_Candidates.Keys.ElementAt(i);
double dSupport = dic_Candidates[strItem];
if ((dSupport / (double)(m_nLastTransId - 1) >= dMinSupport))
{
dic_FrequentReturn.Add(strItem, dSupport);
m_dicAllFrequentItems.Add(strItem, dSupport);
}
}
return dic_FrequentReturn;
}
private Dictionary
{
Dictionary
for (int i = 0; i < dic_FrequentItems.Count - 1; i++)
{
string strFirstItem = Alphabetize(dic_FrequentItems.Keys.ElementAt(i));
for (int j = i + 1; j < dic_FrequentItems.Count; j++)
{
string strSecondItem = Alphabetize(dic_FrequentItems.Keys.ElementAt(j));
string strGeneratedCandidate = GetCandidate(strFirstItem, strSecondItem);
if (strGeneratedCandidate != string.Empty)
{
strGeneratedCandidate = Alphabetize(strGeneratedCandidate);
double dSupport = GetSupport(strGeneratedCandidate);
dic_CandidatesReturn.Add(strGeneratedCandidate, dSupport);
}
}
}
return dic_CandidatesReturn;
}
private string Alphabetize(string strToken)
{
// Convert to char array, then sort and return
char[] arrToken = strToken.ToCharArray();
Array.Sort(arrToken);
return new string(arrToken);
}
private double GetSupport(string strGeneratedCandidate)
{
double dSupportReturn = 0;
foreach (string strTransaction in m_dicTransactions.Values)
{
if (IsSubstring(strGeneratedCandidate, strTransaction))
{
dSupportReturn++;
}
}
return dSupportReturn;
}
private bool IsSubstring(string strChild, string strParent)
{
foreach (char c in strChild)
{
if (!strParent.Contains(c))
{
return false;
}
}
return true;
}
private string GetCandidate(string strFirstItem, string strSecondItem)
{
int nLength = strFirstItem.Length;
if (nLength == 1)
{
return strFirstItem + strSecondItem;
}
else
{
string strFirstSubString = strFirstItem.Substring(0, nLength - 1);
string strSecondSubString = strSecondItem.Substring(0, nLength - 1);
if (strFirstSubString == strSecondSubString)
{
return strFirstItem + strSecondItem[nLength - 1];
}
else
return string.Empty;
}
}
private Dictionary
{
Dictionary
foreach (ListViewItem lviItem in lv_Items.Items)
{
double dSupport = GetSupport(lviItem.Text);
if ((dSupport / (double)(m_nLastTransId - 1) >= dMinSupport))
{
dic_FrequentItemsReturn.Add(lviItem.Text, dSupport);
m_dicAllFrequentItems.Add(lviItem.Text, dSupport);
}
}
return dic_FrequentItemsReturn;
}
private bool ItemIsRemovable(string strItem, ref List
{
string strTransaction;
bool bItemRemovable = true;
foreach (int nTransaction in m_dicTransactions.Keys)
{
strTransaction = m_dicTransactions[nTransaction];
if (strTransaction.Contains(strItem))
{
lst_Transactions.Add(nTransaction);
bItemRemovable = false;
}
}
return bItemRemovable;
}
private void EnableControls(bool bEnable)
{
btn_AddItem.Enabled = bEnable;
btn_DeleteItem.Enabled = bEnable;
btn_AddTrans.Enabled = bEnable;
btn_EditTrans.Visible = bEnable;
btn_DeleteTrans.Enabled = bEnable;
btn_ClearTransactions.Enabled = bEnable;
btn_Solve.Enabled = bEnable;
lv_Transactions.Enabled = bEnable;
}
}
}
Vulpes can u please kindly pinpoint recommendations?
VulpesPosted Jun 9, 2012, 9:02 AM
http://www.codeproject.com/Articles/70371/Apriori-Algorithm
So, you've obviously taken the code from there.
It would have saved a lot of time if you'd told me that before!
It's clear now that the code only works with single character items. One of the comments to the article says as much and it errors out whenever I try even a 2 letter item, let alone 6.
So the combinations it's dealing with are combinations of the items, not subsets of a single item.
One thing that puzzles me is why the guy who wrote it didn't just restrict the input of new items to single characters though it's clear that his code must otherwise be sound to achieve the very high rating for a CP article of 4.95 from 47 votes.
So, if I were you, I'd go back to using the code as he wrote it. I'd forget about using digits as we may have inadvertently changed something critical when altering the code to allow for that. It still gives you up to 26 items to play with (possibly 52 if you allow for both upper and lower case letters) which I'd have thought would be plenty for a data mining exercise.
Engr Tobi OwoeyePosted Jun 9, 2012, 4:33 PM
Engr Tobi OwoeyePosted Jun 8, 2012, 2:52 PM
private string GetCandidate(string strFirstItem, string strSecondItem)
{
int nLength = strFirstItem.Length;
if (nLength == 1)
{
return strFirstItem + strSecondItem;
}
else
{
string strFirstSubString = strFirstItem.Substring(0, nLength - 1);
string strSecondSubString = strSecondItem.Substring(0, nLength - 1);
if (strFirstSubString == strSecondSubString)
{
return strFirstItem + strSecondItem[nLength - 1];
}
else
return string.Empty;
}
}
here it refers to:
"
string strSecondSubString = strSecondItem.Substring(0, nLength - 1);"
and this method as well
private string GetRemaining(string strChild, string strParent)
{
for (int i = 0; i < strChild.Length; i++)
{
int nIndex = strParent.IndexOf(strChild[i]);
strParent = strParent.Remove(nIndex, 1);
}
return strParent;
}
here it refers to:
strParent = strParent.Remove(nIndex, 1);
HJow can I enlarge this index to accept six chars like csc444 etc.