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();
}
}