package ca.pfv.spmf.algorithms.frequentpatterns.estDec;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

/**
 * This is an implementation of a estTree. 
*
* * This implementation was made by Azadeh Soltani
*
* * This file is part of the SPMF DATA MINING SOFTWARE * (http://www.philippe-fournier-viger.com/spmf).
*
* * SPMF is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version.
*
* * SPMF is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* * You should have received a copy of the GNU General Public License along with * SPMF. If not, see . * * @see Algo_estDec * @see estNode * @author Azadeh Soltani */ public class estTree { double N; // |Dk| double d; // decay rate int k; // current tid // itemset count int patternCount =0; // Hashtable for storing frequent patterns into memory Hashtable, Double> patterns; // writer used if result is saved to file BufferedWriter writer; double minsup; double minsig; estNode root; // tree root /** * Constructor */ estTree(double mins) { // default decay rate setDecayRate(2, 10000); N = 0; k = 0; minsup = mins / 100; minsig = 0.1 * minsup; root = new estNode(); // null node } /** * Set the decay rate * @param b decay base * @param h decay-base life */ void setDecayRate(double b, double h) { d = Math.pow(b, -1.0 / h); } /** * Method for updating parameters (Phase 1: parameter updating phase) * @param transaction */ void updateParams(int[] transaction) { // |Dk| = |Dk| x d + 1 N = N * d + 1; k++; updateNodes(root, transaction, 0); } /******************************************************************** * Recursive method for updating the counters of itemsets that * belong to a given transaction (Phase 2: count updating phase). * * @param currentNode a tree node * @param transaction the transaction for updating * @param ind depth of the branch ending at the current node ********************************************************************/ void updateNodes(estNode currentNode, int[] transaction, int ind) { // stop recursion if (ind >= transaction.length) return; // get item at position "ind" in the transaction Integer item = transaction[ind]; // look if there is a node for this item in the est-Tree estNode child = currentNode.getChildWithID(item); if (child != null) { // update count of the node child.update(k, 1, d); // if the support is enough if (child.computeSupport(N) >= minsig) updateNodes(child, transaction, ind + 1); else { /* PFV: WHY NOT REMOVE? * currentNode.children.remove(child); else */ } } updateNodes(currentNode, transaction, ind + 1); } /******************************************************************** * Method for inserting a new item to the tree (itemset of size 1). * * @param it the item ********************************************************************/ void insertItem(Integer it) { // create the node with a count of 0 double c = 0;// (getN(k-1)*minsig)*d+1; root.children.add(new estNode(it, c, k)); } /******************************************************************** * Method for inserting new possible frequent itemsets to the tree based on * the new transaction (Phase 3 : Delayed Insertion Phase). * * @param transaction the new transaction ********************************************************************/ void insertItemset(int[] transaction) { // create a new transaction List transaction2 = new ArrayList(); // add each item from the given transaction that has enough support to the new transaction for (int it : transaction) { estNode child = root.getChildWithID(it); if (child == null) insertItem(it); else if (child.computeSupport(N) >= minsig) transaction2.add(it); } // insert the new transaction insert_n_itemsets(root, transaction2, 0, new int[0]); } /******************************************************************** * Method for calculating |D|k * * @param n ********************************************************************/ double getN(int k) { return (1 - Math.pow(d, k)) / (1 - d); } /******************************************************************** * Method for obtaining the count of an itemset while ignoring * an item at a given position. * * @param itemset the itemset * @param pos the index of the item to be ignored in the itemset ********************************************************************/ double getCountOfItemsetWithoutItemAtPosition(int[] itemset, int pos) { // stop recursion estNode currentNode = root; for (int i=0; i< itemset.length; i++) { if(i != pos) { int item = itemset[i]; estNode child = currentNode.getChildWithID(item); if (child == null) return 0; currentNode = child; } } return currentNode.counter; } /******************************************************************** * Method for estimating the count of n-itemset from its n-1 subsets * * @param currentNode * , transaction, index ********************************************************************/ double estimateCount(int[] itemset) { double min = Double.MAX_VALUE; for (int i = 0; i < itemset.length; ++i) { double c = getCountOfItemsetWithoutItemAtPosition(itemset, i); if (c < min) min = c; } int n = itemset.length; double C_upper = minsig * getN(k - (n - 1)) * Math.pow(d, n - 1) + (1 - Math.pow(d, n - 1)) / (1 - d); if (min > C_upper) min = C_upper; return min; } /******************************************************************** * Recursive method for inserting all itemsets corresponding to the a transaction * * @param currentNode a tree node * @param transaction the transaction * @param the depth of the current node with respect to the root of the tree * @param itemset ********************************************************************/ public void insert_n_itemsets(estNode currentNode, List transaction, int ind, int[] itemset) { // stop recursion if (ind >= transaction.size()) return; Integer item = transaction.get(ind); // look if there is a node already in the est-Tree estNode child = currentNode.getChildWithID(item); // Itemset2 := itemset U item int[] itemset2 = new int[itemset.length+1]; System.arraycopy(itemset, 0, itemset2, 0, itemset.length); itemset2[itemset2.length-1] = item; if (child == null) { double c = estimateCount(itemset2); // if its estimated support is greater than minsig insert a new node // with itemId=item counter=c, tid=k if (c / N >= minsig) { child = new estNode(item, c, k); currentNode.children.add(child); } }// if child else { if (child.counter / N < minsig) { // if its support is less than minsig delete the node if (currentNode.itemID != -1) currentNode.children.remove(currentNode .getChildIndexWithID(item)); } else { // if its support is greater than minsig continue the recursion // with this subtree insert_n_itemsets(child, transaction, ind + 1, itemset2); } } insert_n_itemsets(currentNode, transaction, ind + 1, itemset); } /******************************************************************** * Method for force pruning * * @param root t ********************************************************************/ void forcePruning(estNode root) { for (int i = 0; i < root.children.size(); ++i) { estNode node = root.children.get(i); node.update(k, 0, d); if (node.computeSupport(N) < minsig && root.itemID != -1) root.children.remove(i--); else forcePruning(node); } } /******************************************************************** * Recursive method for finding frequent patterns. * @param root root of the current subtree * @param pattern current pattern * @throws IOException ********************************************************************/ void patternMining(estNode root, List pattern) throws IOException { for (estNode node : root.children) { List patt2 = new ArrayList(pattern); patt2.add(node.itemID); node.update(k, 0, d); double s = node.computeSupport(N); if (s > minsup) { patternCount++; // if store into file if(patterns == null) { writeItemset(patt2, s); }else { // else, store into memory patterns.put(new ArrayList(patt2), s); } patternMining(node, patt2); } } } /******************************************************************** * Method for finding frequent patterns and save them into memory * @param root root of the current subtree ********************************************************************/ Hashtable, Double> patternMining_saveToMemory() throws IOException { // Initialize hashtable for storing frequent patterns into memory patterns = new Hashtable, Double>(); patternCount = 0; // recursive method for pattern mining patternMining(root, new ArrayList()); return patterns; // return patterns found } /******************************************************************** * Method for finding frequent patterns and save them into file * @param root the root of the curent subtree * @param outputPath the output file path * @throws IOException ********************************************************************/ void patternMining_saveToFile(String outputPath) throws IOException { patterns = null; // because we will not save into memory writer = new BufferedWriter(new FileWriter(outputPath)); patternCount = 0; // recursive method for pattern mining patternMining(root, new ArrayList()); writer.close(); } /******************************************************************** * Method for writing frequent patterns in output file * @param itemset the pattern to be saved * @param support a double value ********************************************************************/ void writeItemset(List itemset, double support) throws IOException { StringBuffer buffer = new StringBuffer(); // for each item for (Integer item : itemset) { // write the item buffer.append(item); buffer.append(" "); } // write the support buffer.append("#SUP: "); buffer.append(support); writer.write(buffer.toString()); writer.newLine(); } /** * Get the last transaction id * @return the transaction id (integer) */ int getK() { return k; } }// class

Ads help maintain this website.