package ca.pfv.spmf.algorithms.frequentpatterns.estDec; import java.util.ArrayList; import java.util.List; /** * This is an implementation of a CPTree node. <br\> * <br\> * * This implementation was made by Azadeh Soltani <br\> * <br\> * * This file is part of the SPMF DATA MINING SOFTWARE * (http://www.philippe-fournier-viger.com/spmf).<br\> * <br\> * * 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.<br\> * <br\> * * 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. <br\> * <br\> * * You should have received a copy of the GNU General Public License along with * SPMF. If not, see <http://www.gnu.org/licenses/>. * * @see Algo_estDecPlus * @see CPTree * @author Azadeh Soltani */ class ParentNode{ CPTreeNode pNode; short pInd=0; ParentNode(CPTreeNode mp, short q){ pNode=mp; pInd=q; } boolean equal(ParentNode m){ return (m.pNode == pNode && m.pInd == pInd); } int isMember(List<ParentNode> parents){ for (int i=0;i<parents.size();++i) if (this.equal(parents.get(i))) return i; return -1; } } public class CPTreeNode { List<Integer> itemIDList;// item id list List<ParentNode>parents;// parent list double counter1; //counter double counter2; // counterII List<CPTreeNode> children; // children nodes /** * constructor * @param item the item * @param count the count * @param k the last transaction id */ CPTreeNode(Integer item, CPTreeNode parent, short parentInd, double count) { itemIDList = new ArrayList<Integer>(); itemIDList.add(item); parents = new ArrayList<ParentNode>(); parents.add(new ParentNode(parent,parentInd)); counter1 = count; counter2 = count; children = new ArrayList<CPTreeNode>(); } /** * Default constructor */ CPTreeNode() { itemIDList = new ArrayList<Integer>(); parents = new ArrayList<ParentNode>(); counter1 = 1; counter2 = 1; children = new ArrayList<CPTreeNode>(); } /** * Return the immediate index of itemIDList of this node having a given ID. If there is no * such index, return -1; * * @param id the id * @return the node or null */ public short getInnerIndexWithID(int id,CPTreeNode parentNode,short parentInd ) { for (short i = (short) (parentInd + 1); i < itemIDList.size(); ++i) if (itemIDList.get(i) == id && parents.get(i).pNode == parentNode && parents.get(i).pInd == parentInd) return i; return (short) -1; } /** * Return the immediate child of this node having a given ID. If there is no * such child, return null; * * @param id the id * @return the node or null */ public CPTreeNode getChildWithID(int id,int q) { if (children == null) return null; for (CPTreeNode child : children) { if (child.itemIDList.get(0)==id && child.parents.get(0).pInd==q) { return child; } } return null; } public int getLevel(int j) { int level = 0; while (true) { level++; if (j != 0) j = parents.get(j).pInd; else return level; } } public int getLongestLevel() { int level = 1; ArrayList<Integer> p = new ArrayList<Integer>(); p.add(0); while (true) { if (p.size() == 0) break; level++; ArrayList<Integer> p2 = new ArrayList<Integer>(); for (int j = 1; j < itemIDList.size(); ++j){ int x=parents.get(j).pInd; if (p.contains(x)) { p2.add(j); } } p = p2; } return level-1; } /** * if the itemID is the leaf level node return true * else return false; * * @param id */ public Boolean isLeafLevel(int id) { for (int i = id + 1; i < itemIDList.size(); ++i) { if (parents.get(i).pNode == this && parents.get(i).pInd == id) return false; } return true; } /** * Update the count of a node * * @param k the current transaction id * @param value the value to be added to the count * @param d the decay rate */ public void update(double d) { counter1 = counter1 * d + 1; } /** * Compute the support of this node as a percentage. * * @param N an integer representing a transaction count. */ public double computeSupport(double N,int level) { int maxL = getLongestLevel(); return estimateMergeCount(level, maxL) / N; } public double estimateMergeCount(int level,int longestL){ if (level == 1) return counter1; else if (level == longestL) return counter2; else{ //function 1 : // double x=counter1 - ((counter1 - counter2) * (level - 1) / (longestL - 1)); //return counter1 - ((counter1 - counter2) * (level - 1) / (longestL - 1)); //function 2: double x=0; for(int l=1;l<=longestL-1;++l) x+=1.0/l; double s=0; for(int l=1;l<=level-1;++l) s+=(1.0/l); // double f=counter1 -((counter1-counter2) * s/x); return counter1 -((counter1-counter2) * s/x); } } /** * Method for getting a string representation of this tree * (to be used for debugging purposes). * @param an indentation * @return a string */ public String toString(String indent) { StringBuilder output = new StringBuilder(); output.append("ID="+ super.toString()); output.append(" Counter1="+ counter1); output.append(" Counter2="+ counter2); output.append(" ItemIDList="); for(Integer item: itemIDList) { output.append(item + ","); } output.append(" Parents="); for(ParentNode parent: parents) { output.append("(pind=" + parent.pInd + ",node=" + parent.pNode.toString() + ")"); } output.append("\n"); String newIndent = indent + " "; for (CPTreeNode child : children) { output.append(newIndent+ child.toString(newIndent)); } return output.toString(); } }