ItemSet.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 22k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    ItemSet.java
  18.  *    Copyright (C) 1999 Eibe Frank
  19.  *
  20.  */
  21. package weka.associations;
  22. import java.io.*;
  23. import java.util.*;
  24. import weka.core.*;
  25. /**
  26.  * Class for storing a set of items. Item sets are stored in a lexicographic
  27.  * order, which is determined by the header information of the set of instances
  28.  * used for generating the set of items. All methods in this class assume that
  29.  * item sets are stored in lexicographic order.
  30.  *
  31.  * @author Eibe Frank (eibe@cs.waikato.ac.nz)
  32.  * @version $Revision: 1.8 $
  33.  */
  34. public class ItemSet implements Serializable {
  35.   /** The items stored as an array of of ints. */
  36.   protected int[] m_items;
  37.   /** Counter for how many transactions contain this item set. */
  38.   protected int m_counter;
  39.   /** The total number of transactions */
  40.   protected int m_totalTransactions;
  41.   /**
  42.    * Constructor
  43.    * @param totalTrans the total number of transactions in the data
  44.    */
  45.   public ItemSet(int totalTrans) {
  46.     m_totalTransactions = totalTrans;
  47.   }
  48.   /**
  49.    * Outputs the confidence for a rule.
  50.    *
  51.    * @param premise the premise of the rule
  52.    * @param consequence the consequence of the rule
  53.    * @return the confidence on the training data
  54.    */
  55.   public static double confidenceForRule(ItemSet premise, 
  56.  ItemSet consequence) {
  57.     return (double)consequence.m_counter/(double)premise.m_counter;
  58.   }
  59.   /**
  60.    * Outputs the lift for a rule. Lift is defined as:<br>
  61.    * confidence / prob(consequence)
  62.    *
  63.    * @param premise the premise of the rule
  64.    * @param consequence the consequence of the rule
  65.    * @param consequenceCount how many times the consequence occurs independent
  66.    * of the premise
  67.    * @return the lift on the training data
  68.    */
  69.   public double liftForRule(ItemSet premise, 
  70.     ItemSet consequence,
  71.     int consequenceCount) {
  72.     double confidence = confidenceForRule(premise, consequence);
  73.    return confidence / ((double)consequenceCount / 
  74.   (double)m_totalTransactions);
  75.   }
  76.   /**
  77.    * Outputs the leverage for a rule. Leverage is defined as: <br>
  78.    * prob(premise & consequence) - (prob(premise) * prob(consequence))
  79.    *
  80.    * @param premise the premise of the rule
  81.    * @param consequence the consequence of the rule
  82.    * @param premiseCount how many times the premise occurs independent
  83.    * of the consequent
  84.    * @param consequenceCount how many times the consequence occurs independent
  85.    * of the premise
  86.    * @return the leverage on the training data
  87.    */
  88.   public double leverageForRule(ItemSet premise,
  89. ItemSet consequence,
  90. int premiseCount,
  91. int consequenceCount) {
  92.     double coverageForItemSet = (double)consequence.m_counter / 
  93.       (double)m_totalTransactions;
  94.     double expectedCoverageIfIndependent = 
  95.       ((double)premiseCount / (double)m_totalTransactions) * 
  96.       ((double)consequenceCount / (double)m_totalTransactions);
  97.     double lev = coverageForItemSet - expectedCoverageIfIndependent;
  98.     return lev;
  99.   }
  100.   /**
  101.    * Outputs the conviction for a rule. Conviction is defined as: <br>
  102.    * prob(premise) * prob(!consequence) / prob(premise & !consequence)
  103.    *
  104.    * @param premise the premise of the rule
  105.    * @param consequence the consequence of the rule
  106.    * @param premiseCount how many times the premise occurs independent
  107.    * of the consequent
  108.    * @param consequenceCount how many times the consequence occurs independent
  109.    * of the premise
  110.    * @return the conviction on the training data
  111.    */
  112.   public double convictionForRule(ItemSet premise,
  113.    ItemSet consequence,
  114.    int premiseCount,
  115.    int consequenceCount) {
  116.     double num = 
  117.       (double)premiseCount * (double)(m_totalTransactions - consequenceCount) *
  118.        (double)m_totalTransactions;
  119.     double denom = 
  120.       ((premiseCount - consequence.m_counter)+1);
  121.     
  122.     if (num < 0 || denom < 0) {
  123.       System.err.println("*** "+num+" "+denom);
  124.       System.err.println("premis count: "+premiseCount+" consequence count "+consequenceCount+" total trans "+m_totalTransactions);
  125.     }
  126.     return num / denom;
  127.   }
  128.   /**
  129.    * Checks if an instance contains an item set.
  130.    *
  131.    * @param instance the instance to be tested
  132.    * @return true if the given instance contains this item set
  133.    */
  134.   public final boolean containedBy(Instance instance) {
  135.     
  136.     for (int i = 0; i < instance.numAttributes(); i++) 
  137.       if (m_items[i] > -1) {
  138. if (instance.isMissing(i))
  139.   return false;
  140. if (m_items[i] != (int)instance.value(i))
  141.   return false;
  142.       }
  143.     return true;
  144.   }
  145.   /**
  146.    * Deletes all item sets that don't have minimum support.
  147.    *
  148.    * @param itemSets the set of item sets to be pruned
  149.    * @param minSupport the minimum number of transactions to be covered
  150.    * @return the reduced set of item sets
  151.    */
  152.   public static FastVector deleteItemSets(FastVector itemSets, 
  153.   int minSupport,
  154.   int maxSupport) {
  155.     FastVector newVector = new FastVector(itemSets.size());
  156.     for (int i = 0; i < itemSets.size(); i++) {
  157.       ItemSet current = (ItemSet)itemSets.elementAt(i);
  158.       if ((current.m_counter >= minSupport) 
  159.   && (current.m_counter <= maxSupport))
  160. newVector.addElement(current);
  161.     }
  162.     return newVector;
  163.   }
  164.   /**
  165.    * Tests if two item sets are equal.
  166.    *
  167.    * @param itemSet another item set
  168.    * @return true if this item set contains the same items as the given one
  169.    */
  170.   public final boolean equals(Object itemSet) {
  171.     if ((itemSet == null) || !(itemSet.getClass().equals(this.getClass()))) {
  172.       return false;
  173.     }
  174.     if (m_items.length != ((ItemSet)itemSet).m_items.length)
  175.       return false;
  176.     for (int i = 0; i < m_items.length; i++)
  177.       if (m_items[i] != ((ItemSet)itemSet).m_items[i])
  178. return false;
  179.     return true;
  180.   }
  181.   /**
  182.    * Generates all rules for an item set.
  183.    *
  184.    * @param minConfidence the minimum confidence the rules have to have
  185.    * @param hashtables containing all(!) previously generated
  186.    * item sets
  187.    * @param numItemsInSet the size of the item set for which the rules
  188.    * are to be generated
  189.    * @return all the rules with minimum confidence for the given item set
  190.    */
  191.   public final FastVector[] generateRules(double minConfidence, 
  192.   FastVector hashtables,
  193.   int numItemsInSet) {
  194.     FastVector premises = new FastVector(),consequences = new FastVector(),
  195.       conf = new FastVector();
  196.     FastVector[] rules = new FastVector[3], moreResults;
  197.     ItemSet premise, consequence;
  198.     Hashtable hashtable = (Hashtable)hashtables.elementAt(numItemsInSet - 2);
  199.     // Generate all rules with one item in the consequence.
  200.     for (int i = 0; i < m_items.length; i++) 
  201.       if (m_items[i] != -1) {
  202. premise = new ItemSet(m_totalTransactions);
  203. consequence = new ItemSet(m_totalTransactions);
  204. premise.m_items = new int[m_items.length];
  205. consequence.m_items = new int[m_items.length];
  206. consequence.m_counter = m_counter;
  207. for (int j = 0; j < m_items.length; j++) 
  208.   consequence.m_items[j] = -1;
  209. System.arraycopy(m_items, 0, premise.m_items, 0, m_items.length);
  210. premise.m_items[i] = -1;
  211. consequence.m_items[i] = m_items[i];
  212. premise.m_counter = ((Integer)hashtable.get(premise)).intValue();
  213. premises.addElement(premise);
  214. consequences.addElement(consequence);
  215. conf.addElement(new Double(confidenceForRule(premise, consequence)));
  216.       }
  217.     rules[0] = premises;
  218.     rules[1] = consequences;
  219.     rules[2] = conf;
  220.     pruneRules(rules, minConfidence);
  221.     // Generate all the other rules
  222.     moreResults = moreComplexRules(rules, numItemsInSet, 1, minConfidence,
  223.    hashtables);
  224.     if (moreResults != null) 
  225.       for (int i = 0; i < moreResults[0].size(); i++) {
  226. rules[0].addElement(moreResults[0].elementAt(i));
  227. rules[1].addElement(moreResults[1].elementAt(i));
  228. rules[2].addElement(moreResults[2].elementAt(i));
  229.       }
  230.     return rules;
  231.   }
  232.   /**
  233.    * Generates all significant rules for an item set.
  234.    *
  235.    * @param minMetric the minimum metric (confidence, lift, leverage, 
  236.    * improvement) the rules have to have
  237.    * @param metricType (confidence=0, lift, leverage, improvement)
  238.    * @param hashtables containing all(!) previously generated
  239.    * item sets
  240.    * @param numItemsInSet the size of the item set for which the rules
  241.    * are to be generated
  242.    * @param the significance level for testing the rules
  243.    * @return all the rules with minimum metric for the given item set
  244.    * @exception Exception if something goes wrong
  245.    */
  246.   public final FastVector[] generateRulesBruteForce(double minMetric,
  247.     int metricType,
  248. FastVector hashtables,
  249. int numItemsInSet,
  250. int numTransactions,
  251. double significanceLevel) 
  252.   throws Exception {
  253.     FastVector premises = new FastVector(),consequences = new FastVector(),
  254.       conf = new FastVector(), lift = new FastVector(), lev = new FastVector(),
  255.       conv = new FastVector(); 
  256.     FastVector[] rules = new FastVector[6];
  257.     ItemSet premise, consequence;
  258.     Hashtable hashtableForPremise, hashtableForConsequence;
  259.     int numItemsInPremise, help, max, consequenceUnconditionedCounter;
  260.     double[][] contingencyTable = new double[2][2];
  261.     double metric, chiSquared;
  262.     // Generate all possible rules for this item set and test their
  263.     // significance.
  264.     max = (int)Math.pow(2, numItemsInSet);
  265.     for (int j = 1; j < max; j++) {
  266.       numItemsInPremise = 0;
  267.       help = j;
  268.       while (help > 0) {
  269. if (help % 2 == 1)
  270.   numItemsInPremise++;
  271. help /= 2;
  272.       }
  273.       if (numItemsInPremise < numItemsInSet) {
  274. hashtableForPremise = 
  275.   (Hashtable)hashtables.elementAt(numItemsInPremise-1);
  276. hashtableForConsequence = 
  277.   (Hashtable)hashtables.elementAt(numItemsInSet-numItemsInPremise-1);
  278. premise = new ItemSet(m_totalTransactions);
  279. consequence = new ItemSet(m_totalTransactions);
  280. premise.m_items = new int[m_items.length];
  281. consequence.m_items = new int[m_items.length];
  282. consequence.m_counter = m_counter;
  283. help = j;
  284. for (int i = 0; i < m_items.length; i++) 
  285.   if (m_items[i] != -1) {
  286.     if (help % 2 == 1) {          
  287.       premise.m_items[i] = m_items[i];
  288.       consequence.m_items[i] = -1;
  289.     } else {
  290.       premise.m_items[i] = -1;
  291.       consequence.m_items[i] = m_items[i];
  292.     }
  293.     help /= 2;
  294.   } else {
  295.     premise.m_items[i] = -1;
  296.     consequence.m_items[i] = -1;
  297.   }
  298. premise.m_counter = ((Integer)hashtableForPremise.get(premise)).intValue();
  299. consequenceUnconditionedCounter =
  300.   ((Integer)hashtableForConsequence.get(consequence)).intValue();
  301. if (metricType == 0) {
  302.   contingencyTable[0][0] = (double)(consequence.m_counter);
  303.   contingencyTable[0][1] = (double)(premise.m_counter - consequence.m_counter);
  304.   contingencyTable[1][0] = (double)(consequenceUnconditionedCounter -
  305.     consequence.m_counter);
  306.   contingencyTable[1][1] = (double)(numTransactions - premise.m_counter -
  307.     consequenceUnconditionedCounter +
  308.     consequence.m_counter);
  309.   chiSquared = ContingencyTables.chiSquared(contingencyTable, false);
  310.   metric = confidenceForRule(premise, consequence);
  311.   if ((!(metric < minMetric)) &&
  312.       (!(chiSquared > significanceLevel))) {
  313.     premises.addElement(premise);
  314.     consequences.addElement(consequence);
  315.     conf.addElement(new Double(metric));
  316.     lift.addElement(new Double(liftForRule(premise, consequence, 
  317.        consequenceUnconditionedCounter)));
  318.     lev.addElement(new Double(leverageForRule(premise, consequence,
  319.      premise.m_counter,
  320.      consequenceUnconditionedCounter)));
  321.     conv.addElement(new Double(convictionForRule(premise, consequence,
  322.        premise.m_counter,
  323.        consequenceUnconditionedCounter)));
  324.   }
  325. } else {
  326.   double tempConf = confidenceForRule(premise, consequence);
  327.   double tempLift = liftForRule(premise, consequence, 
  328. consequenceUnconditionedCounter);
  329.   double tempLev = leverageForRule(premise, consequence,
  330.    premise.m_counter,
  331.    consequenceUnconditionedCounter);
  332.   double tempConv = convictionForRule(premise, consequence,
  333.       premise.m_counter,
  334.       consequenceUnconditionedCounter);
  335.   switch(metricType) {
  336.   case 1: 
  337.     metric = tempLift;
  338.     break;
  339.   case 2:
  340.     metric = tempLev;
  341.     break;
  342.   case 3: 
  343.     metric = tempConv;
  344.     break;
  345.   default:
  346.     throw new Exception("ItemSet: Unknown metric type!");
  347.   }
  348.   if (!(metric < minMetric)) {
  349.     premises.addElement(premise);
  350.     consequences.addElement(consequence);
  351.     conf.addElement(new Double(tempConf));
  352.     lift.addElement(new Double(tempLift));
  353.     lev.addElement(new Double(tempLev));
  354.     conv.addElement(new Double(tempConv));
  355.   }
  356. }
  357.       }
  358.     }
  359.     rules[0] = premises;
  360.     rules[1] = consequences;
  361.     rules[2] = conf;
  362.     rules[3] = lift;
  363.     rules[4] = lev;
  364.     rules[5] = conv;
  365.     return rules;
  366.   }
  367.   /**
  368.    * Return a hashtable filled with the given item sets.
  369.    *
  370.    * @param itemSets the set of item sets to be used for filling the hash table
  371.    * @param initialSize the initial size of the hashtable
  372.    * @return the generated hashtable
  373.    */
  374.   public static Hashtable getHashtable(FastVector itemSets, int initialSize) {
  375.     Hashtable hashtable = new Hashtable(initialSize);
  376.     for (int i = 0; i < itemSets.size(); i++) {
  377.       ItemSet current = (ItemSet)itemSets.elementAt(i);
  378.       hashtable.put(current, new Integer(current.m_counter));
  379.     }
  380.     return hashtable;
  381.   }
  382.   /**
  383.    * Produces a hash code for a item set.
  384.    *
  385.    * @return a hash code for a set of items
  386.    */
  387.   public final int hashCode() {
  388.     long result = 0;
  389.     for (int i = m_items.length-1; i >= 0; i--)
  390.       result += (i * m_items[i]);
  391.     return (int)result;
  392.   }
  393.   /**
  394.    * Merges all item sets in the set of (k-1)-item sets 
  395.    * to create the (k)-item sets and updates the counters.
  396.    *
  397.    * @param itemSets the set of (k-1)-item sets
  398.    * @param size the value of (k-1)
  399.    * @return the generated (k)-item sets
  400.    */
  401.   public static FastVector mergeAllItemSets(FastVector itemSets, int size, 
  402.     int totalTrans) {
  403.     FastVector newVector = new FastVector();
  404.     ItemSet result;
  405.     int numFound, k;
  406.     for (int i = 0; i < itemSets.size(); i++) {
  407.       ItemSet first = (ItemSet)itemSets.elementAt(i);
  408.     out:
  409.       for (int j = i+1; j < itemSets.size(); j++) {
  410. ItemSet second = (ItemSet)itemSets.elementAt(j);
  411. result = new ItemSet(totalTrans);
  412. result.m_items = new int[first.m_items.length];
  413. // Find and copy common prefix of size 'size'
  414. numFound = 0;
  415. k = 0;
  416. while (numFound < size) {
  417.   if (first.m_items[k] == second.m_items[k]) {
  418.     if (first.m_items[k] != -1) 
  419.       numFound++;
  420.     result.m_items[k] = first.m_items[k];
  421.   } else 
  422.     break out;
  423.   k++;
  424. }
  425. // Check difference
  426. while (k < first.m_items.length) {
  427.   if ((first.m_items[k] != -1) && (second.m_items[k] != -1))
  428.     break;
  429.   else {
  430.     if (first.m_items[k] != -1)
  431.       result.m_items[k] = first.m_items[k];
  432.     else
  433.       result.m_items[k] = second.m_items[k];
  434.   }
  435.   k++;
  436. }
  437. if (k == first.m_items.length) {
  438.   result.m_counter = 0;
  439.   newVector.addElement(result);
  440. }
  441.       }
  442.     }
  443.     return newVector;
  444.   }
  445.   /**
  446.    * Prunes a set of (k)-item sets using the given (k-1)-item sets.
  447.    *
  448.    * @param toPrune the set of (k)-item sets to be pruned
  449.    * @param kMinusOne the (k-1)-item sets to be used for pruning
  450.    * @return the pruned set of item sets
  451.    */
  452.   public static FastVector pruneItemSets(FastVector toPrune, Hashtable kMinusOne) {
  453.     FastVector newVector = new FastVector(toPrune.size());
  454.     int help, j;
  455.     for (int i = 0; i < toPrune.size(); i++) {
  456.       ItemSet current = (ItemSet)toPrune.elementAt(i);
  457.       for (j = 0; j < current.m_items.length; j++)
  458. if (current.m_items[j] != -1) {
  459.   help = current.m_items[j];
  460.   current.m_items[j] = -1;
  461.   if (kMinusOne.get(current) == null) {
  462.     current.m_items[j] = help;
  463.     break;
  464.   } else 
  465.     current.m_items[j] = help;
  466. }
  467.       if (j == current.m_items.length) 
  468. newVector.addElement(current);
  469.     }
  470.     return newVector;
  471.   }
  472.   /**
  473.    * Prunes a set of rules.
  474.    *
  475.    * @param rules a two-dimensional array of lists of item sets. The first list
  476.    * of item sets contains the premises, the second one the consequences.
  477.    * @param minConfidence the minimum confidence the rules have to have
  478.    */
  479.   public static void pruneRules(FastVector[] rules, double minConfidence) {
  480.     FastVector newPremises = new FastVector(rules[0].size()),
  481.       newConsequences = new FastVector(rules[1].size()),
  482.       newConf = new FastVector(rules[2].size());
  483.     for (int i = 0; i < rules[0].size(); i++) 
  484.       if (!(((Double)rules[2].elementAt(i)).doubleValue() <
  485.     minConfidence)) {
  486. newPremises.addElement(rules[0].elementAt(i));
  487. newConsequences.addElement(rules[1].elementAt(i));
  488. newConf.addElement(rules[2].elementAt(i));
  489.       }
  490.     rules[0] = newPremises;
  491.     rules[1] = newConsequences;
  492.     rules[2] = newConf;
  493.   }
  494.   /**
  495.    * Converts the header info of the given set of instances into a set 
  496.    * of item sets (singletons). The ordering of values in the header file 
  497.    * determines the lexicographic order.
  498.    *
  499.    * @param instances the set of instances whose header info is to be used
  500.    * @return a set of item sets, each containing a single item
  501.    * @exception Exception if singletons can't be generated successfully
  502.    */
  503.   public static FastVector singletons(Instances instances) throws Exception {
  504.     FastVector setOfItemSets = new FastVector();
  505.     ItemSet current;
  506.     for (int i = 0; i < instances.numAttributes(); i++) {
  507.       if (instances.attribute(i).isNumeric())
  508. throw new Exception("Can't handle numeric attributes!");
  509.       for (int j = 0; j < instances.attribute(i).numValues(); j++) {
  510. current = new ItemSet(instances.numInstances());
  511. current.m_items = new int[instances.numAttributes()];
  512. for (int k = 0; k < instances.numAttributes(); k++)
  513.   current.m_items[k] = -1;
  514. current.m_items[i] = j;
  515. setOfItemSets.addElement(current);
  516.       }
  517.     }
  518.     return setOfItemSets;
  519.   }
  520.   
  521.   /**
  522.    * Subtracts an item set from another one.
  523.    *
  524.    * @param toSubtract the item set to be subtracted from this one.
  525.    * @return an item set that only contains items form this item sets that
  526.    * are not contained by toSubtract
  527.    */
  528.   public final ItemSet subtract(ItemSet toSubtract) {
  529.     ItemSet result = new ItemSet(m_totalTransactions);
  530.     
  531.     result.m_items = new int[m_items.length];
  532.     for (int i = 0; i < m_items.length; i++) 
  533.       if (toSubtract.m_items[i] == -1)
  534. result.m_items[i] = m_items[i];
  535.       else
  536. result.m_items[i] = -1;
  537.     result.m_counter = 0;
  538.     return result;
  539.   }
  540.   /**
  541.    * Outputs the support for an item set.
  542.    *
  543.    * @return the support
  544.    */
  545.   public final int support() {
  546.     return m_counter;
  547.   }
  548.   /**
  549.    * Returns the contents of an item set as a string.
  550.    *
  551.    * @param instances contains the relevant header information
  552.    * @return string describing the item set
  553.    */
  554.   public final String toString(Instances instances) {
  555.     StringBuffer text = new StringBuffer();
  556.     for (int i = 0; i < instances.numAttributes(); i++)
  557.       if (m_items[i] != -1) {
  558. text.append(instances.attribute(i).name()+'=');
  559. text.append(instances.attribute(i).value(m_items[i])+' ');
  560.       }
  561.     text.append(m_counter);
  562.     return text.toString();
  563.   }
  564.   /**
  565.    * Updates counter of item set with respect to given transaction.
  566.    *
  567.    * @param instance the instance to be used for ubdating the counter
  568.    */
  569.   public final void upDateCounter(Instance instance) {
  570.     if (containedBy(instance))
  571.       m_counter++;
  572.   }
  573.   /**
  574.    * Updates counters for a set of item sets and a set of instances.
  575.    *
  576.    * @param itemSets the set of item sets which are to be updated
  577.    * @param instances the instances to be used for updating the counters
  578.    */
  579.   public static void upDateCounters(FastVector itemSets, Instances instances) {
  580.     for (int i = 0; i < instances.numInstances(); i++) {
  581.       Enumeration enum = itemSets.elements();
  582.       while (enum.hasMoreElements()) 
  583. ((ItemSet)enum.nextElement()).upDateCounter(instances.instance(i));
  584.     }
  585.   }
  586.   /**
  587.    * Generates rules with more than one item in the consequence.
  588.    *
  589.    * @param rules all the rules having (k-1)-item sets as consequences
  590.    * @param numItemsInSet the size of the item set for which the rules
  591.    * are to be generated
  592.    * @param numItemsInConsequence the value of (k-1)
  593.    * @param minConfidence the minimum confidence a rule has to have
  594.    * @param hashtables the hashtables containing all(!) previously generated
  595.    * item sets
  596.    * @return all the rules having (k)-item sets as consequences
  597.    */
  598.   private final FastVector[] moreComplexRules(FastVector[] rules, 
  599.       int numItemsInSet, 
  600.       int numItemsInConsequence,
  601.       double minConfidence, 
  602.       FastVector hashtables) {
  603.     ItemSet newPremise;
  604.     FastVector[] result, moreResults;
  605.     FastVector newConsequences, newPremises = new FastVector(), 
  606.       newConf = new FastVector();
  607.     Hashtable hashtable;
  608.     if (numItemsInSet > numItemsInConsequence + 1) {
  609.       hashtable =
  610. (Hashtable)hashtables.elementAt(numItemsInSet - numItemsInConsequence - 2);
  611.       newConsequences = mergeAllItemSets(rules[1], 
  612.  numItemsInConsequence - 1,
  613.  m_totalTransactions);
  614.       Enumeration enum = newConsequences.elements();
  615.       while (enum.hasMoreElements()) {
  616. ItemSet current = (ItemSet)enum.nextElement();
  617. current.m_counter = m_counter;
  618. newPremise = subtract(current);
  619. newPremise.m_counter = ((Integer)hashtable.get(newPremise)).intValue();
  620. newPremises.addElement(newPremise);
  621. newConf.addElement(new Double(confidenceForRule(newPremise, current)));
  622.       }
  623.       result = new FastVector[3];
  624.       result[0] = newPremises;
  625.       result[1] = newConsequences;
  626.       result[2] = newConf;
  627.       pruneRules(result, minConfidence);
  628.       moreResults = moreComplexRules(result,numItemsInSet,numItemsInConsequence+1,
  629.      minConfidence, hashtables);
  630.       if (moreResults != null) 
  631. for (int i = 0; i < moreResults[0].size(); i++) {
  632.   result[0].addElement(moreResults[0].elementAt(i));
  633.   result[1].addElement(moreResults[1].elementAt(i));
  634.   result[2].addElement(moreResults[2].elementAt(i));
  635. }
  636.       return result;
  637.     } else
  638.       return null;
  639.   }
  640. }