package ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.candidatePatternsGeneration; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.EquivalenceClass; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.dataStructures.abstractions.Abstraction_Qualitative; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.dataStructures.abstractions.ItemAbstractionPair; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.dataStructures.creators.AbstractionCreator_Qualitative; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.dataStructures.creators.ItemAbstractionPairCreator; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.dataStructures.patterns.Pattern; import ca.pfv.spmf.algorithms.sequentialpatterns.spade_spam_AGP.idLists.IDList; /** * Class that implements a candidate generator for standard SDM. * * 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 CandidateGenerator_Qualitative implements CandidateGenerator { /** * Static reference in order to make the class singleton */ private static CandidateGenerator_Qualitative instance = null; /** * Method to remove the static reference of this class */ public static void clear() { instance = null; } /** * Standard constructor. */ private CandidateGenerator_Qualitative() { } /** * Get the static reference to the singleton class. * * @return */ public static CandidateGenerator_Qualitative getInstance() { if (instance == null) { instance = new CandidateGenerator_Qualitative(); } return instance; } /** * It generates a list of candidate patterns from the two patterns given as * parameters * * @param pattern1 The first pattern from which a new candidate is generated * @param pattern2 The second pattern from which a new candidate is * generated * @param minSupport The mininum relative support * @return A list of candidate patterns created from pattern1 and pattern2 */ @Override public List<Pattern> generateCandidates(Pattern pattern1, Pattern pattern2, int minSupport, boolean doNotExploreXY, boolean doNotExploreYX, boolean doNotExploreX_Y, boolean doNotExploreY_X) { //New list where we keep the new candidate patterns List<Pattern> candidates = new ArrayList<Pattern>(); /* We check if just taking the intersection of sequence appearances we * exceed or equal the minimum support */ BitSet joinBitmap = (BitSet) pattern1.getAppearingIn().clone(); joinBitmap.and(pattern2.getAppearingIn()); if (joinBitmap.cardinality() >= minSupport) {//If that is the case ItemAbstractionPairCreator pairCreator = ItemAbstractionPairCreator.getInstance(); AbstractionCreator_Qualitative qualitativeCreator = AbstractionCreator_Qualitative.getInstance(); /* We get the last two items of the last patterns as well as their * qualitative relations */ ItemAbstractionPair lastPairOfPattern1 = pattern1.getElements().get(pattern1.size() - 1); ItemAbstractionPair lastPairOfPattern2 = pattern2.getElements().get(pattern2.size() - 1); Abstraction_Qualitative abstractionOfLastPairOfPattern1 = ((Abstraction_Qualitative) lastPairOfPattern1.getAbstraction()); Abstraction_Qualitative abstractionOfLastPairOfPattern2 = ((Abstraction_Qualitative) lastPairOfPattern2.getAbstraction()); /* * If both of them does not have an equal relation */ if (!abstractionOfLastPairOfPattern1.hasEqualRelation() && !abstractionOfLastPairOfPattern2.hasEqualRelation()) { //Both pattern1 and pattern2 has as last element and item occurring in a different itemset to the previous one (last but one) //And if the last item of both patterns is not the same if (!lastPairOfPattern1.getItem().equals(lastPairOfPattern2.getItem())) { //we have to create three candidate patterns /* EXAMPLE: if the first pattern is (P < x), being x the last item, * and the second pattern is (P < y), being y its last item, * * We have three possible candidate patterns: * C1 = (P < x < y), with x before y * C2 = (P < y < x), with y before x * C3 = (P < (x y)), with x and y at the same time */ //So we make C3 Pattern newCandidate_equalRelation = null; if (pattern1.compareTo(pattern2) < 0 && doNotExploreXY == false) { newCandidate_equalRelation = pattern1.clonePattern(); newCandidate_equalRelation.add(pairCreator.getItemAbstractionPair(lastPairOfPattern2.getItem(), qualitativeCreator.createAbstraction(true))); } else if (doNotExploreYX == false) { newCandidate_equalRelation = pattern2.clonePattern(); newCandidate_equalRelation.add(pairCreator.getItemAbstractionPair(lastPairOfPattern1.getItem(), qualitativeCreator.createAbstraction(true))); } if (newCandidate_equalRelation != null) { candidates.add(newCandidate_equalRelation); } //And we make C2 if (doNotExploreY_X == false) { Pattern newCandidate_BeforeRelationWithChangedItems = pattern2.clonePattern(); newCandidate_BeforeRelationWithChangedItems.add(lastPairOfPattern1); candidates.add(newCandidate_BeforeRelationWithChangedItems); } } //And we make C1 if (doNotExploreX_Y == false) { Pattern newCandidate_BeforeRelation = pattern1.clonePattern(); newCandidate_BeforeRelation.add(lastPairOfPattern2); candidates.add(newCandidate_BeforeRelation); } /* * if the items of both patterns have an equal relation */ } else if (abstractionOfLastPairOfPattern1.hasEqualRelation() && abstractionOfLastPairOfPattern2.hasEqualRelation()) { //We only create a candidate /* EXAMPLE: if the first pattern is (P x), being x the last item, * and the second pattern is (P y), being y its last item, * * We have a possible candidate pattern: * C1 = (P x y), with x and y at the same time */ Pattern newCandidate_equalRelation; if (pattern1.compareTo(pattern2) < 0 && doNotExploreXY == false) { newCandidate_equalRelation = pattern1.clonePattern(); newCandidate_equalRelation.add(pairCreator.getItemAbstractionPair(lastPairOfPattern2.getItem(), qualitativeCreator.createAbstraction(true))); candidates.add(newCandidate_equalRelation); } else if (pattern1.compareTo(pattern2) > 0 && doNotExploreYX == false) { newCandidate_equalRelation = pattern2.clonePattern(); newCandidate_equalRelation.add(pairCreator.getItemAbstractionPair(lastPairOfPattern1.getItem(), qualitativeCreator.createAbstraction(true))); candidates.add(newCandidate_equalRelation); } /* * if the one pattern has an equal relation and the other has not */ } else { //We only create a candidate /* EXAMPLE: if the first pattern is (P x), being x the last item, * and the second pattern is (P < y), being y its last item, * * We have three possible candidate patterns: * C1 = (P x < y), with y appearing after x * * Conversely, * if the first pattern is (P < x), being x the last item, * and the second pattern is (P y), being y its last item, * * We have three possible candidate patterns: * C1 = (P y < x), with x appearing after y */ Pattern newCandidate_BeforeRelation = null; if (abstractionOfLastPairOfPattern1.hasEqualRelation() && doNotExploreX_Y == false) { newCandidate_BeforeRelation = pattern1.clonePattern(); newCandidate_BeforeRelation.add(lastPairOfPattern2); } else if (doNotExploreY_X == false) { newCandidate_BeforeRelation = pattern2.clonePattern(); newCandidate_BeforeRelation.add(lastPairOfPattern1); } if (newCandidate_BeforeRelation != null) { candidates.add(newCandidate_BeforeRelation); } } } return candidates; } /** * It executes the join operation over the Idlists of the equivalence * classesgiven as parameters. How the call is done it depends on the two * last items in the pattern extension, given as parameter. The minimum * support is provided to the method in order to avoid those join operation * that we know that lead to infrequent results. * * @param extension The candidate pattern previously made from the extension * of two frequent patterns * @param equivalenceClass_i Equivalence class from the pattern1 that * allowed creating the candidate extension * @param equivalenceClass_j Equivalence class from the pattern2 that * allowed creating the candidate extension * @param minSupport Minimum relative support * @return The IdList associated with the pattern extension previously * created. */ @Override public IDList join(Pattern extension, EquivalenceClass equivalenceClass_i, EquivalenceClass equivalenceClass_j, int minSupport) { // if(notExploreYX || notExploreXY) { // System.out.println("TEST"); // } //We get the last but one pair of the extension pattern ItemAbstractionPair lastButOnePair = extension.getLastButOneElement(); //We get the last pair extension pattern ItemAbstractionPair lastPair = extension.getLastElement(); /* We get the last pair of the identifier associated with the second Idlist, *i.e. the pattern2 last pair */ ItemAbstractionPair lastPairFromEquivalenceClass_j = equivalenceClass_j.getClassIdentifier().getLastElement(); /* * If the last pair of the extension has an equal relation */ if (((Abstraction_Qualitative) lastPair.getAbstraction()).hasEqualRelation()) { // PFV-2013 //And the last but one is not the same item if (!lastButOnePair.equals(lastPair)) { //We get the join of the IdList respecting the order given as parameters return equivalenceClass_i.getIdList().join(equivalenceClass_j.getIdList(), true, minSupport); } //If the last pair of the extension pattern does not have an equal relation } else { // //If that last pair of the extension is the same as the last pair of the second Idlist if (lastPairFromEquivalenceClass_j.equals(lastPair)) { //We get the join of the IdList respecting the order given as parameters return equivalenceClass_i.getIdList().join(equivalenceClass_j.getIdList(), false, minSupport); //Otherwise } else { // PFV-2013 //We revert the order in the call to the join operation for both IdLists return equivalenceClass_j.getIdList().join(equivalenceClass_i.getIdList(), false, minSupport); } } return null; } }