# -*- coding: utf-8 -*-
"""
Created on Thu Apr 25 17:55:14 2019

@author: fede9
"""

import datetime
import math
import mysql.connector
from SPTree2 import SPTree

#input coordinate stringhe
#output coordinate intere 
def parserLocation(lat, long):
   assert(len(lat) == 13) #se non è un valore corretto di latitudine
   strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
   
   long = long.strip() #elimino tabulazioni
   assert(len(long) == 14) #se non è un valore corretto di lognitudine
   strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
   #print(str)
   return [int(strlat)/100000000, int(strlong)/100000000]
#end parserLocation
   
def distanceLocation(lat1, long1, lat2, long2) :
   #conversione in radianti
   lat1 = round(lat1*(2*math.pi)/360, 2)
   long1 = round(long1*(2*math.pi)/360, 2)
   lat2 = round(lat2*(2*math.pi)/360, 2)
   long2 = round(long2*(2*math.pi)/360, 2)
   
   
   dist = math.acos( math.sin(lat1) * math.sin(lat2) 
      + math.cos(lat1) * math.cos(lat2) * math.cos(long1-long2)) * 6371
   
   assert(dist >= 0)
   return dist
#end distanceLocation
   
#input data e ora stringa
#output giorni (intero)
def distanceTime(timeE, timeP) :
   assert(len(timeE) == 16)
   assert(len(timeP) == 16)
   
   daysE = int(timeE[0:2])
   monthsE = int(timeE[3:5])
   yearsE = int(timeE[6:10])
   daysP = int(timeP[0:2])
   monthsP = int(timeP[3:5])
   yearsP = int(timeP[6:10])
   
   dE = datetime.date(yearsE, monthsE, daysE)
   dP = datetime.date(yearsP, monthsP, daysP)
   
   return abs((dE - dP).days)
#end distanceTime
   
#input event, type evet
#output neigborhood event
def neighborhood(event, typeF) :
   #raggio spaziale della location (km)
   r = 0.1
   #raggio temporale
   t = 2
   #neighbothood with respect to event type
   nfe = set()
   
   sql = "SELECT * FROM " + table
   mycursor.execute(sql)
   
   for crime in mycursor:
      #print(event)
      #print(crime[5])
      [late, longe] = parserLocation(event[4], event[5])
      [latp, longp] = parserLocation(crime[4], crime[5])
      #se di tipo specificato
      if crime[1] == typeF:
         #se è entro il raggio spaziale
         if distanceLocation(late, longe, latp, longp) <= r:
            timee = event[2]
            timep = crime[2]
            diffDays = distanceTime(timee, timep)
            #se è entro il raggio temporale
            #escludo se stesso
            if diffDays <= t and event != crime:
               nfe.add(crime[0])
   #end for
   return nfe
#end neighborhood
   
#input tipo di evento
#output insieme ti tutti gli eventi di quel tipo
def setD(typeD) :
   setReturn = set()
   #print(typeD)
   sql = "SELECT * FROM " + table + " WHERE offence_code_group LIKE \"" + typeD + "\""   
   #print(sql)
   mycursor.execute(sql)
   
   for record in mycursor:
      setReturn.add(record[0])
   return setReturn
#end setD

#input insiemeSet precedente e tipo corrente
#output insieme di istanze associate
def setInstances(prevSet, currentType):
   set_return = set()

   for event in prevSet:
      sql = "SELECT * FROM " + table + " WHERE incident_num = \"" + event + "\""
      mycursor.execute(sql)
      #la tupla che mi interessa
      ev = mycursor.fetchone()
      #print(ev)
      neig = neighborhood(ev, currentType)
      #print(neig)
      set_return = set_return.union(neig)
   return set_return
#end setInstance
   
#candidate generation
#input un insieme di sequenze significative di lunghezza uguale
#assumo che l'input sia di una lista di sequenze (che a loro volta sono liste)
#output albero con set di candidati 
def candidateGen(setSeq, tree) :
   
   for seq in setSeq :
      #se la sequenza precedente esiste
      node = tree.searchNode(seq[:len(seq)-1])
      if node != 0 :
         #calcolo nuovo setInstances tra node e tipo di seq[len(seq)-1]
         newSet = setInstances(node.set, seq[len(seq)-1])
         print("inserito: " + str(seq))
         #creo un set che è l'union tra set di node e neighborhood trovato
         tree.insertNode(seq, newSet) #gli aggiungo l'insieme del nodo
      else:
         print("error candidate Gen - node non trovato")
#end caditateGen

#calcola il valore di Partitipation rateo di questo nodo
def computePR(n1, tree):
   typeD = n1.value
   nSet = tree.searchNode([typeD])
   if (nSet is None):
      print("tipo non trovato")
      return
   
   #print("esito searchPR: " + str(nSet))
   ins = len(n1.set)
   d_set = len(nSet.set)
   #print(ins)
   #print(d_set)
   pr = ins / d_set
   return pr
#end computePR
   
def computePI(seq, tree):
   length = len(seq)
   n = tree.searchNode(seq)
   #se il nodo non esiste allora lo segnalo in output
   if n is None:
      return None
   if length <= 2: #caso base
      return computePR(n, tree)
   else:
      pr = computePR(n,tree)
      pi = computePI(seq[:length-1], tree)
      return min(pi, pr)
#end computePI

#verifica se all'interno di una sequenza (list) vi siano elementi doppi
#output true se non sono presenti due tipi uguali
#output false se sono presenti due tipi uguali
def checkDouble(seq):
   seqSet = set(seq)
   if len(seq) == len(seqSet):
      return True
   else:
      return False
#end checkDouble

def candidateGenTree(length, tree):
   candidates = tree.candidates
   for cand in candidates:
      if len(cand) == length-1:
         nodeCand = tree.searchNode(cand)
         if nodeCand is None:
            print("cand not found, seq: " + str(cand))
            continue
         children = nodeCand.parent2.children
         for child in children:
            newSeq = cand[:]
            newSeq.append(child.value)
            if checkDouble(newSeq):
   #            print("cand: " + str(cand))
   #            print("newSeq: " + str(newSeq))
               #print("cand: " + str(cand) + ", newSeq: " + str(newSeq) + " ...")
               newSet = setInstances(nodeCand.set, child.value)
               tree.insertNode(newSeq, newSet)
               print("inserito: " + str(newSeq))
#end candidateGenTree

#input lista di [sequenza, pi]
#output coppia [sequenza, pi] con pi minore
def seqPIMin(seqList, num):
   teta = 1
   i = 0
   #verifico che vi siano n-1 elementi nella lista che superino il nuovo teta
   while i < num:
      #aggiorno il newteta se è il massimo dei minori di teta
      newteta = 0
      for el in seqList:
         if el[1] < teta and el[1] > newteta:
            newteta = el[1]
            #print(newteta)
      teta = newteta
      i = 0
      #verifico che vi siano n-1 elementi nella lista che superino il nuovo teta
      for el in seqList:
         if el[1] >= teta:
            i += 1
   return teta
#end seqPIMin

#faccio il refreshTree, in base al teta elimino tutte le sequenze che hanno un teta minore dall'albero
def refreshTree(tree, teta):
   cands = tree.candidates
   for cand in cands:
      pi = computePI(cand, tree)
      #questo controllo mi permette di evitare sequenze non più presenti
      if pi is None:
         continue
      if pi < teta:
         delNode = tree.searchNode(cand)
         if delNode is None:
            print(str(cand) + " not found")
            tree.candidates.remove(cand)
            continue
         delNode.parent1.children.remove(delNode)
         tree.candidates.remove(cand)

#verifyCandidates, si occupa del calcolo del pi di ciascun candidato
#output lista di coppie sequenza - pi
def verifyCandidates(lun, teta, tree):
   cand = tree.candidates
   ret = []
   
   for seq in cand:
      if len(seq) == lun: 
         pi = computePI(seq, tree)
         #questo controllo mi permette di evitare sequenze non più presenti
         if pi is None:
            continue
         
         if pi >= teta:
            ret.append([seq, pi])
         else:
            #taglio l'albero relativo a questa computazione
            n = tree.searchNode(seq)
            if n is None:
               print("error")
               return
            
            for child in n.parent1.children:
               if child.value == seq[len(seq)-1]:
                  n.parent1.children.remove(child)
                  print("eliminato ramo albero")
                  tree.candidates.remove(seq)
                  break
         
   return ret
#end verifyCandidates

#verifyTopCandidates, si occupa del calcolo del pi di ciascun candidato
#estraendo solo i primi n elementi in base al valore di pi
#output lista di coppie [sequenza - pi] (n elementi)
def verifyTopCandidates(lun, teta, top, num, tree):
   
   for seq in tree.candidates:
      if len(seq) == lun: 
         pi = computePI(seq, tree)
         #questo controllo mi permette di evitare sequenze non più presenti
         if pi is None:
            continue
         if pi >= teta:
            #se ho ancora spazio nel top
            if len(top) < num-1:
               top.append([seq, pi])
            #se sono al limite del top
            elif len(top) == num-1:
               top.append([seq, pi])
               teta = seqPIMin(top, num)
               print("new teta (==): " + str(teta))
            else:
               #se ho riempito tutto il top
               top.append([seq, pi])
               if pi > teta:
                  teta = seqPIMin(top, num)
                  print("new teta (>): " + str(teta))
                  #cancello tutti i top con pi < teta
                  for el in top:
                     if el[1] < teta:
                        top.remove(el)
                        #elimino il relativo sotto-albero alle sequenze eliminate
                        seqdel = el[0]
                        n = tree.searchNode(seqdel)
                        if n is None:
                           print("error top candidates, seq non trovata: " + str(seqdel))
                           continue
                        
                        for child in n.parent1.children:
                           if child.value == seqdel[len(seqdel)-1]:
                              n.parent1.children.remove(child)
                              print("eliminato ramo di: " + str(seqdel) + ", che ha pi = " + str(el[1]))
                              break
                  #end for
                  #cancello tutti le seq lunghe lun dei candidates
                  for cand in tree.candidates:
                     if len(cand[0])==lun and cand[1] < teta:
                        tree.candidates.remove(cand)
                        #elimino il relativo sotto-albero
                        seqdel = cand[0]
                        n = tree.searchNode(seqdel)
                        if n is None:
                           print("error cand candidates, seq non trovata: " + str(seqdel))
                           continue
                           
                        for child in n.parent1.children:
                           if child.value == seqdel[len(seqdel)-1]:
                              n.parent1.children.remove(child)
                              print("delete ramo di: " + str(seqdel) + ", che ha pi = " + str(cand[1]))
                              break
                  #end for
               #end if
         else:
            #se il pi ha un teta mirore rispetto al limite
            #taglio l'albero relativo a questa computazione
            n = tree.searchNode(seq)
            if n is None:
               print("error, seq non trovata: " + str(seq))
               continue
            
            for child in n.parent1.children:
               if child.value == seq[len(seq)-1]:
                  n.parent1.children.remove(child)                              
                  tree.candidates.remove(seq)
                  print("eliminato(2) ramo di: " + str(seq) + ", che ha pi = " + str(pi))
                  break
         
   return top
#end verifyCandidates

#algroritmo STBF senza il top e l'update della teta
def stbfMiner():
   #teta valore di threshold rispetto al pi
   teta = 0.7
   #creo l'albero delle sequenze   
   tree = SPTree()   
   #prendo ciascun tipo di evento
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   #inserendo il primo layer di albero
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   #genero i pattern di lunghezza 2
   #per ora sono handmade
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"],
           ["Larceny", "Aggravated Assault"], ["Commercial Burglary", "Other Burglary"]]
   
   print("... generating candidates(2)")
   candidateGen(seq2, tree)
   #faccio la verifyCandidates(2)
   print(tree)
   print("\n... verifying candidates(2)")
   val = verifyCandidates(2, teta, tree)
   for el in val:
      print(str(el[0]) + " - " + str(el[1]))
      
   print("\n... generating candidates(3)")
   candidateGenTree(3, tree)
   print("\n... verifying candidates(3)")
   val = verifyCandidates(3, teta, tree)
   for el in val:
      print(str(el[0]) + " - " + str(el[1]))
   
   print("\n" + str(tree))
#end stbfMiner
   
################ stbfMiner Top
#algroritmo STBF con il top e l'update della teta
def stbfMinerTop():
   #teta valore di threshold rispetto al pi
   #top è l'array in cui salvo i migliori risultati
   #num è il numero di risultati desiderati
   teta = 0.25
   top = []
   num = 20
   #creo l'albero delle sequenze   
   tree = SPTree()   
   #prendo ciascun tipo di evento
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   #inserendo il primo layer di albero
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   #genero i pattern di lunghezza 2
   #per ora sono handmade
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"],
           ["Larceny", "Aggravated Assault"], ["Commercial Burglary", "Other Burglary"],
           ["Residential Burglary", "Auto Theft"],["Homicide", "Other Burglary"],
           ["Other Burglary", "Larceny"],["Larceny From Motor Vehicle", "Aggravated Assault"],
           ["Larceny", "Auto Theft"]]
   
   print("... generating candidates(2)")
   candidateGen(seq2, tree)
   #faccio la verifyCandidates(2)
   print(tree)
   print("\n... verifying candidates(2)")
   top = verifyTopCandidates(2, teta, top, num, tree)
   i = 0
   for el in top:
      i += 1
      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
      
   print("\n... generating candidates(3)")
   candidateGenTree(3, tree)
   print("\n... verifying candidates(3)")
   top = verifyTopCandidates(3, teta, top, num, tree)
   if top is None:
      print("Top none")
   i = 0
   for el in top:
      i += 1
      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
   
#   print("\n\n" + str(tree))
   tree.refreshCandidates()
   print("\nDopo il refresh\n" + str(tree))
   
#   print("\n... generating candidates(4)")
#   candidateGenTree(4, tree)
#   print("\n... verifying candidates(4)")
#   top = verifyTopCandidates(4, teta, top, num, tree)
#   if top is None:
#      print("Top none")
#   i = 0
#   for el in top:
#      i += 1
#      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
#   
##   print("\n\n" + str(tree))
#   tree.refreshCandidates()
#   print("\nDopo il refresh\n" + str(tree))
##############################################################
   #TEST

def testTree() :
   t = SPTree(["A", "B", "C"])
   #inserisco i sets
   sA = set()
   sA.add("10")
   sB = set()
   sB.add('IT01R003')
   sC = set()
   sC.add('30')
   
   nA = t.searchNode(["A"])
   nB = t.searchNode(["B"])
   nC = t.searchNode(["C"])  
   
   nA.insertSet(sA)
   nB.insertSet(sB)
   nC.insertSet(sC)
   print(nA)
   print(nB)
   print(nC)
#end testTree

def testCrimeTree() :
   
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   seq3 = [["Commercial Burglary", "Homicide", "Auto Theft"], 
           ["Larceny From Motor Vehicle", "Homicide", "Auto Theft"],
           ["Aggravated Assault", "Auto Theft", "Residential Burglary"],
           ["Aggravated Assault", "Robbery", "Larceny"], 
           ["Larceny From Motor Vehicle", "Commercial Burglary", "Auto Theft"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree)
   candidateGen(seq3, tree)
   
   print(tree)
   
   for tipo in tree.root.children:
      print(tipo.value + ": " + str(len(tipo.set)))
#end testCrimeTree
      
def testPR() :
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree) #inserisco sequenze di 2 elementi
   
   for seq in seq2:
      n = tree.searchNode(seq)
      pr1 = computePR(n, tree)
      print("seq: " + str(seq) + " - pr: " + str(pr1))
   
#end testPR
      
def testPI() :
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   seq3 = [["Commercial Burglary", "Homicide", "Auto Theft"], 
           ["Larceny From Motor Vehicle", "Homicide", "Auto Theft"],
           ["Aggravated Assault", "Auto Theft", "Residential Burglary"],
           ["Aggravated Assault", "Robbery", "Larceny"], 
           ["Larceny From Motor Vehicle", "Commercial Burglary", "Auto Theft"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree) #inserisco sequenze di 2 elementi
   candidateGen(seq3, tree)
   i=1
   for seq in seq2:
      pi = computePI(seq, tree)
      print(str(i) + ". " + str(seq) + " - pi: " + str(pi))
      i += 1
   for seq in seq3:
      pi = computePI(seq, tree)
      print(str(i) + ". " + str(seq) + " - pi: " + str(pi))
      i += 1
#end  testPI
#############################
   #MAIN
if __name__ == "__main__":
   mydb = mysql.connector.connect(
         host = "localhost",
         user = "root",
         passwd = "fedeServer33",
         database = "bostoncrime"
         )
   table = "crimedata2018small"
   mycursor = mydb.cursor()
   
#   print("Testing testTree :")
#   testTree()
   
#   print("Testing testCrimeTree :")
#   testCrimeTree()
   
#   print("Testing testPR :")
#   testPR()
   
#   print("Testing testPI :")
#   testPI()
   
#   print("Testing STBF Miner")
#   stbfMiner()
   
   print("Testing STBF Miner Top")
   stbfMinerTop()
   
   
   mycursor.close()
84840eebc2bdd5c27a0e0762a31c58c6c8dcb783
<mask token>


def parserLocation(lat, long):
    assert len(lat) == 13
    strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
    long = long.strip()
    assert len(long) == 14
    strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
    return [int(strlat) / 100000000, int(strlong) / 100000000]


<mask token>


def distanceTime(timeE, timeP):
    assert len(timeE) == 16
    assert len(timeP) == 16
    daysE = int(timeE[0:2])
    monthsE = int(timeE[3:5])
    yearsE = int(timeE[6:10])
    daysP = int(timeP[0:2])
    monthsP = int(timeP[3:5])
    yearsP = int(timeP[6:10])
    dE = datetime.date(yearsE, monthsE, daysE)
    dP = datetime.date(yearsP, monthsP, daysP)
    return abs((dE - dP).days)


def neighborhood(event, typeF):
    r = 0.1
    t = 2
    nfe = set()
    sql = 'SELECT * FROM ' + table
    mycursor.execute(sql)
    for crime in mycursor:
        [late, longe] = parserLocation(event[4], event[5])
        [latp, longp] = parserLocation(crime[4], crime[5])
        if crime[1] == typeF:
            if distanceLocation(late, longe, latp, longp) <= r:
                timee = event[2]
                timep = crime[2]
                diffDays = distanceTime(timee, timep)
                if diffDays <= t and event != crime:
                    nfe.add(crime[0])
    return nfe


<mask token>


def setInstances(prevSet, currentType):
    set_return = set()
    for event in prevSet:
        sql = ('SELECT * FROM ' + table + ' WHERE incident_num = "' + event +
            '"')
        mycursor.execute(sql)
        ev = mycursor.fetchone()
        neig = neighborhood(ev, currentType)
        set_return = set_return.union(neig)
    return set_return


def candidateGen(setSeq, tree):
    for seq in setSeq:
        node = tree.searchNode(seq[:len(seq) - 1])
        if node != 0:
            newSet = setInstances(node.set, seq[len(seq) - 1])
            print('inserito: ' + str(seq))
            tree.insertNode(seq, newSet)
        else:
            print('error candidate Gen - node non trovato')


def computePR(n1, tree):
    typeD = n1.value
    nSet = tree.searchNode([typeD])
    if nSet is None:
        print('tipo non trovato')
        return
    ins = len(n1.set)
    d_set = len(nSet.set)
    pr = ins / d_set
    return pr


def computePI(seq, tree):
    length = len(seq)
    n = tree.searchNode(seq)
    if n is None:
        return None
    if length <= 2:
        return computePR(n, tree)
    else:
        pr = computePR(n, tree)
        pi = computePI(seq[:length - 1], tree)
        return min(pi, pr)


<mask token>


def seqPIMin(seqList, num):
    teta = 1
    i = 0
    while i < num:
        newteta = 0
        for el in seqList:
            if el[1] < teta and el[1] > newteta:
                newteta = el[1]
        teta = newteta
        i = 0
        for el in seqList:
            if el[1] >= teta:
                i += 1
    return teta


def refreshTree(tree, teta):
    cands = tree.candidates
    for cand in cands:
        pi = computePI(cand, tree)
        if pi is None:
            continue
        if pi < teta:
            delNode = tree.searchNode(cand)
            if delNode is None:
                print(str(cand) + ' not found')
                tree.candidates.remove(cand)
                continue
            delNode.parent1.children.remove(delNode)
            tree.candidates.remove(cand)


def verifyCandidates(lun, teta, tree):
    cand = tree.candidates
    ret = []
    for seq in cand:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                ret.append([seq, pi])
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error')
                    return
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        print('eliminato ramo albero')
                        tree.candidates.remove(seq)
                        break
    return ret


<mask token>


def stbfMinerTop():
    teta = 0.25
    top = []
    num = 20
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary'], ['Residential Burglary',
        'Auto Theft'], ['Homicide', 'Other Burglary'], ['Other Burglary',
        'Larceny'], ['Larceny From Motor Vehicle', 'Aggravated Assault'], [
        'Larceny', 'Auto Theft']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    top = verifyTopCandidates(2, teta, top, num, tree)
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    top = verifyTopCandidates(3, teta, top, num, tree)
    if top is None:
        print('Top none')
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    tree.refreshCandidates()
    print('\nDopo il refresh\n' + str(tree))


def testTree():
    t = SPTree(['A', 'B', 'C'])
    sA = set()
    sA.add('10')
    sB = set()
    sB.add('IT01R003')
    sC = set()
    sC.add('30')
    nA = t.searchNode(['A'])
    nB = t.searchNode(['B'])
    nC = t.searchNode(['C'])
    nA.insertSet(sA)
    nB.insertSet(sB)
    nC.insertSet(sC)
    print(nA)
    print(nB)
    print(nC)


def testCrimeTree():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    print(tree)
    for tipo in tree.root.children:
        print(tipo.value + ': ' + str(len(tipo.set)))


<mask token>

<mask token>


def parserLocation(lat, long):
    assert len(lat) == 13
    strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
    long = long.strip()
    assert len(long) == 14
    strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
    return [int(strlat) / 100000000, int(strlong) / 100000000]


<mask token>


def distanceTime(timeE, timeP):
    assert len(timeE) == 16
    assert len(timeP) == 16
    daysE = int(timeE[0:2])
    monthsE = int(timeE[3:5])
    yearsE = int(timeE[6:10])
    daysP = int(timeP[0:2])
    monthsP = int(timeP[3:5])
    yearsP = int(timeP[6:10])
    dE = datetime.date(yearsE, monthsE, daysE)
    dP = datetime.date(yearsP, monthsP, daysP)
    return abs((dE - dP).days)


def neighborhood(event, typeF):
    r = 0.1
    t = 2
    nfe = set()
    sql = 'SELECT * FROM ' + table
    mycursor.execute(sql)
    for crime in mycursor:
        [late, longe] = parserLocation(event[4], event[5])
        [latp, longp] = parserLocation(crime[4], crime[5])
        if crime[1] == typeF:
            if distanceLocation(late, longe, latp, longp) <= r:
                timee = event[2]
                timep = crime[2]
                diffDays = distanceTime(timee, timep)
                if diffDays <= t and event != crime:
                    nfe.add(crime[0])
    return nfe


<mask token>


def setInstances(prevSet, currentType):
    set_return = set()
    for event in prevSet:
        sql = ('SELECT * FROM ' + table + ' WHERE incident_num = "' + event +
            '"')
        mycursor.execute(sql)
        ev = mycursor.fetchone()
        neig = neighborhood(ev, currentType)
        set_return = set_return.union(neig)
    return set_return


def candidateGen(setSeq, tree):
    for seq in setSeq:
        node = tree.searchNode(seq[:len(seq) - 1])
        if node != 0:
            newSet = setInstances(node.set, seq[len(seq) - 1])
            print('inserito: ' + str(seq))
            tree.insertNode(seq, newSet)
        else:
            print('error candidate Gen - node non trovato')


def computePR(n1, tree):
    typeD = n1.value
    nSet = tree.searchNode([typeD])
    if nSet is None:
        print('tipo non trovato')
        return
    ins = len(n1.set)
    d_set = len(nSet.set)
    pr = ins / d_set
    return pr


def computePI(seq, tree):
    length = len(seq)
    n = tree.searchNode(seq)
    if n is None:
        return None
    if length <= 2:
        return computePR(n, tree)
    else:
        pr = computePR(n, tree)
        pi = computePI(seq[:length - 1], tree)
        return min(pi, pr)


<mask token>


def seqPIMin(seqList, num):
    teta = 1
    i = 0
    while i < num:
        newteta = 0
        for el in seqList:
            if el[1] < teta and el[1] > newteta:
                newteta = el[1]
        teta = newteta
        i = 0
        for el in seqList:
            if el[1] >= teta:
                i += 1
    return teta


def refreshTree(tree, teta):
    cands = tree.candidates
    for cand in cands:
        pi = computePI(cand, tree)
        if pi is None:
            continue
        if pi < teta:
            delNode = tree.searchNode(cand)
            if delNode is None:
                print(str(cand) + ' not found')
                tree.candidates.remove(cand)
                continue
            delNode.parent1.children.remove(delNode)
            tree.candidates.remove(cand)


def verifyCandidates(lun, teta, tree):
    cand = tree.candidates
    ret = []
    for seq in cand:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                ret.append([seq, pi])
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error')
                    return
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        print('eliminato ramo albero')
                        tree.candidates.remove(seq)
                        break
    return ret


def verifyTopCandidates(lun, teta, top, num, tree):
    for seq in tree.candidates:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                if len(top) < num - 1:
                    top.append([seq, pi])
                elif len(top) == num - 1:
                    top.append([seq, pi])
                    teta = seqPIMin(top, num)
                    print('new teta (==): ' + str(teta))
                else:
                    top.append([seq, pi])
                    if pi > teta:
                        teta = seqPIMin(top, num)
                        print('new teta (>): ' + str(teta))
                        for el in top:
                            if el[1] < teta:
                                top.remove(el)
                                seqdel = el[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error top candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('eliminato ramo di: ' + str(
                                            seqdel) + ', che ha pi = ' + str(el[1])
                                            )
                                        break
                        for cand in tree.candidates:
                            if len(cand[0]) == lun and cand[1] < teta:
                                tree.candidates.remove(cand)
                                seqdel = cand[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error cand candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('delete ramo di: ' + str(seqdel) +
                                            ', che ha pi = ' + str(cand[1]))
                                        break
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error, seq non trovata: ' + str(seq))
                    continue
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        tree.candidates.remove(seq)
                        print('eliminato(2) ramo di: ' + str(seq) +
                            ', che ha pi = ' + str(pi))
                        break
    return top


def stbfMiner():
    teta = 0.7
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    val = verifyCandidates(2, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    val = verifyCandidates(3, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n' + str(tree))


def stbfMinerTop():
    teta = 0.25
    top = []
    num = 20
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary'], ['Residential Burglary',
        'Auto Theft'], ['Homicide', 'Other Burglary'], ['Other Burglary',
        'Larceny'], ['Larceny From Motor Vehicle', 'Aggravated Assault'], [
        'Larceny', 'Auto Theft']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    top = verifyTopCandidates(2, teta, top, num, tree)
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    top = verifyTopCandidates(3, teta, top, num, tree)
    if top is None:
        print('Top none')
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    tree.refreshCandidates()
    print('\nDopo il refresh\n' + str(tree))


def testTree():
    t = SPTree(['A', 'B', 'C'])
    sA = set()
    sA.add('10')
    sB = set()
    sB.add('IT01R003')
    sC = set()
    sC.add('30')
    nA = t.searchNode(['A'])
    nB = t.searchNode(['B'])
    nC = t.searchNode(['C'])
    nA.insertSet(sA)
    nB.insertSet(sB)
    nC.insertSet(sC)
    print(nA)
    print(nB)
    print(nC)


def testCrimeTree():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    print(tree)
    for tipo in tree.root.children:
        print(tipo.value + ': ' + str(len(tipo.set)))


def testPR():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    for seq in seq2:
        n = tree.searchNode(seq)
        pr1 = computePR(n, tree)
        print('seq: ' + str(seq) + ' - pr: ' + str(pr1))


<mask token>

<mask token>


def parserLocation(lat, long):
    assert len(lat) == 13
    strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
    long = long.strip()
    assert len(long) == 14
    strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
    return [int(strlat) / 100000000, int(strlong) / 100000000]


<mask token>


def distanceTime(timeE, timeP):
    assert len(timeE) == 16
    assert len(timeP) == 16
    daysE = int(timeE[0:2])
    monthsE = int(timeE[3:5])
    yearsE = int(timeE[6:10])
    daysP = int(timeP[0:2])
    monthsP = int(timeP[3:5])
    yearsP = int(timeP[6:10])
    dE = datetime.date(yearsE, monthsE, daysE)
    dP = datetime.date(yearsP, monthsP, daysP)
    return abs((dE - dP).days)


def neighborhood(event, typeF):
    r = 0.1
    t = 2
    nfe = set()
    sql = 'SELECT * FROM ' + table
    mycursor.execute(sql)
    for crime in mycursor:
        [late, longe] = parserLocation(event[4], event[5])
        [latp, longp] = parserLocation(crime[4], crime[5])
        if crime[1] == typeF:
            if distanceLocation(late, longe, latp, longp) <= r:
                timee = event[2]
                timep = crime[2]
                diffDays = distanceTime(timee, timep)
                if diffDays <= t and event != crime:
                    nfe.add(crime[0])
    return nfe


def setD(typeD):
    setReturn = set()
    sql = ('SELECT * FROM ' + table + ' WHERE offence_code_group LIKE "' +
        typeD + '"')
    mycursor.execute(sql)
    for record in mycursor:
        setReturn.add(record[0])
    return setReturn


def setInstances(prevSet, currentType):
    set_return = set()
    for event in prevSet:
        sql = ('SELECT * FROM ' + table + ' WHERE incident_num = "' + event +
            '"')
        mycursor.execute(sql)
        ev = mycursor.fetchone()
        neig = neighborhood(ev, currentType)
        set_return = set_return.union(neig)
    return set_return


def candidateGen(setSeq, tree):
    for seq in setSeq:
        node = tree.searchNode(seq[:len(seq) - 1])
        if node != 0:
            newSet = setInstances(node.set, seq[len(seq) - 1])
            print('inserito: ' + str(seq))
            tree.insertNode(seq, newSet)
        else:
            print('error candidate Gen - node non trovato')


def computePR(n1, tree):
    typeD = n1.value
    nSet = tree.searchNode([typeD])
    if nSet is None:
        print('tipo non trovato')
        return
    ins = len(n1.set)
    d_set = len(nSet.set)
    pr = ins / d_set
    return pr


def computePI(seq, tree):
    length = len(seq)
    n = tree.searchNode(seq)
    if n is None:
        return None
    if length <= 2:
        return computePR(n, tree)
    else:
        pr = computePR(n, tree)
        pi = computePI(seq[:length - 1], tree)
        return min(pi, pr)


def checkDouble(seq):
    seqSet = set(seq)
    if len(seq) == len(seqSet):
        return True
    else:
        return False


def candidateGenTree(length, tree):
    candidates = tree.candidates
    for cand in candidates:
        if len(cand) == length - 1:
            nodeCand = tree.searchNode(cand)
            if nodeCand is None:
                print('cand not found, seq: ' + str(cand))
                continue
            children = nodeCand.parent2.children
            for child in children:
                newSeq = cand[:]
                newSeq.append(child.value)
                if checkDouble(newSeq):
                    newSet = setInstances(nodeCand.set, child.value)
                    tree.insertNode(newSeq, newSet)
                    print('inserito: ' + str(newSeq))


def seqPIMin(seqList, num):
    teta = 1
    i = 0
    while i < num:
        newteta = 0
        for el in seqList:
            if el[1] < teta and el[1] > newteta:
                newteta = el[1]
        teta = newteta
        i = 0
        for el in seqList:
            if el[1] >= teta:
                i += 1
    return teta


def refreshTree(tree, teta):
    cands = tree.candidates
    for cand in cands:
        pi = computePI(cand, tree)
        if pi is None:
            continue
        if pi < teta:
            delNode = tree.searchNode(cand)
            if delNode is None:
                print(str(cand) + ' not found')
                tree.candidates.remove(cand)
                continue
            delNode.parent1.children.remove(delNode)
            tree.candidates.remove(cand)


def verifyCandidates(lun, teta, tree):
    cand = tree.candidates
    ret = []
    for seq in cand:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                ret.append([seq, pi])
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error')
                    return
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        print('eliminato ramo albero')
                        tree.candidates.remove(seq)
                        break
    return ret


def verifyTopCandidates(lun, teta, top, num, tree):
    for seq in tree.candidates:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                if len(top) < num - 1:
                    top.append([seq, pi])
                elif len(top) == num - 1:
                    top.append([seq, pi])
                    teta = seqPIMin(top, num)
                    print('new teta (==): ' + str(teta))
                else:
                    top.append([seq, pi])
                    if pi > teta:
                        teta = seqPIMin(top, num)
                        print('new teta (>): ' + str(teta))
                        for el in top:
                            if el[1] < teta:
                                top.remove(el)
                                seqdel = el[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error top candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('eliminato ramo di: ' + str(
                                            seqdel) + ', che ha pi = ' + str(el[1])
                                            )
                                        break
                        for cand in tree.candidates:
                            if len(cand[0]) == lun and cand[1] < teta:
                                tree.candidates.remove(cand)
                                seqdel = cand[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error cand candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('delete ramo di: ' + str(seqdel) +
                                            ', che ha pi = ' + str(cand[1]))
                                        break
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error, seq non trovata: ' + str(seq))
                    continue
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        tree.candidates.remove(seq)
                        print('eliminato(2) ramo di: ' + str(seq) +
                            ', che ha pi = ' + str(pi))
                        break
    return top


def stbfMiner():
    teta = 0.7
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    val = verifyCandidates(2, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    val = verifyCandidates(3, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n' + str(tree))


def stbfMinerTop():
    teta = 0.25
    top = []
    num = 20
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary'], ['Residential Burglary',
        'Auto Theft'], ['Homicide', 'Other Burglary'], ['Other Burglary',
        'Larceny'], ['Larceny From Motor Vehicle', 'Aggravated Assault'], [
        'Larceny', 'Auto Theft']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    top = verifyTopCandidates(2, teta, top, num, tree)
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    top = verifyTopCandidates(3, teta, top, num, tree)
    if top is None:
        print('Top none')
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    tree.refreshCandidates()
    print('\nDopo il refresh\n' + str(tree))


def testTree():
    t = SPTree(['A', 'B', 'C'])
    sA = set()
    sA.add('10')
    sB = set()
    sB.add('IT01R003')
    sC = set()
    sC.add('30')
    nA = t.searchNode(['A'])
    nB = t.searchNode(['B'])
    nC = t.searchNode(['C'])
    nA.insertSet(sA)
    nB.insertSet(sB)
    nC.insertSet(sC)
    print(nA)
    print(nB)
    print(nC)


def testCrimeTree():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    print(tree)
    for tipo in tree.root.children:
        print(tipo.value + ': ' + str(len(tipo.set)))


def testPR():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    for seq in seq2:
        n = tree.searchNode(seq)
        pr1 = computePR(n, tree)
        print('seq: ' + str(seq) + ' - pr: ' + str(pr1))


def testPI():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    i = 1
    for seq in seq2:
        pi = computePI(seq, tree)
        print(str(i) + '. ' + str(seq) + ' - pi: ' + str(pi))
        i += 1
    for seq in seq3:
        pi = computePI(seq, tree)
        print(str(i) + '. ' + str(seq) + ' - pi: ' + str(pi))
        i += 1


<mask token>

<mask token>


def parserLocation(lat, long):
    assert len(lat) == 13
    strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
    long = long.strip()
    assert len(long) == 14
    strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
    return [int(strlat) / 100000000, int(strlong) / 100000000]


def distanceLocation(lat1, long1, lat2, long2):
    lat1 = round(lat1 * (2 * math.pi) / 360, 2)
    long1 = round(long1 * (2 * math.pi) / 360, 2)
    lat2 = round(lat2 * (2 * math.pi) / 360, 2)
    long2 = round(long2 * (2 * math.pi) / 360, 2)
    dist = math.acos(math.sin(lat1) * math.sin(lat2) + math.cos(lat1) *
        math.cos(lat2) * math.cos(long1 - long2)) * 6371
    assert dist >= 0
    return dist


def distanceTime(timeE, timeP):
    assert len(timeE) == 16
    assert len(timeP) == 16
    daysE = int(timeE[0:2])
    monthsE = int(timeE[3:5])
    yearsE = int(timeE[6:10])
    daysP = int(timeP[0:2])
    monthsP = int(timeP[3:5])
    yearsP = int(timeP[6:10])
    dE = datetime.date(yearsE, monthsE, daysE)
    dP = datetime.date(yearsP, monthsP, daysP)
    return abs((dE - dP).days)


def neighborhood(event, typeF):
    r = 0.1
    t = 2
    nfe = set()
    sql = 'SELECT * FROM ' + table
    mycursor.execute(sql)
    for crime in mycursor:
        [late, longe] = parserLocation(event[4], event[5])
        [latp, longp] = parserLocation(crime[4], crime[5])
        if crime[1] == typeF:
            if distanceLocation(late, longe, latp, longp) <= r:
                timee = event[2]
                timep = crime[2]
                diffDays = distanceTime(timee, timep)
                if diffDays <= t and event != crime:
                    nfe.add(crime[0])
    return nfe


def setD(typeD):
    setReturn = set()
    sql = ('SELECT * FROM ' + table + ' WHERE offence_code_group LIKE "' +
        typeD + '"')
    mycursor.execute(sql)
    for record in mycursor:
        setReturn.add(record[0])
    return setReturn


def setInstances(prevSet, currentType):
    set_return = set()
    for event in prevSet:
        sql = ('SELECT * FROM ' + table + ' WHERE incident_num = "' + event +
            '"')
        mycursor.execute(sql)
        ev = mycursor.fetchone()
        neig = neighborhood(ev, currentType)
        set_return = set_return.union(neig)
    return set_return


def candidateGen(setSeq, tree):
    for seq in setSeq:
        node = tree.searchNode(seq[:len(seq) - 1])
        if node != 0:
            newSet = setInstances(node.set, seq[len(seq) - 1])
            print('inserito: ' + str(seq))
            tree.insertNode(seq, newSet)
        else:
            print('error candidate Gen - node non trovato')


def computePR(n1, tree):
    typeD = n1.value
    nSet = tree.searchNode([typeD])
    if nSet is None:
        print('tipo non trovato')
        return
    ins = len(n1.set)
    d_set = len(nSet.set)
    pr = ins / d_set
    return pr


def computePI(seq, tree):
    length = len(seq)
    n = tree.searchNode(seq)
    if n is None:
        return None
    if length <= 2:
        return computePR(n, tree)
    else:
        pr = computePR(n, tree)
        pi = computePI(seq[:length - 1], tree)
        return min(pi, pr)


def checkDouble(seq):
    seqSet = set(seq)
    if len(seq) == len(seqSet):
        return True
    else:
        return False


def candidateGenTree(length, tree):
    candidates = tree.candidates
    for cand in candidates:
        if len(cand) == length - 1:
            nodeCand = tree.searchNode(cand)
            if nodeCand is None:
                print('cand not found, seq: ' + str(cand))
                continue
            children = nodeCand.parent2.children
            for child in children:
                newSeq = cand[:]
                newSeq.append(child.value)
                if checkDouble(newSeq):
                    newSet = setInstances(nodeCand.set, child.value)
                    tree.insertNode(newSeq, newSet)
                    print('inserito: ' + str(newSeq))


def seqPIMin(seqList, num):
    teta = 1
    i = 0
    while i < num:
        newteta = 0
        for el in seqList:
            if el[1] < teta and el[1] > newteta:
                newteta = el[1]
        teta = newteta
        i = 0
        for el in seqList:
            if el[1] >= teta:
                i += 1
    return teta


def refreshTree(tree, teta):
    cands = tree.candidates
    for cand in cands:
        pi = computePI(cand, tree)
        if pi is None:
            continue
        if pi < teta:
            delNode = tree.searchNode(cand)
            if delNode is None:
                print(str(cand) + ' not found')
                tree.candidates.remove(cand)
                continue
            delNode.parent1.children.remove(delNode)
            tree.candidates.remove(cand)


def verifyCandidates(lun, teta, tree):
    cand = tree.candidates
    ret = []
    for seq in cand:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                ret.append([seq, pi])
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error')
                    return
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        print('eliminato ramo albero')
                        tree.candidates.remove(seq)
                        break
    return ret


def verifyTopCandidates(lun, teta, top, num, tree):
    for seq in tree.candidates:
        if len(seq) == lun:
            pi = computePI(seq, tree)
            if pi is None:
                continue
            if pi >= teta:
                if len(top) < num - 1:
                    top.append([seq, pi])
                elif len(top) == num - 1:
                    top.append([seq, pi])
                    teta = seqPIMin(top, num)
                    print('new teta (==): ' + str(teta))
                else:
                    top.append([seq, pi])
                    if pi > teta:
                        teta = seqPIMin(top, num)
                        print('new teta (>): ' + str(teta))
                        for el in top:
                            if el[1] < teta:
                                top.remove(el)
                                seqdel = el[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error top candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('eliminato ramo di: ' + str(
                                            seqdel) + ', che ha pi = ' + str(el[1])
                                            )
                                        break
                        for cand in tree.candidates:
                            if len(cand[0]) == lun and cand[1] < teta:
                                tree.candidates.remove(cand)
                                seqdel = cand[0]
                                n = tree.searchNode(seqdel)
                                if n is None:
                                    print(
                                        'error cand candidates, seq non trovata: '
                                         + str(seqdel))
                                    continue
                                for child in n.parent1.children:
                                    if child.value == seqdel[len(seqdel) - 1]:
                                        n.parent1.children.remove(child)
                                        print('delete ramo di: ' + str(seqdel) +
                                            ', che ha pi = ' + str(cand[1]))
                                        break
            else:
                n = tree.searchNode(seq)
                if n is None:
                    print('error, seq non trovata: ' + str(seq))
                    continue
                for child in n.parent1.children:
                    if child.value == seq[len(seq) - 1]:
                        n.parent1.children.remove(child)
                        tree.candidates.remove(seq)
                        print('eliminato(2) ramo di: ' + str(seq) +
                            ', che ha pi = ' + str(pi))
                        break
    return top


def stbfMiner():
    teta = 0.7
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    val = verifyCandidates(2, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    val = verifyCandidates(3, teta, tree)
    for el in val:
        print(str(el[0]) + ' - ' + str(el[1]))
    print('\n' + str(tree))


def stbfMinerTop():
    teta = 0.25
    top = []
    num = 20
    tree = SPTree()
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault'], ['Larceny', 'Aggravated Assault'], [
        'Commercial Burglary', 'Other Burglary'], ['Residential Burglary',
        'Auto Theft'], ['Homicide', 'Other Burglary'], ['Other Burglary',
        'Larceny'], ['Larceny From Motor Vehicle', 'Aggravated Assault'], [
        'Larceny', 'Auto Theft']]
    print('... generating candidates(2)')
    candidateGen(seq2, tree)
    print(tree)
    print('\n... verifying candidates(2)')
    top = verifyTopCandidates(2, teta, top, num, tree)
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    print('\n... generating candidates(3)')
    candidateGenTree(3, tree)
    print('\n... verifying candidates(3)')
    top = verifyTopCandidates(3, teta, top, num, tree)
    if top is None:
        print('Top none')
    i = 0
    for el in top:
        i += 1
        print(str(i) + '. ' + str(el[0]) + ' - ' + str(el[1]))
    tree.refreshCandidates()
    print('\nDopo il refresh\n' + str(tree))


def testTree():
    t = SPTree(['A', 'B', 'C'])
    sA = set()
    sA.add('10')
    sB = set()
    sB.add('IT01R003')
    sC = set()
    sC.add('30')
    nA = t.searchNode(['A'])
    nB = t.searchNode(['B'])
    nC = t.searchNode(['C'])
    nA.insertSet(sA)
    nB.insertSet(sB)
    nC.insertSet(sC)
    print(nA)
    print(nB)
    print(nC)


def testCrimeTree():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    print(tree)
    for tipo in tree.root.children:
        print(tipo.value + ': ' + str(len(tipo.set)))


def testPR():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    for seq in seq2:
        n = tree.searchNode(seq)
        pr1 = computePR(n, tree)
        print('seq: ' + str(seq) + ' - pr: ' + str(pr1))


def testPI():
    seq2 = [['Aggravated Assault', 'Auto Theft'], ['Commercial Burglary',
        'Homicide'], ['Other Burglary', 'Robbery'], ['Homicide',
        'Auto Theft'], ['Larceny', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery'], ['Larceny From Motor Vehicle',
        'Homicide'], ['Commercial Burglary', 'Auto Theft'], ['Robbery',
        'Larceny'], ['Larceny From Motor Vehicle', 'Commercial Burglary'],
        ['Auto Theft', 'Residential Burglary'], ['Auto Theft',
        'Aggravated Assault']]
    seq3 = [['Commercial Burglary', 'Homicide', 'Auto Theft'], [
        'Larceny From Motor Vehicle', 'Homicide', 'Auto Theft'], [
        'Aggravated Assault', 'Auto Theft', 'Residential Burglary'], [
        'Aggravated Assault', 'Robbery', 'Larceny'], [
        'Larceny From Motor Vehicle', 'Commercial Burglary', 'Auto Theft']]
    sql = 'SELECT DISTINCT offence_code_group FROM ' + table
    mycursor.execute(sql)
    types = []
    setTypes = []
    for tipo in mycursor:
        types.append(tipo[0])
    for el in types:
        s = setD(el)
        setTypes.append(s)
    tree = SPTree()
    i = 0
    for el in types:
        tree.insertNode(el, setTypes[i])
        i += 1
    candidateGen(seq2, tree)
    candidateGen(seq3, tree)
    i = 1
    for seq in seq2:
        pi = computePI(seq, tree)
        print(str(i) + '. ' + str(seq) + ' - pi: ' + str(pi))
        i += 1
    for seq in seq3:
        pi = computePI(seq, tree)
        print(str(i) + '. ' + str(seq) + ' - pi: ' + str(pi))
        i += 1


if __name__ == '__main__':
    mydb = mysql.connector.connect(host='localhost', user='root', passwd=
        'fedeServer33', database='bostoncrime')
    table = 'crimedata2018small'
    mycursor = mydb.cursor()
    print('Testing STBF Miner Top')
    stbfMinerTop()
    mycursor.close()

# -*- coding: utf-8 -*-
"""
Created on Thu Apr 25 17:55:14 2019

@author: fede9
"""

import datetime
import math
import mysql.connector
from SPTree2 import SPTree

#input coordinate stringhe
#output coordinate intere 
def parserLocation(lat, long):
   assert(len(lat) == 13) #se non è un valore corretto di latitudine
   strlat = lat[0] + lat[2] + lat[3:5] + lat[6:9] + lat[10:13]
   
   long = long.strip() #elimino tabulazioni
   assert(len(long) == 14) #se non è un valore corretto di lognitudine
   strlong = long[0:2] + long[3] + long[4:6] + long[7:10] + long[11:14]
   #print(str)
   return [int(strlat)/100000000, int(strlong)/100000000]
#end parserLocation
   
def distanceLocation(lat1, long1, lat2, long2) :
   #conversione in radianti
   lat1 = round(lat1*(2*math.pi)/360, 2)
   long1 = round(long1*(2*math.pi)/360, 2)
   lat2 = round(lat2*(2*math.pi)/360, 2)
   long2 = round(long2*(2*math.pi)/360, 2)
   
   
   dist = math.acos( math.sin(lat1) * math.sin(lat2) 
      + math.cos(lat1) * math.cos(lat2) * math.cos(long1-long2)) * 6371
   
   assert(dist >= 0)
   return dist
#end distanceLocation
   
#input data e ora stringa
#output giorni (intero)
def distanceTime(timeE, timeP) :
   assert(len(timeE) == 16)
   assert(len(timeP) == 16)
   
   daysE = int(timeE[0:2])
   monthsE = int(timeE[3:5])
   yearsE = int(timeE[6:10])
   daysP = int(timeP[0:2])
   monthsP = int(timeP[3:5])
   yearsP = int(timeP[6:10])
   
   dE = datetime.date(yearsE, monthsE, daysE)
   dP = datetime.date(yearsP, monthsP, daysP)
   
   return abs((dE - dP).days)
#end distanceTime
   
#input event, type evet
#output neigborhood event
def neighborhood(event, typeF) :
   #raggio spaziale della location (km)
   r = 0.1
   #raggio temporale
   t = 2
   #neighbothood with respect to event type
   nfe = set()
   
   sql = "SELECT * FROM " + table
   mycursor.execute(sql)
   
   for crime in mycursor:
      #print(event)
      #print(crime[5])
      [late, longe] = parserLocation(event[4], event[5])
      [latp, longp] = parserLocation(crime[4], crime[5])
      #se di tipo specificato
      if crime[1] == typeF:
         #se è entro il raggio spaziale
         if distanceLocation(late, longe, latp, longp) <= r:
            timee = event[2]
            timep = crime[2]
            diffDays = distanceTime(timee, timep)
            #se è entro il raggio temporale
            #escludo se stesso
            if diffDays <= t and event != crime:
               nfe.add(crime[0])
   #end for
   return nfe
#end neighborhood
   
#input tipo di evento
#output insieme ti tutti gli eventi di quel tipo
def setD(typeD) :
   setReturn = set()
   #print(typeD)
   sql = "SELECT * FROM " + table + " WHERE offence_code_group LIKE \"" + typeD + "\""   
   #print(sql)
   mycursor.execute(sql)
   
   for record in mycursor:
      setReturn.add(record[0])
   return setReturn
#end setD

#input insiemeSet precedente e tipo corrente
#output insieme di istanze associate
def setInstances(prevSet, currentType):
   set_return = set()

   for event in prevSet:
      sql = "SELECT * FROM " + table + " WHERE incident_num = \"" + event + "\""
      mycursor.execute(sql)
      #la tupla che mi interessa
      ev = mycursor.fetchone()
      #print(ev)
      neig = neighborhood(ev, currentType)
      #print(neig)
      set_return = set_return.union(neig)
   return set_return
#end setInstance
   
#candidate generation
#input un insieme di sequenze significative di lunghezza uguale
#assumo che l'input sia di una lista di sequenze (che a loro volta sono liste)
#output albero con set di candidati 
def candidateGen(setSeq, tree) :
   
   for seq in setSeq :
      #se la sequenza precedente esiste
      node = tree.searchNode(seq[:len(seq)-1])
      if node != 0 :
         #calcolo nuovo setInstances tra node e tipo di seq[len(seq)-1]
         newSet = setInstances(node.set, seq[len(seq)-1])
         print("inserito: " + str(seq))
         #creo un set che è l'union tra set di node e neighborhood trovato
         tree.insertNode(seq, newSet) #gli aggiungo l'insieme del nodo
      else:
         print("error candidate Gen - node non trovato")
#end caditateGen

#calcola il valore di Partitipation rateo di questo nodo
def computePR(n1, tree):
   typeD = n1.value
   nSet = tree.searchNode([typeD])
   if (nSet is None):
      print("tipo non trovato")
      return
   
   #print("esito searchPR: " + str(nSet))
   ins = len(n1.set)
   d_set = len(nSet.set)
   #print(ins)
   #print(d_set)
   pr = ins / d_set
   return pr
#end computePR
   
def computePI(seq, tree):
   length = len(seq)
   n = tree.searchNode(seq)
   #se il nodo non esiste allora lo segnalo in output
   if n is None:
      return None
   if length <= 2: #caso base
      return computePR(n, tree)
   else:
      pr = computePR(n,tree)
      pi = computePI(seq[:length-1], tree)
      return min(pi, pr)
#end computePI

#verifica se all'interno di una sequenza (list) vi siano elementi doppi
#output true se non sono presenti due tipi uguali
#output false se sono presenti due tipi uguali
def checkDouble(seq):
   seqSet = set(seq)
   if len(seq) == len(seqSet):
      return True
   else:
      return False
#end checkDouble

def candidateGenTree(length, tree):
   candidates = tree.candidates
   for cand in candidates:
      if len(cand) == length-1:
         nodeCand = tree.searchNode(cand)
         if nodeCand is None:
            print("cand not found, seq: " + str(cand))
            continue
         children = nodeCand.parent2.children
         for child in children:
            newSeq = cand[:]
            newSeq.append(child.value)
            if checkDouble(newSeq):
   #            print("cand: " + str(cand))
   #            print("newSeq: " + str(newSeq))
               #print("cand: " + str(cand) + ", newSeq: " + str(newSeq) + " ...")
               newSet = setInstances(nodeCand.set, child.value)
               tree.insertNode(newSeq, newSet)
               print("inserito: " + str(newSeq))
#end candidateGenTree

#input lista di [sequenza, pi]
#output coppia [sequenza, pi] con pi minore
def seqPIMin(seqList, num):
   teta = 1
   i = 0
   #verifico che vi siano n-1 elementi nella lista che superino il nuovo teta
   while i < num:
      #aggiorno il newteta se è il massimo dei minori di teta
      newteta = 0
      for el in seqList:
         if el[1] < teta and el[1] > newteta:
            newteta = el[1]
            #print(newteta)
      teta = newteta
      i = 0
      #verifico che vi siano n-1 elementi nella lista che superino il nuovo teta
      for el in seqList:
         if el[1] >= teta:
            i += 1
   return teta
#end seqPIMin

#faccio il refreshTree, in base al teta elimino tutte le sequenze che hanno un teta minore dall'albero
def refreshTree(tree, teta):
   cands = tree.candidates
   for cand in cands:
      pi = computePI(cand, tree)
      #questo controllo mi permette di evitare sequenze non più presenti
      if pi is None:
         continue
      if pi < teta:
         delNode = tree.searchNode(cand)
         if delNode is None:
            print(str(cand) + " not found")
            tree.candidates.remove(cand)
            continue
         delNode.parent1.children.remove(delNode)
         tree.candidates.remove(cand)

#verifyCandidates, si occupa del calcolo del pi di ciascun candidato
#output lista di coppie sequenza - pi
def verifyCandidates(lun, teta, tree):
   cand = tree.candidates
   ret = []
   
   for seq in cand:
      if len(seq) == lun: 
         pi = computePI(seq, tree)
         #questo controllo mi permette di evitare sequenze non più presenti
         if pi is None:
            continue
         
         if pi >= teta:
            ret.append([seq, pi])
         else:
            #taglio l'albero relativo a questa computazione
            n = tree.searchNode(seq)
            if n is None:
               print("error")
               return
            
            for child in n.parent1.children:
               if child.value == seq[len(seq)-1]:
                  n.parent1.children.remove(child)
                  print("eliminato ramo albero")
                  tree.candidates.remove(seq)
                  break
         
   return ret
#end verifyCandidates

#verifyTopCandidates, si occupa del calcolo del pi di ciascun candidato
#estraendo solo i primi n elementi in base al valore di pi
#output lista di coppie [sequenza - pi] (n elementi)
def verifyTopCandidates(lun, teta, top, num, tree):
   
   for seq in tree.candidates:
      if len(seq) == lun: 
         pi = computePI(seq, tree)
         #questo controllo mi permette di evitare sequenze non più presenti
         if pi is None:
            continue
         if pi >= teta:
            #se ho ancora spazio nel top
            if len(top) < num-1:
               top.append([seq, pi])
            #se sono al limite del top
            elif len(top) == num-1:
               top.append([seq, pi])
               teta = seqPIMin(top, num)
               print("new teta (==): " + str(teta))
            else:
               #se ho riempito tutto il top
               top.append([seq, pi])
               if pi > teta:
                  teta = seqPIMin(top, num)
                  print("new teta (>): " + str(teta))
                  #cancello tutti i top con pi < teta
                  for el in top:
                     if el[1] < teta:
                        top.remove(el)
                        #elimino il relativo sotto-albero alle sequenze eliminate
                        seqdel = el[0]
                        n = tree.searchNode(seqdel)
                        if n is None:
                           print("error top candidates, seq non trovata: " + str(seqdel))
                           continue
                        
                        for child in n.parent1.children:
                           if child.value == seqdel[len(seqdel)-1]:
                              n.parent1.children.remove(child)
                              print("eliminato ramo di: " + str(seqdel) + ", che ha pi = " + str(el[1]))
                              break
                  #end for
                  #cancello tutti le seq lunghe lun dei candidates
                  for cand in tree.candidates:
                     if len(cand[0])==lun and cand[1] < teta:
                        tree.candidates.remove(cand)
                        #elimino il relativo sotto-albero
                        seqdel = cand[0]
                        n = tree.searchNode(seqdel)
                        if n is None:
                           print("error cand candidates, seq non trovata: " + str(seqdel))
                           continue
                           
                        for child in n.parent1.children:
                           if child.value == seqdel[len(seqdel)-1]:
                              n.parent1.children.remove(child)
                              print("delete ramo di: " + str(seqdel) + ", che ha pi = " + str(cand[1]))
                              break
                  #end for
               #end if
         else:
            #se il pi ha un teta mirore rispetto al limite
            #taglio l'albero relativo a questa computazione
            n = tree.searchNode(seq)
            if n is None:
               print("error, seq non trovata: " + str(seq))
               continue
            
            for child in n.parent1.children:
               if child.value == seq[len(seq)-1]:
                  n.parent1.children.remove(child)                              
                  tree.candidates.remove(seq)
                  print("eliminato(2) ramo di: " + str(seq) + ", che ha pi = " + str(pi))
                  break
         
   return top
#end verifyCandidates

#algroritmo STBF senza il top e l'update della teta
def stbfMiner():
   #teta valore di threshold rispetto al pi
   teta = 0.7
   #creo l'albero delle sequenze   
   tree = SPTree()   
   #prendo ciascun tipo di evento
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   #inserendo il primo layer di albero
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   #genero i pattern di lunghezza 2
   #per ora sono handmade
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"],
           ["Larceny", "Aggravated Assault"], ["Commercial Burglary", "Other Burglary"]]
   
   print("... generating candidates(2)")
   candidateGen(seq2, tree)
   #faccio la verifyCandidates(2)
   print(tree)
   print("\n... verifying candidates(2)")
   val = verifyCandidates(2, teta, tree)
   for el in val:
      print(str(el[0]) + " - " + str(el[1]))
      
   print("\n... generating candidates(3)")
   candidateGenTree(3, tree)
   print("\n... verifying candidates(3)")
   val = verifyCandidates(3, teta, tree)
   for el in val:
      print(str(el[0]) + " - " + str(el[1]))
   
   print("\n" + str(tree))
#end stbfMiner
   
################ stbfMiner Top
#algroritmo STBF con il top e l'update della teta
def stbfMinerTop():
   #teta valore di threshold rispetto al pi
   #top è l'array in cui salvo i migliori risultati
   #num è il numero di risultati desiderati
   teta = 0.25
   top = []
   num = 20
   #creo l'albero delle sequenze   
   tree = SPTree()   
   #prendo ciascun tipo di evento
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   #inserendo il primo layer di albero
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   #genero i pattern di lunghezza 2
   #per ora sono handmade
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"],
           ["Larceny", "Aggravated Assault"], ["Commercial Burglary", "Other Burglary"],
           ["Residential Burglary", "Auto Theft"],["Homicide", "Other Burglary"],
           ["Other Burglary", "Larceny"],["Larceny From Motor Vehicle", "Aggravated Assault"],
           ["Larceny", "Auto Theft"]]
   
   print("... generating candidates(2)")
   candidateGen(seq2, tree)
   #faccio la verifyCandidates(2)
   print(tree)
   print("\n... verifying candidates(2)")
   top = verifyTopCandidates(2, teta, top, num, tree)
   i = 0
   for el in top:
      i += 1
      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
      
   print("\n... generating candidates(3)")
   candidateGenTree(3, tree)
   print("\n... verifying candidates(3)")
   top = verifyTopCandidates(3, teta, top, num, tree)
   if top is None:
      print("Top none")
   i = 0
   for el in top:
      i += 1
      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
   
#   print("\n\n" + str(tree))
   tree.refreshCandidates()
   print("\nDopo il refresh\n" + str(tree))
   
#   print("\n... generating candidates(4)")
#   candidateGenTree(4, tree)
#   print("\n... verifying candidates(4)")
#   top = verifyTopCandidates(4, teta, top, num, tree)
#   if top is None:
#      print("Top none")
#   i = 0
#   for el in top:
#      i += 1
#      print(str(i) + ". " + str(el[0]) + " - " + str(el[1]))
#   
##   print("\n\n" + str(tree))
#   tree.refreshCandidates()
#   print("\nDopo il refresh\n" + str(tree))
##############################################################
   #TEST

def testTree() :
   t = SPTree(["A", "B", "C"])
   #inserisco i sets
   sA = set()
   sA.add("10")
   sB = set()
   sB.add('IT01R003')
   sC = set()
   sC.add('30')
   
   nA = t.searchNode(["A"])
   nB = t.searchNode(["B"])
   nC = t.searchNode(["C"])  
   
   nA.insertSet(sA)
   nB.insertSet(sB)
   nC.insertSet(sC)
   print(nA)
   print(nB)
   print(nC)
#end testTree

def testCrimeTree() :
   
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   seq3 = [["Commercial Burglary", "Homicide", "Auto Theft"], 
           ["Larceny From Motor Vehicle", "Homicide", "Auto Theft"],
           ["Aggravated Assault", "Auto Theft", "Residential Burglary"],
           ["Aggravated Assault", "Robbery", "Larceny"], 
           ["Larceny From Motor Vehicle", "Commercial Burglary", "Auto Theft"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree)
   candidateGen(seq3, tree)
   
   print(tree)
   
   for tipo in tree.root.children:
      print(tipo.value + ": " + str(len(tipo.set)))
#end testCrimeTree
      
def testPR() :
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree) #inserisco sequenze di 2 elementi
   
   for seq in seq2:
      n = tree.searchNode(seq)
      pr1 = computePR(n, tree)
      print("seq: " + str(seq) + " - pr: " + str(pr1))
   
#end testPR
      
def testPI() :
   seq2 = [["Aggravated Assault", "Auto Theft"], ["Commercial Burglary", "Homicide"], 
           ["Other Burglary", "Robbery"], ["Homicide", "Auto Theft"], 
           ["Larceny", "Residential Burglary"], ["Aggravated Assault", "Robbery"],
           ["Larceny From Motor Vehicle", "Homicide"],["Commercial Burglary", "Auto Theft"],
           ["Robbery", "Larceny"], ["Larceny From Motor Vehicle", "Commercial Burglary"],
           ["Auto Theft", "Residential Burglary"], ["Auto Theft", "Aggravated Assault"]]
   
   seq3 = [["Commercial Burglary", "Homicide", "Auto Theft"], 
           ["Larceny From Motor Vehicle", "Homicide", "Auto Theft"],
           ["Aggravated Assault", "Auto Theft", "Residential Burglary"],
           ["Aggravated Assault", "Robbery", "Larceny"], 
           ["Larceny From Motor Vehicle", "Commercial Burglary", "Auto Theft"]]
   
   sql = "SELECT DISTINCT offence_code_group FROM " + table
   mycursor.execute(sql)
   
   types = []
   setTypes = []
   #inizializzo i tipi di eventi e i setD a loro legati
   for tipo in mycursor:
      types.append(tipo[0])
   
   for el in types:
      s = setD(el)
      setTypes.append(s)

   tree = SPTree()
   i = 0
   for el in types:
      tree.insertNode(el, setTypes[i])
      i += 1
   
   candidateGen(seq2, tree) #inserisco sequenze di 2 elementi
   candidateGen(seq3, tree)
   i=1
   for seq in seq2:
      pi = computePI(seq, tree)
      print(str(i) + ". " + str(seq) + " - pi: " + str(pi))
      i += 1
   for seq in seq3:
      pi = computePI(seq, tree)
      print(str(i) + ". " + str(seq) + " - pi: " + str(pi))
      i += 1
#end  testPI
#############################
   #MAIN
if __name__ == "__main__":
   mydb = mysql.connector.connect(
         host = "localhost",
         user = "root",
         passwd = "fedeServer33",
         database = "bostoncrime"
         )
   table = "crimedata2018small"
   mycursor = mydb.cursor()
   
#   print("Testing testTree :")
#   testTree()
   
#   print("Testing testCrimeTree :")
#   testCrimeTree()
   
#   print("Testing testPR :")
#   testPR()
   
#   print("Testing testPI :")
#   testPI()
   
#   print("Testing STBF Miner")
#   stbfMiner()
   
   print("Testing STBF Miner Top")
   stbfMinerTop()
   
   
   mycursor.close()