diff --git a/tests/correlatedPattern/basic/abstract.py b/tests/correlatedPattern/basic/abstract.py new file mode 100644 index 00000000..76d333d5 --- /dev/null +++ b/tests/correlatedPattern/basic/abstract.py @@ -0,0 +1,174 @@ +# Copyright (C) 2021 Rage Uday Kiran +# +# This program 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. +# +# This program 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 this program. If not, see . + +from abc import ABC as _ABC, abstractmethod as _abstractmethod +import time as _time +import csv as _csv +import pandas as _pd +from collections import defaultdict as _defaultdict +from itertools import combinations as _c +import os as _os +import os.path as _ospath +import psutil as _psutil +import validators as _validators +from urllib.request import urlopen as _urlopen +import sys as _sys +import math as _math + + +class _correlatedPatterns(_ABC): + """ + :Description: This abstract base class defines the variables and methods that every correlated pattern mining algorithm must + employ in PAMI + + :Attributes: + + iFile : str + Input file name or path of the input file + minSup: integer or float or str + The user can specify minSup either in count or proportion of database size. + If the program detects the data type of minSup is integer, then it treats minSup is expressed in count. + Otherwise, it will be treated as float. + Example: minSup=10 will be treated as integer, while minSup=10.0 will be treated as float + minAllConf: float + The user given minimum all confidence Ratio(should be in range of 0 to 1) + sep : str + This variable is used to distinguish items from one another in a transaction. The default seperator is tab space or \t. + However, the users can override their default separator + startTime:float + To record the start time of the algorithm + endTime:float + To record the completion time of the algorithm + finalPatterns: dict + Storing the complete set of patterns in a dictionary variable + oFile : str + Name of the output file to store complete set of correlated patterns + memoryUSS : float + To store the total amount of USS memory consumed by the program + memoryRSS : float + To store the total amount of RSS memory consumed by the program + + :Methods: + + startMine() + Calling this function will start the actual mining process + getPatterns() + This function will output all interesting patterns discovered by an algorithm + save(oFile) + This function will store the discovered patterns in an output file specified by the user + getPatternsAsDataFrame() + The function outputs the patterns generated by an algorithm as a data frame + getMemoryUSS() + This function outputs the total amount of USS memory consumed by a mining algorithm + getMemoryRSS() + This function outputs the total amount of RSS memory consumed by a mining algorithm + getRuntime() + This function outputs the total runtime of a mining algorithm + + """ + + def __init__(self, iFile, minSup, minAllConf, sep="\t"): + """ + :param iFile: Input file name or path of the input file + :type iFile: str + :param minSup: The user can specify minSup either in count or proportion of database size. + If the program detects the data type of minSup is integer, then it treats minSup is expressed in count. + Otherwise, it will be treated as float. + Example: minSup=10 will be treated as integer, while minSup=10.0 will be treated as float + :type minSup: int or float or str + :param minAllConf: The user given minimum all confidence Ratio(should be in range of 0 to 1) + :type minAllConf :float + :param sep: separator used to distinguish items from each other. The default separator is tab space. However, users can override the default separator + :type sep: str + """ + + self._iFile = iFile + self._sep = sep + self._minSup = minSup + self._minAllConf = minAllConf + self._finalPatterns = {} + self._oFile = str() + self._memoryRSS = float() + self._memoryUSS = float() + self._startTime = float() + self._endTime = float() + + + @_abstractmethod + def startMine(self): + """ + Code for the mining process will start from this function + """ + + pass + + @_abstractmethod + def getPatterns(self): + """ + Complete set of correlated patterns generated will be retrieved from this function + """ + + pass + + @_abstractmethod + def save(self, oFile): + """ + Complete set of correlated patterns will be saved in to an output file from this function + :param oFile: Name of the output file + :type oFile: csv file + """ + + pass + + @_abstractmethod + def getPatternsAsDataFrame(self): + """ + Complete set of correlated patterns will be loaded in to data frame from this function + """ + + pass + + @_abstractmethod + def getMemoryUSS(self): + """ + Total amount of USS memory consumed by the program will be retrieved from this function + """ + + pass + + @_abstractmethod + def getMemoryRSS(self): + """ + Total amount of RSS memory consumed by the program will be retrieved from this function + """ + + pass + + + @_abstractmethod + def getRuntime(self): + """ + Total amount of runtime taken by the program will be retrieved from this function + """ + + pass + + @_abstractmethod + def printResults(self): + """ + To print the results of execution. + """ + + pass \ No newline at end of file diff --git a/tests/correlatedPattern/basic/automated_test_CoMine.py b/tests/correlatedPattern/basic/automated_test_CoMine.py new file mode 100644 index 00000000..23a87dc7 --- /dev/null +++ b/tests/correlatedPattern/basic/automated_test_CoMine.py @@ -0,0 +1,18 @@ +import pandas as pd +from PAMI.correlatedPattern.basic.CoMine import CoMine as alg +import warnings + +warnings.filterwarnings("ignore") + +# CoMine algorithm from PAMI +def test_pami(dataset, min_sup=0.2, min_all_conf=0.2): + dataset = [",".join(i) for i in dataset] + with open("sample.csv", "w+") as f: + f.write("\n".join(dataset)) + obj = alg(iFile="sample.csv", minSup=min_sup, minAllConf=min_all_conf, sep=',') + obj.mine() + res = obj.getPatternsAsDataFrame() + res["Patterns"] = res["Patterns"].apply(lambda x: x.split()) + res["Support"] = res["Support"].apply(lambda x: x / len(dataset)) + pami = res + return pami diff --git a/tests/correlatedPattern/basic/automated_test_CoMinePlus.py b/tests/correlatedPattern/basic/automated_test_CoMinePlus.py new file mode 100644 index 00000000..bd5095cd --- /dev/null +++ b/tests/correlatedPattern/basic/automated_test_CoMinePlus.py @@ -0,0 +1,19 @@ +import pandas as pd +from PAMI.correlatedPattern.basic.CoMinePlus import CoMinePlus as alg +import warnings + +warnings.filterwarnings("ignore") + +# CoMine algorithm from PAMI +def test_pami(dataset, min_sup=0.2, min_all_conf=0.2): + dataset = [",".join(i) for i in dataset] + with open("sample.csv", "w+") as f: + f.write("\n".join(dataset)) + obj = alg(iFile="sample.csv", minSup=min_sup, minAllConf=min_all_conf, sep=',') + obj.mine() + res = obj.getPatternsAsDataFrame() + res["Patterns"] = res["Patterns"].apply(lambda x: x.split()) + res["Support"] = res["Support"].apply(lambda x: x / len(dataset)) + pami = res + return pami + diff --git a/tests/correlatedPattern/basic/automated_test_case_CoMine.py b/tests/correlatedPattern/basic/automated_test_case_CoMine.py new file mode 100644 index 00000000..5c6462c0 --- /dev/null +++ b/tests/correlatedPattern/basic/automated_test_case_CoMine.py @@ -0,0 +1,57 @@ +import unittest +from gen import generate_transactional_dataset +from automated_test_CoMine import test_pami +import warnings + +warnings.filterwarnings("ignore") + +class TestExample(unittest.TestCase): + + def test_num_patterns(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + + pami = test_pami(dataset) + # As we don't have a second method to compare, we just verify the length of pami + self.assertGreater(len(pami), 0, "No patterns were generated by CoMine") + + print("3 test cases for number of patterns have been passed") + + def test_equality(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + + pami = test_pami(dataset) + # Since we have no second method to compare, we just verify the patterns are generated + pami_patterns = sorted(list(pami["Patterns"])) + self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by CoMine") + + print("3 test cases for Patterns equality are passed") + + def test_support(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + + pami = test_pami(dataset) + # Since we have no second method to compare, we just verify the support values are generated + pami.sort_values(by="Support", inplace=True) + ps = list(pami["Support"]) + for support in ps: + self.assertTrue(support > 0, "Support value should be greater than 0") + + print("3 test cases for support equality are passed") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/correlatedPattern/basic/automated_test_case_CoMinePlus.py b/tests/correlatedPattern/basic/automated_test_case_CoMinePlus.py new file mode 100644 index 00000000..1c50f142 --- /dev/null +++ b/tests/correlatedPattern/basic/automated_test_case_CoMinePlus.py @@ -0,0 +1,47 @@ +import unittest +from gen import generate_transactional_dataset +from automated_test_CoMinePlus import test_pami +import warnings + +warnings.filterwarnings("ignore") + +class TestExample(unittest.TestCase): + def test_num_patterns(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + pami = test_pami(dataset) + self.assertGreater(len(pami), 0, "No patterns were generated by PAMI") + print("3 test cases for number of patterns have been passed") + + def test_equality(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + pami = test_pami(dataset) + pami_patterns = sorted(list(pami["Patterns"])) + self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") + print("3 test cases for Patterns equality are passed") + + def test_support(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + items = ["item-{}".format(i) for i in range(1, num_distinct_items + 1)] + dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) + pami = test_pami(dataset) + pami.sort_values(by="Support", inplace=True) + ps = list(pami["Support"]) + for support in ps: + self.assertTrue(support > 0, "Support value should be greater than 0") + print("3 test cases for support equality are passed") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/correlatedPattern/basic/gen.py b/tests/correlatedPattern/basic/gen.py new file mode 100644 index 00000000..4f5fba80 --- /dev/null +++ b/tests/correlatedPattern/basic/gen.py @@ -0,0 +1,20 @@ +import random +import warnings + +warnings.filterwarnings("ignore") + +def generate_transactional_dataset(num_transactions, items, max_items_per_transaction): + dataset = [] + for _ in range(num_transactions): + num_items = random.randint(1, max_items_per_transaction) + transaction = random.sample(items, num_items) + dataset.append(transaction) + return dataset + +# Example usage: +# num_distinct_items=20 +# num_transactions = 1000 +# max_items_per_transaction = 20 +# items=["item-{}".format(i) for i in range(1,num_distinct_items+1)] +# dataset = generate_transactional_dataset(num_transactions, items, max_items_per_transaction) +# print(dataset) diff --git a/tests/frequentPattern/basic/abstract.py b/tests/frequentPattern/basic/abstract.py new file mode 100644 index 00000000..814f25b2 --- /dev/null +++ b/tests/frequentPattern/basic/abstract.py @@ -0,0 +1,189 @@ +# Copyright (C) 2021 Rage Uday Kiran +# +# This program 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. +# +# This program 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 this program. If not, see . +# +# This program 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. +# +# This program 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 this program. If not, see . + +# from abc import ABC as _ABC, abstractmethod as _abstractmethod +from abc import ABC as _ABC, abstractmethod as _abstractmethod +import time as _time +import csv as _csv +import pandas as _pd +from collections import defaultdict as _defaultdict +from itertools import combinations as _c +import os as _os +import os.path as _ospath +import psutil as _psutil +import sys as _sys +import validators as _validators +from urllib.request import urlopen as _urlopen +import functools as _functools + + +class _frequentPatterns(_ABC): + """ + :Description: This abstract base class defines the variables and methods that every frequent pattern mining algorithm must + employ in PAMI + + :Attributes: + + iFile : str + Input file name or path of the input file + minSup: integer or float or str + The user can specify minSup either in count or proportion of database size. + If the program detects the data type of minSup is integer, then it treats minSup is expressed in count. + Otherwise, it will be treated as float. + Example: minSup=10 will be treated as integer, while minSup=10.0 will be treated as float + sep : str + This variable is used to distinguish items from one another in a transaction. The default seperator is tab space or \t. + However, the users can override their default separator + startTime:float + To record the start time of the algorithm + endTime:float + To record the completion time of the algorithm + finalPatterns: dict + Storing the complete set of patterns in a dictionary variable + oFile : str + Name of the output file to store complete set of frequent patterns + memoryUSS : float + To store the total amount of USS memory consumed by the program + memoryRSS : float + To store the total amount of RSS memory consumed by the program + + :Methods: + + startMine() + Calling this function will start the actual mining process + getPatterns() + This function will output all interesting patterns discovered by an algorithm + save(oFile) + This function will store the discovered patterns in an output file specified by the user + getPatternsAsDataFrame() + The function outputs the patterns generated by an algorithm as a data frame + getMemoryUSS() + This function outputs the total amount of USS memory consumed by a mining algorithm + getMemoryRSS() + This function outputs the total amount of RSS memory consumed by a mining algorithm + getRuntime() + This function outputs the total runtime of a mining algorithm + + """ + + def __init__(self, iFile, minSup, sep="\t"): + """ + :param iFile: Input file name or path of the input file + :type iFile: str or DataFrame + :param minSup: The user can specify minSup either in count or proportion of database size. + If the program detects the data type of minSup is integer, then it treats minSup is expressed in count. + Otherwise, it will be treated as float. + Example: minSup=10 will be treated as integer, while minSup=10.0 will be treated as float + :type minSup: int or float or str + :param sep: separator used to distinguish items from each other. The default separator is tab space. However, users can override the default separator + :type sep: str + """ + + self._iFile = iFile + self._sep = sep + self._minSup = minSup + self._finalPatterns = {} + self._oFile = str() + self._memoryUSS = float() + self._memoryRSS = float() + self._startTime = float() + self._endTime = float() + + @_abstractmethod + def startMine(self): + """ + Code for the mining process will start from this function + """ + + pass + + @_abstractmethod + def mine(self): + """ + Code for the mining process will start from this function + """ + + pass + + @_abstractmethod + def getPatterns(self): + """ + Complete set of frequent patterns generated will be retrieved from this function + """ + + pass + + @_abstractmethod + def save(self, oFile): + """ + Complete set of frequent patterns will be saved in to an output file from this function + :param oFile: Name of the output file + :type oFile: csvfile + """ + + pass + + @_abstractmethod + def getPatternsAsDataFrame(self): + """ + Complete set of frequent patterns will be loaded in to data frame from this function + """ + + pass + + @_abstractmethod + def getMemoryUSS(self): + """ + Total amount of USS memory consumed by the program will be retrieved from this function + """ + + pass + + @_abstractmethod + def getMemoryRSS(self): + """ + Total amount of RSS memory consumed by the program will be retrieved from this function + """ + + pass + + @_abstractmethod + def getRuntime(self): + """ + Total amount of runtime taken by the program will be retrieved from this function + """ + + pass + + @_abstractmethod + def printResults(self): + """ + To print result of the execution + """ + + pass \ No newline at end of file diff --git a/tests/frequentPattern/basic/automated_test_case_ECLAT.py b/tests/frequentPattern/basic/automated_test_case_ECLAT.py index a70248d3..87969355 100644 --- a/tests/frequentPattern/basic/automated_test_case_ECLAT.py +++ b/tests/frequentPattern/basic/automated_test_case_ECLAT.py @@ -33,7 +33,7 @@ def test_equality(self): pami_patterns = sorted(list(pami["Patterns"])) self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") - print("2 test cases for Patterns equality are passed") + print("3 test cases for Patterns equality are passed") def test_support(self): for _ in range(3): diff --git a/tests/frequentPattern/basic/automated_test_case_ECLATDiffset.py b/tests/frequentPattern/basic/automated_test_case_ECLATDiffset.py index 92014d00..e6007683 100644 --- a/tests/frequentPattern/basic/automated_test_case_ECLATDiffset.py +++ b/tests/frequentPattern/basic/automated_test_case_ECLATDiffset.py @@ -33,7 +33,7 @@ def test_equality(self): pami_patterns = sorted(list(pami["Patterns"])) self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") - print("2 test cases for Patterns equality are passed") + print("3 test cases for Patterns equality are passed") def test_support(self): for _ in range(3): diff --git a/tests/frequentPattern/basic/automated_test_case_apriori.py b/tests/frequentPattern/basic/automated_test_case_apriori.py index 808666db..25f6d617 100644 --- a/tests/frequentPattern/basic/automated_test_case_apriori.py +++ b/tests/frequentPattern/basic/automated_test_case_apriori.py @@ -33,7 +33,7 @@ def test_equality(self): pami_patterns = sorted(list(pami["Patterns"])) self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") - print("2 test cases for Patterns equality are passed") + print("3 test cases for Patterns equality are passed") def test_support(self): for _ in range(3): diff --git a/tests/frequentPattern/basic/automated_test_case_fpgrowth.py b/tests/frequentPattern/basic/automated_test_case_fpgrowth.py index 6e115bc0..70e2e7ed 100644 --- a/tests/frequentPattern/basic/automated_test_case_fpgrowth.py +++ b/tests/frequentPattern/basic/automated_test_case_fpgrowth.py @@ -33,7 +33,7 @@ def test_equality(self): pami_patterns = sorted(list(pami["Patterns"])) self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") - print("2 test cases for Patterns equality are passed") + print("3 test cases for Patterns equality are passed") def test_support(self): for _ in range(3): diff --git a/tests/recurringPattern/basic/abstract.py b/tests/recurringPattern/basic/abstract.py new file mode 100644 index 00000000..43d44d21 --- /dev/null +++ b/tests/recurringPattern/basic/abstract.py @@ -0,0 +1,164 @@ +# Copyright (C) 2021 Rage Uday Kiran +# +# This program 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. +# +# This program 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 this program. If not, see . +from abc import ABC as _ABC, abstractmethod as _abstractmethod +import time as _time +import csv as _csv +import pandas as _pd +from collections import defaultdict as _defaultdict +from itertools import combinations as _c +import os as _os +import os.path as _ospath +import psutil as _psutil +import sys as _sys +import validators as _validators +from urllib.request import urlopen as _urlopen + + +class _recurringPatterns(_ABC): + """ + :Description: This abstract base class defines the variables and methods that every periodic-frequent pattern mining algorithm must + employ in PAMI + + :Attributes: + + iFile : str + Input file name or path of the input file + + maxPer : int or float or str + The user can specify maxPer either in count or proportion of database size. + If the program detects the data type of maxPer is integer, then it treats maxPer is expressed in count. + Otherwise, it will be treated as float. + Example: maxPer=10 will be treated as integer, while maxPer=10.0 will be treated as float + minPS : int or float or str + The user can specify minPS either in count or proportion of database size. + If the program detects the data type of minPS is integer, then it treats minPS is expressed in count. + Otherwise, it will be treated as float. + Example: minPS=10 will be treated as integer, while minPS=10.0 will be treated as float + minRec : int or float or str + The user has to specify minRec in count. + sep : str + This variable is used to distinguish items from one another in a transaction. The default seperator is tab space or \t. + However, the users can override their default separator. + startTime : float + To record the start time of the algorithm + endTime : float + To record the completion time of the algorithm + finalPatterns : dict + Storing the complete set of patterns in a dictionary variable + oFile : str + Name of the output file to store complete set of periodic-frequent patterns + memoryUSS : float + To store the total amount of USS memory consumed by the program + memoryRSS : float + To store the total amount of RSS memory consumed by the program + + :Methods: + + startMine() + Mining process will start from here + getPatterns() + Complete set of patterns will be retrieved with this function + save(oFile) + Complete set of periodic-frequent patterns will be loaded in to a output file + getPatternsAsDataFrame() + Complete set of periodic-frequent patterns will be loaded in to data frame + getMemoryUSS() + Total amount of USS memory consumed by the program will be retrieved from this function + getMemoryRSS() + Total amount of RSS memory consumed by the program will be retrieved from this function + getRuntime() + Total amount of runtime taken by the program will be retrieved from this function + """ + + def __init__(self, iFile, maxPer, minPS, minRec,sep = '\t'): + """ + :param iFile: Input file name or path of the input file + :type iFile: str + :param minPS: The user can specify minPS either in count or proportion of database size. + If the program detects the data type of minSup is integer, then it treats minSup is expressed in count. + Otherwise, it will be treated as float. + Example: minSup=10 will be treated as integer, while minSup=10.0 will be treated as float + :type minPS: int or float or str + :param maxPer: The user can specify maxPer either in count or proportion of database size. + If the program detects the data type of maxPer is integer, then it treats maxPer is expressed in count. + Otherwise, it will be treated as float. + Example: maxPer=10 will be treated as integer, while maxPer=10.0 will be treated as float + :type maxPer: int or float or str + :param sep: the separator used in the database + :type sep: str + """ + + self._iFile = iFile + self._minPS = minPS + self._maxPer = maxPer + self._minRec = minRec + self._sep = sep + self._oFile = str() + self._finalPatterns = {} + self._startTime = float() + self._endTime = float() + self._memoryRSS = float() + self._memoryUSS = float() + + @_abstractmethod + def startMine(self): + """Code for the mining process will start from this function""" + + pass + + @_abstractmethod + def getPatterns(self): + """Complete set of periodic-frequent patterns generated will be retrieved from this function""" + + pass + + @_abstractmethod + def save(self, oFile): + """Complete set of periodic-frequent patterns will be saved in to an output file from this function + + :param oFile: Name of the output file + :type oFile: csv file + """ + + pass + + @_abstractmethod + def getPatternsAsDataFrame(self): + """Complete set of periodic-frequent patterns will be loaded in to data frame from this function""" + + pass + + @_abstractmethod + def getMemoryUSS(self): + """Total amount of USS memory consumed by the program will be retrieved from this function""" + + pass + + @_abstractmethod + def getMemoryRSS(self): + """Total amount of RSS memory consumed by the program will be retrieved from this function""" + pass + + @_abstractmethod + def getRuntime(self): + """Total amount of runtime taken by the program will be retrieved from this function""" + + pass + + @_abstractmethod + def printResults(self): + """ To print all the results of execution""" + + pass diff --git a/tests/recurringPattern/basic/automated_test_RPGrowth.py b/tests/recurringPattern/basic/automated_test_RPGrowth.py new file mode 100644 index 00000000..94b1b495 --- /dev/null +++ b/tests/recurringPattern/basic/automated_test_RPGrowth.py @@ -0,0 +1,19 @@ +import pandas as pd +from gen import generate_transactional_dataset +from PAMI.recurringPattern.basic import RPGrowth as alg +import warnings + +warnings.filterwarnings("ignore") + +# RPGrowth algorithm from PAMI +def test_pami(dataset, min_sup=0.2, max_period_count=5000, min_rec=1.8): + dataset = [",".join(map(str, i)) for i in dataset] + with open("sample.csv", "w+") as f: + f.write("\n".join(dataset)) + obj = alg.RPGrowth(iFile="sample.csv", minPS=min_sup, maxPer=max_period_count, minRec=min_rec, sep=',') + obj.startMine() # Using mine() instead of the deprecated startMine() + res = obj.getPatternsAsDataFrame() + res["Patterns"] = res["Patterns"].apply(lambda x: x.split()) + res["Support"] = res["Support"].apply(lambda x: x / len(dataset)) + pami = res + return pami diff --git a/tests/recurringPattern/basic/automated_test_case_RPGrowth.py b/tests/recurringPattern/basic/automated_test_case_RPGrowth.py new file mode 100644 index 00000000..2ed284b6 --- /dev/null +++ b/tests/recurringPattern/basic/automated_test_case_RPGrowth.py @@ -0,0 +1,52 @@ +import unittest +from gen import generate_transactional_dataset +from automated_test_RPGrowth import test_pami +import warnings + +warnings.filterwarnings("ignore") + +class TestRPGrowth(unittest.TestCase): + def test_num_patterns(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + dataset = generate_transactional_dataset(num_transactions, num_distinct_items, max_items_per_transaction) + + pami = test_pami(dataset) + # As we don't have a second method to compare, we just verify the length of pami + self.assertGreater(len(pami), 0, "No patterns were generated by PAMI") + + print("3 test cases for number of patterns have been passed") + + def test_equality(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + dataset = generate_transactional_dataset(num_transactions, num_distinct_items, max_items_per_transaction) + + pami = test_pami(dataset) + # Since we have no second method to compare, we just verify the patterns are generated + pami_patterns = sorted(list(pami["Patterns"])) + self.assertTrue(len(pami_patterns) > 0, "No patterns were generated by PAMI") + print("3 test cases for Patterns equality are passed") + + def test_support(self): + for _ in range(3): + num_distinct_items = 20 + num_transactions = 1000 + max_items_per_transaction = 20 + dataset = generate_transactional_dataset(num_transactions, num_distinct_items, max_items_per_transaction) + + pami = test_pami(dataset) + # Since we have no second method to compare, we just verify the support values are generated + pami.sort_values(by="Support", inplace=True) + ps = list(pami["Support"]) + for support in ps: + self.assertTrue(support > 0, "Support value should be greater than 0") + + print("3 test cases for support equality are passed") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/recurringPattern/basic/gen.py b/tests/recurringPattern/basic/gen.py new file mode 100644 index 00000000..ea321eee --- /dev/null +++ b/tests/recurringPattern/basic/gen.py @@ -0,0 +1,9 @@ +import random + +def generate_transactional_dataset(num_transactions, num_distinct_items, max_items_per_transaction): + dataset = [] + for _ in range(num_transactions): + num_items = random.randint(1, max_items_per_transaction) + transaction = random.sample(range(1, num_distinct_items + 1), num_items) + dataset.append(transaction) + return dataset