package ca.pfv.spmf.algorithms.associationrules.TopKRules_and_TNR; /* This file is copyright (c) 2008-2012 Philippe Fournier-Viger * * 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 <http://www.gnu.org/licenses/>. */ import java.util.BitSet; /** * This class represents an association rule found by the * TNR or TopKRules algorithm for top-k association rule mining. * <br/><br/> * * This implementation is optimized for these algorithms. In particular, * it stores the tidset of the rule and the tidset of the * rule antecedent as bitsets. Furthermore, the antecedent and * consequent are stored as array of integers. Lastly, * for optimization, the maximum item id of the antecedent * and consequent of the rule are precalculated and kept (as explained in the papers). * * @see AlgoTNR * @see AlgoTopKRules * @author Philippe Fournier-Viger */ public class RuleG implements Comparable<RuleG>{ private Integer[] itemset1; // antecedent of the rule private Integer[] itemset2; // consequent of the rule public BitSet tids1; // tidset of the antecedent public BitSet common; // tidset of the rule public int maxLeft; // maximum item id in the antecedent public int maxRight; // maximum item id in the consequent // variable to indicate if this rule is a candidate for both left and right // expansions (true) or just for right expansion (false) public boolean expandLR = false; // the support of this rule private int count; /** * Constructor * @param itemset1 the left itemset * @param itemset2 the right itemset * @param count support of the rule * @param tids1 tidset of the antecedent * @param common tidset of the rule * @param maxLeft maximum item id in the antecedent * @param maxRight maximum item id in the consequent */ public RuleG(Integer[] itemset1, Integer[] itemset2, int count, BitSet tids1, BitSet common, int maxLeft, int maxRight){ this.count = count; this.itemset1 = itemset1; this.itemset2 = itemset2; this.common = common; this.tids1 = tids1; this.maxLeft= maxLeft; this.maxRight= maxRight; } /** * Get the antecedent. * @return an itemset */ public Integer[] getItemset1() { return itemset1; } /** * Get the consequent. * @return an itemset */ public Integer[] getItemset2() { return itemset2; } /** * Get the support of this rule. * @return the support (integer) */ public int getAbsoluteSupport(){ return count; } /** * Get the confidence of this rule. * @return the confidence (double) */ public double getConfidence() { return ((double)count) / tids1.cardinality(); } /** * Compare this rule with another rule "o". * @return 1 if this rule is larger, 0 if equal, or -1 if smaller. * The comparison is done based on the support, * then on the size of the antecedent, * then on the size of the consequent, * then on the confidence, * then on the hashCodes. */ public int compareTo(RuleG o) { // if the same object, return 0. if(o == this){ return 0; } // compare the supports int compare = this.getAbsoluteSupport() - o.getAbsoluteSupport(); if(compare !=0){ return compare; } //compare antecedent sizes int itemset1sizeA = this.itemset1 == null ? 0 : this.itemset1.length; int itemset1sizeB = o.itemset1 == null ? 0 : o.itemset1.length; int compare2 = itemset1sizeA - itemset1sizeB; if(compare2 !=0){ return compare2; } //compare consequent sizes int itemset2sizeA = this.itemset2 == null ? 0 : this.itemset2.length; int itemset2sizeB = o.itemset2 == null ? 0 : o.itemset2.length; int compare3 = itemset2sizeA - itemset2sizeB; if(compare3 !=0){ return compare3; } // compare confidence int compare4 = (int)(this.getConfidence() - o.getConfidence()); if(compare !=0){ return compare4; } // compare hashcodes return this.hashCode() - o.hashCode(); } public boolean equals(Object o){ RuleG ruleX = (RuleG)o; if(ruleX.itemset1.length != this.itemset1.length){ return false; } if(ruleX.itemset2.length != this.itemset2.length){ return false; } for(int i=0; i< itemset1.length; i++){ if(this.itemset1[i] != ruleX.itemset1[i]){ return false; } } for(int i=0; i< itemset2.length; i++){ if(this.itemset2[i] != ruleX.itemset2[i]){ return false; } } return true; } /** * Get a string representation of this rule. * @return a string */ public String toString(){ return toString(itemset1) + " ==> " + toString(itemset2); } /** * Return a string representation of an itemset * @param itemset the itemset * @return a string */ private String toString(Integer[] itemset) { StringBuilder temp = new StringBuilder(); // for each item, add it to the string, separated by a space for(int item : itemset){ temp.append(item + " "); } return temp.toString(); } }