package ca.pfv.spmf.algorithms.sequentialpatterns.gsp_AGP.items;
import java.util.ArrayList;
import java.util.List;
/**Inspired in SPMF Implementation of a sequence.
* A sequence is defined as a list of itemsets and can have an identifier.
*
* 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 Sequence {
/**
* Number of items that appear in the sequence, i.e. the addition of the itemset sizes.
*/
private int numberOfItems = 0;
/**
* itemsets that compose the sequence.
*/
private final List<Itemset> itemsets = new ArrayList<Itemset>();
/**
* Sequence identifier.
*/
private int id;
/**
* Constructor for a Sequence.
* @param id an integer identifier
*/
public Sequence(int id) {
this.id = id;
}
/**
* Adds an itemset in the sequence. The itemset is inserte at the end of the sequence
* @param itemset the itemset to add
*/
public void addItemset(Itemset itemset) {
itemsets.add(itemset);
numberOfItems += itemset.size();
}
/**
* Adds an item to the last itemset of de sequence.
* @param item
*/
public void addItem(Item item) {
itemsets.get(size() - 1).addItem(item);
numberOfItems++;
}
/**
* Adds an item to the specified itemset
* @param indexItemset itemset where we want to add the item
* @param item item to add
*/
public void addItem(int indexItemset, Item item) {
itemsets.get(indexItemset).addItem(item);
numberOfItems++;
}
/**
* Add an item in the specified position of the specified itemset
* @param indexItemset Index of the itemset where we want to add the item
* @param indexItem Position in the itemset where we want to add the item
* @param item item to add
*/
public void addItem(int indexItemset, int indexItem, Item item) {
itemsets.get(indexItemset).addItem(indexItem, item);
numberOfItems++;
}
/**
* It removes a specified itemset
* @param indexItemset index of the itemset that we want to remove
* @return the removed itemset
*/
public Itemset remove(int indexItemset) {
Itemset itemset = itemsets.remove(indexItemset);
numberOfItems -= itemset.size();
return itemset;
}
/**
* It removes a specified item in a specified itemset.
* @param indexItemset index of the itemset where we want to remove an item
* @param indexItem index of the item that we want to remove
* @return the removed item
*/
public Item remove(int indexItemset, int indexItem) {
numberOfItems--;
return itemsets.get(indexItemset).removeItem(indexItem);
}
/**
* It removes a specified item in a specified itemset.
* @param indexItemset index of the itemset where we want to remove an item
* @param item item to remove
*/
public void remove(int indexItemset, Item item) {
itemsets.get(indexItemset).removeItem(item);
numberOfItems--;
}
/**
* It clones a sequence
* @return the cloned sequence
*/
public Sequence cloneSequence() {
Sequence sequence = new Sequence(getId());
for (Itemset itemset : itemsets) {
sequence.addItemset(itemset.cloneItemset());
}
return sequence;
}
/**
* The sequence as a string
* @return the string
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("");
for (Itemset itemset : itemsets) {
sb.append("{t=");
sb.append(itemset.getTimestamp());
sb.append(", ");
for (Item item : itemset.getItems()) {
String string = item.toString();
sb.append(string);
sb.append(' ');
}
sb.append('}');
}
return sb.append(" ").toString();
}
/**
* It returns the sequence identifier
* @return the sequence id of this sequence
*/
public int getId() {
return id;
}
/**
* Set the sequence identifier of this sequence
* @param integer the sequence id.
*/
void setId(Integer integer) {
id=integer;
}
/**
* Obtains a list the itemsets that compose the sequence
* @return the list of itemsets
*/
public List<Itemset> getItemsets() {
return itemsets;
}
/**
* It gets the ith itemset of this sequence
* @param index the index i
* @return the itemset
*/
public Itemset get(int index) {
return itemsets.get(index);
}
/**
* The number of itemsets that compose the sequence
* @return the number of itemsets
*/
public int size() {
return itemsets.size();
}
/**
* The number of items that compose the sequence
* @return the number of items
*/
public int getLength() {
return numberOfItems;
}
/**
* Get the time length of the sequence. It is equal to the last itemset timestamp minus the first itemset timestamp
* @return the time length
*/
public long getTimeLength() {
return itemsets.get(itemsets.size() - 1).getTimestamp() - itemsets.get(0).getTimestamp();
}
/**
* It returns a pair <itemset index, item index> indicanting the first appearance of an item in the sequence.
* The starting point where the method takes the search up is given as parameter.
* @param itemsetIndex Index of the first itemset where we will start to search
* @param itemIndex Index of the first item where we will start to search
* @param item Item to find
* @return the pair position if the item is found, otherwise null value
*/
public int[] searchForTheFirstAppearance(int itemsetIndex, int itemIndex, Item item) {
//We ensure that the itemset index is within the sequence
if (itemsetIndex < size()) {
//From that itemset
for (int i = itemsetIndex; i < itemsets.size(); i++) {
Itemset currentItemset = itemsets.get(i);
//the beginning index is 0 or itemIndex if we are in the itemset referred by itemsetIndex
int beginning = (i == (itemsetIndex)) ? (itemIndex) : 0;
//We search for the item in our current itemset
int pos = currentItemset.binarySearch(item);
//uncomment the line of below if you'd rather run a lineal search
//int pos = currentItemset.linealSearch(item);
//If the index returned by the search method is positive and equal or greater than our beginning item index
if (pos >= beginning) {
//We return the pair <i,pos>, where i is the current itemset index and pos the current item index in that itemset
return new int[]{i, pos};
}
}
}
return null;
}
/**
*
* @param item
* @param itemsetIndex
* @param ItemIndex
* @return
*/
/*public int[] searchForAnItemInLaterItemset(Item item, int itemsetIndex, int ItemIndex) {
if (itemsetIndex < size()) {
int firstItemset = itemsetIndex;
int firstItem = ItemIndex;
for (int i = firstItemset; i < itemsets.size(); i++) {
Itemset currentItemset = itemsets.get(i);
int beginning = (i == firstItemset) ? (firstItem) : 0;
//int pos = currentItemset.binarySearch(item);
//uncomment if you'd rather run a lineal search
int pos = currentItemset.linealSearch(item);
if (pos >= beginning) {
return new int[]{i,pos};
}
}
}
return null;
}*/
/**
* It returns a pair <itemset index, item index> indicanting the appearance of an item in the itemset given as parameter.
* The starting point where the method takes the search up is given as parameter
* @param item Item to find
* @param itemsetIndex Index of the first itemset where we will start to search
* @param itemIndex Index of the first item where we will start to search
* @return the pair position if the item is found, otherwise null value
*/
public int[] SearchForItemAtTheSameItemset(Item item, int itemsetIndex, int itemIndex) {
//We ensure that the itemset index is within the sequence
if (itemsetIndex < size()) {
//For the given itemset
Itemset currentItemset = itemsets.get(itemsetIndex);
//We search for the item in our current itemset
int pos = currentItemset.binarySearch(item);
//uncomment the line of below if you'd rather run a lineal search
//int pos = currentItemset.linealSearch(item);
//If the index returned by the search method is positive and equal or greater than our beginning item index
if (pos >= itemIndex) {
//We return the pair <itemsetIndex,pos>, where itemsetIndex is the current itemset index and pos the current item index in that itemset
return new int[]{itemsetIndex, pos};
}
}
return null;
}
/**
* It returns a pair <itemset index, item index> indicanting the first appearance
* of an item in the sequence that appears in a itemset that has a temporal
* distance with respect to the current itemset, as it the given parameter.
* The starting point where the method takes the search up is given as parameter.
* @param item Item to find
* @param itemsetIndex Index of the first itemset where we will start to search
* @param itemIndex Index of the first item where we will start to search
* @param temporalDistance Temporal distance at which the item to find should be
* @return the pair position if the item is found, otherwise null value
*/
public int[] searchForItemInAConcreteTemporalDistance(Item item, int itemsetIndex, int itemIndex, long temporalDistance) {
//We ensure that the first itemset index is within the sequence
if (itemsetIndex < size()) {
//We keep the current timestamp
long initialTimestamp = itemsets.get(itemsetIndex).getTimestamp();
//And the timestamp of the itemset where the item should be, if it is the case
long objectiveTimestamp = initialTimestamp + temporalDistance;
//we establish the itemset index starting from the next itemset
int itemset = itemsetIndex + 1;
//while we still have itemsets in the sequence and they have a timestamp less than that in which we are interested, we skip them
while (itemset < itemsets.size() && itemsets.get(itemset).getTimestamp() < objectiveTimestamp) {
itemset++;
}
//When the loop is over, if the itemset timestamp is the same as that we are expecting
if (itemset < itemsets.size() && itemsets.get(itemset).getTimestamp() == objectiveTimestamp) {
Itemset currentItemset = itemsets.get(itemset);
//We search for the item in our current itemset
int pos = currentItemset.binarySearch(item);
//uncomment the line of below if you'd rather run a lineal search
//int pos = currentItemset.linealSearch(item);
//If the index returned by the search method is positive and equal or greater than our beginning item index
if (pos >= 0) {
//We return the pair <itemset,pos>, where itemset is the current itemset index and pos the current item index in that itemset
return new int[]{itemset, pos};
}
}
}
return null;
}
/**
* It gives the number of items that appears after a concrete position of the sequence
* @param itemsetIndex the itemset index in which we will start to look for
* @param itemIndex the item index in which we will start to look for
* @return the number of items
*/
public int numberOfItemsAfterPositionIth(int itemsetIndex, int itemIndex){
int size=0;
if(itemsetIndex<itemsets.size()-1){
int currentItemset=itemsetIndex+1;
for(int i=currentItemset;i<itemsets.size();i++){
size+=itemsets.get(currentItemset).size();
}
}
size+=(itemsets.get(itemsetIndex).size()-itemIndex-1);
return size;
}
}