/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package ca.pfv.spmf.algorithms.sequentialpatterns.gsp_AGP.items.patterns; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import ca.pfv.spmf.algorithms.sequentialpatterns.gsp_AGP.items.abstractions.ItemAbstractionPair; /** * Implementation of pattern structure. We define it as a list of pairs <abstraction, item>. * Besides, a bitSet appearingIn denotes the sequences where the pattern appears. * * Copyright Antonio Gomariz PeƱalver 2013 * * 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/>. * * @author agomariz */ public class Pattern implements Comparable<Pattern> { /** * List of elements of a patterns. Concretely it is a list of pairs <abstraction, item> */ private List<ItemAbstractionPair> elements; /** * Bitset when we keep the sequence IDs where the pattern it appears */ private BitSet appearingIn; //private Boolean frequent = null; /** * Standard constructor that sets all the attributes to empty values */ public Pattern() { this.elements = new ArrayList<ItemAbstractionPair>(); this.appearingIn = new BitSet(); } /** * Constructor that creates a pattern with the given element list * @param elements element list */ public Pattern(List<ItemAbstractionPair> elements) { this.elements = elements; this.appearingIn = new BitSet(); } /** * Constructor that creates a pattern with the only element passed as a parameter * @param pair */ public Pattern(ItemAbstractionPair pair) { this.elements = new ArrayList<ItemAbstractionPair>(); this.elements.add(pair); this.appearingIn = new BitSet(); } /** * Get the string representation of this itemset * @return the string representation */ @Override public String toString() { StringBuilder result = new StringBuilder(); BitSet sequenceIdsList = appearingIn; for (int i = 0; i < elements.size(); i++) { result.append(elements.get(i).toString()); } result.append("\t["); //for (int i = 0; i < listaEntradasPresentes.size(); i++) { for(int i = sequenceIdsList.nextSetBit(0); i >= 0; i = sequenceIdsList.nextSetBit(i+1)){ result.append(i).append(", "); } result.deleteCharAt(result.length() - 1); result.deleteCharAt(result.length() - 1); result.append("]"); return result.toString(); } /** * Get a string representation of this itemset. Adjusted to SPMF format. * @param outputSequenceIdentifiers if true, sequence identifiers will be output * @return the string representation */ public String toStringToFile(boolean outputSequenceIdentifiers) { StringBuilder result = new StringBuilder(); for (int i = 0; i < elements.size(); i++) { if(i==elements.size()-1){ if(i!=0) result.append(elements.get(i).toStringToFile()); else result.append(elements.get(i).getItem()); result.append(" -1"); } else if(i==0){ result.append(elements.get(i).getItem()); }else{ result.append(elements.get(i).toStringToFile()); } } result.append(" #SUP: "); result.append(appearingIn.cardinality()); // if the user wants the sequence IDs, we will show them if(outputSequenceIdentifiers) { result.append(" #SID: "); for (int i = appearingIn.nextSetBit(0); i >= 0; i = appearingIn.nextSetBit(i+1)) { result.append(i); result.append(" "); } } return result.toString(); } /** * Method that clones a pattern * @return the clone of the pattern */ public Pattern clonePattern() { List<ItemAbstractionPair> elementsCopy = new ArrayList<ItemAbstractionPair>(elements); Pattern clone = new Pattern(elementsCopy); return clone; } /** * It gets the components of the patterns in a list of pairs * @return the list of pairs */ public List<ItemAbstractionPair> getElements() { return elements; } /** * It gets the ith component from the pattern * @param i ith index of the element to return * @return the element (ItemAbstractionPair) */ public ItemAbstractionPair getIthElement(int i) { return elements.get(i); } /** * It returns the last but one element of the pattern * @return the last but one element */ public ItemAbstractionPair getLastButOneElement() { if (size() > 1) { return getIthElement(size() - 2); } return null; } /** * It returns the last element of the pattern * @return the last element */ public ItemAbstractionPair getLastElement() { if (size() > 0) { return getIthElement(size() - 1); } return null; } /** * It returns the first n elements of the pattern * @param n an integer n * @return the first n elements */ public List<ItemAbstractionPair> getNElements(int n) { if (n <= elements.size()) { return elements.subList(0, n - 1); } return null; } /** * Setter for the pattern components * @param elements a list of elements */ public void setElements(List<ItemAbstractionPair> elements) { this.elements = elements; } /** * Add a pair in the last position of the pattern * @param pair the pair */ public void add(ItemAbstractionPair pair) { this.elements.add(pair); } /** * return the pattern size * @return the size of the pattern */ public int size() { return elements.size(); } /** * Compare this pattern to another pattern * @param arg the other pattern * @return 0 if equal, -1 if smaller, otherwise 1 */ public int compareTo(Pattern arg) { List<ItemAbstractionPair> elementsOfBiggerPattern, elementsOfSmallerPattern; if (getElements().size() >= arg.getElements().size()) { elementsOfBiggerPattern = getElements(); elementsOfSmallerPattern = arg.getElements(); } else { elementsOfSmallerPattern = getElements(); elementsOfBiggerPattern = arg.getElements(); } for (int i = 0; i < elementsOfSmallerPattern.size(); i++) { int comparison = elementsOfSmallerPattern.get(i).compareTo(elementsOfBiggerPattern.get(i)); if (comparison != 0) { return comparison; } } if (elementsOfBiggerPattern.size() == elementsOfSmallerPattern.size()) { return 0; } if (getElements().size() < arg.getElements().size()) { return -1; } return 1; } /** * Check if this pattern is equal to another. * @param arg another pattern * @return true if equal, otherwise false. */ public boolean equals(Object arg) { if (arg instanceof Pattern) { Pattern p = (Pattern) arg; if (this.compareTo(p) == 0) { return true; } return false; } return false; } @Override public int hashCode() { int hash = 5; hash = 67 * hash + (this.elements != null ? this.elements.hashCode() : 0); return hash; } /** * It answer to the question of if the current pattern is a prefix of the * given pattern * @param p pattern where we want to check if our current pattern is a prefix * @return true if is a positive answer, false otherwise */ public boolean isPrefix(Pattern p) { boolean output = false; List<ItemAbstractionPair> pElements = new ArrayList<ItemAbstractionPair>(p.getElements()); pElements.remove(pElements.size() - 1); Pattern pTemp = new Pattern(pElements); if (this.equals(pTemp)) { output = true; } return output; } /** * Return the set of sequence IDs where the pattern appears * @return the set as a bitset */ public BitSet getAppearingIn() { return appearingIn; } public void setAppearingIn(BitSet appearingIn) { this.appearingIn = appearingIn; } public void clear() { elements.clear(); appearingIn.clear(); } /** * Add a sequence ID in the sequence Id set * @param sequenceId the sequence id */ public void addAppearance(Integer sequenceId) { appearingIn.set(sequenceId); } /** * It returns the support of a pattern * @return the support */ public double getSupport() { return appearingIn.cardinality(); } }