def pickle_and_write(posting_array, posting_f): skip_list = SkipList(posting_array).build_skips() skip_list_pickled = pickle.dumps(skip_list) skip_list_start = posting_f.tell() posting_f.write(skip_list_pickled + '\n') skip_list_end = posting_f.tell() return skip_list_start, skip_list_end
def stable_size_threshold_rebalancing_original_gaps(repetitions, sequence_file_name, result_file_name): # Setup sequence_files = [sequence_file_name + str(i) + '.txt' for i in range(repetitions)] thresholds = [float(i / 10) for i in range(10, 21)] # Perform experiment results = [] for number, threshold in enumerate(thresholds): print('Threshold = ' + str(threshold)) rebalances = [] for i, sequence in enumerate(sequence_files): if i == 8: continue print('Repetition = ' + str(i)) skiplist = SkipList(3, threshold) rebalances.append(run_sequence_threshold(skiplist, sequence)) results.append(rebalances) # Output results fout = open(result_file_name, 'w') for repetition in results: search_path_lengths = [] rebalances = [] for result in repetition: r, s = result rebalances.append(r) search_path_lengths.append(s) search_path_lengths.sort() rebalances.sort() # print('SPL: ' + str(sum(search_path_lengths[1:-1]) / 7.0)) # print('REB: ' + str(sum(rebalances[1:-1]) / 7.0)) write_result_line(fout, sum(rebalances[1:-1]) / 7.0, sum(search_path_lengths[1:-1]) / 7.0) fout.close()
def generate_insertions_sequence(size, iterations, sequence_file_name): # Build initial list skiplist = SkipList(3) numbers = list(range(1, size * 5)) shuffle(numbers) numbers = [Element(float(i)) for i in sorted(numbers[:size])] deletable_keys = [] sequence = open(sequence_file_name, 'w') sequence.write("initial_list:\n") used_keys = [] for i, element in enumerate(numbers): skiplist.insert(element.key) used_keys.append(element.key) write_sequence_line(sequence, 0, 'insert', element.key) if i % 250: skiplist.full_rebalance() skiplist.full_rebalance() numbers[0].next_value = numbers[0].key / 2.0 for i in range(1, size): numbers[i].next_value = (numbers[i].key + numbers[i - 1].key) / 2.0 append_value = numbers[-1].key + 1.0 # Generate sequence sequence.write("updates:\n") for i in range(1, iterations + 1): index = randint(0, len(numbers)) if index == 0: element = numbers[0] value = element.next_value element.next_value = value / 2.0 assert (value not in used_keys) elif index == len(numbers): value = append_value append_value += 1.0 assert (value not in used_keys) else: element = numbers[index] value = element.next_value element.next_value = (element.next_value + element.key) / 2.0 assert (value not in used_keys) assert (len(numbers) == len(set(numbers))) skiplist.insert(value) used_keys.append(value) write_sequence_line(sequence, i, 'insert', value) sequence.close()
def run_sequence(sequence_file_name): # Build initial list skiplist = SkipList(3) sequence = open(sequence_file_name) sequence.readline() size = 0 while True: line = sequence.readline().strip().split(':') if line[0] != '0': break if line[1] != 'insert': raise Exception('Invalid sequence') skiplist.insert(float(line[2])) if size % 250 == 0: while skiplist.rebalance(): continue size += 1 while skiplist.rebalance(): continue # Perform experiment result = [(0, skiplist.head.s / skiplist.size)] while True: line = sequence.readline() if line == '': break line = line.strip().split(':') i = int(line[0]) operation = line[1] value = float(line[2]) if operation == 'insert' or operation == 'insert-rebalance': skiplist.insert(value) size += 1 elif operation == 'delete': skiplist.delete(value) size -= 1 else: raise Exception('Invalid operation') if i % 10 == 0: result.append((i, skiplist.head.s / size)) sequence.close() return result
def new_skiplist(size, balance=False): sl = SkipList(3) for i in range(1, size + 1): sl.insert(i) if balance: sl.full_rebalance() return sl
def test(): #seed(421) # check case #seed(3421) # check case #seed(2441) # check case #seed(241) # check case L = sample(range(10, 99), 17) chosen = choice(L) print(f" >> BUILD_LIST: {L}") SL = SkipList(L) print(SL) print(f" >> Search Path for item {chosen}: {SL.path_to_target(chosen)}") print("\n\n") letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" seed(12344) L2 = sample(letters, 13) print(f" >> BUILD_LIST: {L2}") SL2 = SkipList(L2) print(SL2) print(f" >> Search Path for item 'q': {SL2.path_to_target('q')}") print(f" >> SL2.pop() = {SL2.pop()}") print(f" >> SL2.pop('K') = {SL2.pop('K')}") print(f" >> .... now pushing 'j'... ") SL2.push("j") print(f" >> .... now iddd '33' and add '102'... ") SL2 += "33" SL2 = SL2 + '102' print("\n\n") print(SL2) print(f"SL2.find_range('H', 'c') = {SL2.find_range('H', 'c')}") print(f"SL2.find_range('I', 'c') = {SL2.find_range('I', 'c')}") print(f"SL2.find_range('I', 'T') = {SL2.find_range('I', 'T')}") print(f"SL2.find_range('I', 'K') = {SL2.find_range('I', 'K')}") print(f"SL2.find_range('102', 'q') = {SL2.find_range('102', 'q')}") print(f" >> Is 'Z' in Skip List? {'Z' in SL2}") print(f" >> Is 'O' in Skip List? {'O' in SL2}")
def stable_size_ratio_rebalance_original_gaps(repetitions, sequence_file_name, result_file_name): # Setup sequence_files = [sequence_file_name + str(i) + '.txt' for i in range(repetitions)] ratios = [round(0.05 * i, 2) for i in range(21)] # Perform experiment results = [] for ratio in ratios: print('Ratio = ' + str(ratio)) sub_result = [] for i, sequence in enumerate(sequence_files): print('Repetition = ' + str(i)) skiplist = SkipList(3) sub_result.append(run_sequence_ratio(skiplist, ratio, sequence)) results.append(sub_result) # Output results fout = open(result_file_name, 'w') for i, repetition in enumerate(results): search_path_lengths_avg = [] search_path_lengths_worst = [] rebalances = [] for result in repetition: r, sa, sw = result rebalances.append(r) search_path_lengths_avg.append(sa) search_path_lengths_worst.append(sw) search_path_lengths_avg.sort() search_path_lengths_worst.sort() rebalances.sort() ratio = ratios[i] reb = sum(rebalances[1:-1]) / (repetitions - 2.0) spla = sum(search_path_lengths_avg[1:-1]) / (repetitions - 2.0) splw = sum(search_path_lengths_worst[1:-1]) / (repetitions - 2.0) write_result_line_4(fout, ratio, reb, spla, splw) fout.close()
class SkipListMap( Map ): def __init__( self, _MIN_VALUE, _MAX_VALUE ): self._T = SkipList( Map._Item( _MIN_VALUE, None ), Map._Item( _MAX_VALUE, None ) ) def __str__( self ): return str( self._T ) def __len__( self ): return len( self._T ) def __getitem__( self, k ): p = self._T.SkipSearch( self._Item( k ) ) if p._elem._key != k: return False return p._elem._value def __setitem__( self, k, v ): self._T.SkipInsert( self._Item( k, v ) ) def __delitem__( self, k ): p = self._T.SkipRemove( self._Item( k ) ) if p is None: return False return p._elem._value def __iter__( self ): for item in self._T: yield item._key def __reversed__( self ): for item in reversed( self._T ): yield item._key def pop( self, k ): p = self._T.SkipRemove( self._Item( k ) ) if p is None: return False return p._elem._value def find_min( self ): if len( self._T ) > 0: return (self._T.Min()._value) else: return None def find_max( self ): if len( self._T ) > 0: return (self._T.Max()._value) else: return None def find_ge( self, k ): #return (key,value) where key >= k p = self._T.SkipSearch( Map._Item( k ) ) p = p.elem._next if p._next is None: return None return (p._elem._key,p._elem._value) def find_le( self, k ): #return (key,value) where key <= k p = self._T.SkipSearch( Map._Item( k ) ) if p._prev is None: return None return (p._elem._key,p._elem._value) def find_gt( self, k ): #return (key,value) where key > k p = self._T.SkipSearch( Map._Item( k ) ) if p._next is None or p._next._next is None: return None p = p._next return (p._elem._key,p._elem._value) def find_lt( self, k ): #return (key,value) where key < k p = self._T.SkipSearch( Map._Item( k ) ) if p._prev is None or p._prev._prev is None: return None if p._elem._k == k: p = p._prev return (p._elem._key,p._elem._value) def find_range( self, start, stop ): #iterate (key,value) where start <= key < stop if start is None: start = self._T.Min() p = self._T.SkipSearch( Map._Item( start ) ) while not( p._belo is None ): p = p._belo while not( p._next is None ) and ( p._elem._key < stop ): yield (p._elem._key,p._elem._value) p = p._next
def __init__( self, _MIN_VALUE, _MAX_VALUE ): self._T = SkipList( Map._Item( _MIN_VALUE, None ), Map._Item( _MAX_VALUE, None ) )
from SkipList import SkipList lst = SkipList(3, 0.5) lst.insert(3) lst.insert(6) lst.insert(7) lst.insert(9) lst.insert(12) lst.insert(19) lst.insert(17) lst.displayList() lst.searchElement(19) lst.deleteElement(3) lst.displayList()
# Import skiplist from SkipList import SkipList from random import randint import time import csv sl = SkipList() # sl = SortedLinkList() arr = [10, 3, 7, 2, 91, 1] for a in arr: sl.insert(a) sl.print_list() sl = SkipList() n = 100 list_csv = [] list_to_search = [] for i in range(n): k = randint(0, 100000) print(f'Inserting: {k}') sl.insert(k) list_to_search.append(k) list_csv.append(sl.elem_count_each_level()) # Goal 1 level_count = sl.count_list() for l in list_csv: diff = level_count - len(l) for i in range(diff): l.append(0)
import numpy as np from SkipList import SkipList from Node import Node def printPromptMessage(): print("Type 'add' to add a new contact to your address book") print("Type 'update' to update the information of an existing contact") print("Type 'exit' to exit your address book application") if __name__ == '__main__': current = SkipList() print("Welcome message here") printPromptMessage() userInput:str = input("Your input: ") while (userInput != "exit"): if (userInput == "add"): print("Type the name of the person you want to add: ") personName:str = input("") while len(personName) == 0: print("The person's name cannot have no characters.") print("Please retype the name of you contact: ") personName = input("") print("Type the email of the person you want to add: ") personEmail:str = input("") foundNode:Node = current.search(personName.capitalize()) if (foundNode == None): current.insert(personName.capitalize(), personEmail) print('Added ' + str(personName) + ' to the contact book.') else: print(str(personName) + ' is already in the contact book. ')
import numpy as np from SkipList import SkipList height, p = 10, 0.5 n_items = 200 #make a skip list with specified height and #bubble-up probability skip_list = SkipList(height=height, p=p) items_to_add = np.random.randint(0, 2**(height + 1), n_items) items_to_add = [x for x in set(items_to_add)] #add all the items for item in items_to_add: skip_list.add(item) assert item in skip_list assert skip_list.num_vals == len(set(items_to_add)) print('skip list size :', skip_list.num_vals) print('skip list num elts:', skip_list.num_elts) ratio = skip_list.num_elts / skip_list.num_vals print('ratio : ', ratio) print('actual num vals : ', len(items_to_add)) num_added = skip_list.num_vals for i, to_remove in enumerate(items_to_add): skip_list.remove(to_remove) print('removed item :', to_remove) assert to_remove not in skip_list print('skip list size :', skip_list.num_vals) print('skip list num elts:', skip_list.num_elts)
def __init__(self): self._T = SkipList()
class SortedSkipListMap(Map): def _find_index(self, k, low, high): """ Binary search Return the index of the leftmost item with key >= k return j such that: T[low:j] have key < k T[j:high+1] have key >= k """ if high < low: return high + 1 else: mid = (low + high) // 2 if k == self._T[mid]._key: return mid elif k < self._T[mid]._key: return self._find_index(k, low, mid - 1) else: return self._find_index(k, mid + 1, high) def __init__(self): self._T = SkipList() def __len__(self): return len(self._T) def __getitem__(self, k): j = self._find_index(k, 0, len(self._T) - 1) if j == len(self._T) or self._T[j]._key != k: return False return self._T[j]._value def __setitem__(self, k, v): j = self._find_index(k, 0, len(self._T) - 1) if j < len(self._T) and self._T[j]._key == k: self._T[j]._value = v else: self._T.insert(j, self._Item(k, v)) def __delitem__(self, k): j = self._find_index(k, 0, len(self._T) - 1) if j == len(self._T) or self._T[j]._key != k: return False self._T.pop(j) def __iter__(self): for item in self._T: yield item._key def __reversed__(self): for item in reversed(self._T): yield item._key def find_min(self): if len(self._T) > 0: return (self._T[0]._key, self._T[0]._value) else: return None def find_max(self): if len(self._T) > 0: return (self._T[-1]._key, self._T[-1]._value) else: return None def find_ge(self, k): #return (key,value) where key >= k j = self._find_index(k, 0, len(self._T) - 1) if j < len(self._T): return (self._T[j]._key, self._T[j]._value) else: return None def find_le(self, k): #return (key,value) where key <= k j = self._find_index(k, 0, len(self._T) - 1) if j > 0: return (self._T[j - 1]._key, self._T[j - 1]._value) else: return None def find_gt(self, k): #return (key,value) where key > k j = self._find_index(k, 0, len(self._T) - 1) if j < len(self._T) and self._T[j]._key == k: j += 1 if j < len(self._T): return (self._T[j]._key, self._T[j]._value) else: return None def find_lt(self, k): #return (key,value) where key < k j = self._find_index(k, 0, len(self._T) - 1) if j > 0: return (self._T[j - 1]._key, self._T[j - 1]._value) else: return None def find_range(self, start, stop): #iterate (key,value) where start <= key < stop if start is None: j = 0 else: j = self._find_index(start, 0, len(self._T) - 1) while j < len(self._T) and (stop is None or self._T[j]._key < stop): yield (self.T[j]._key, self._T[j]._value) j += 1
class SkipListMap(Map): #on utilise une skiplist avec des Items comme éléments dans les noeuds #on utilise les valeurs de +infini et -infini pour les sentinelles def __init__(self, _MIN_KEY=_MIN, _MAX_KEY=_MAX): self._T = SkipList(Map._Item(_MIN_KEY, None), Map._Item(_MAX_KEY, None)) def __str__(self): return str(self._T) def __len__(self): return len(self._T) #accès à l'élément k, par appel direct à SkipSearch def __getitem__(self, k): p = self._T.SkipSearch(self._Item(k)) if p._elem._key != k: raise KeyError(k) return p._elem._value #assignation de l'élément de clé k, appel direct à SkipInsert def __setitem__(self, k, v): self._T.SkipInsert(self._Item(k, v)) #suppression de l'élément de clé k, appel direct à SkipRemove def __delitem__(self, k): p = self._T.SkipRemove(self._Item(k)) if p is None: raise KeyError(k) return p._elem._value #itérateur sur les clé def __iter__(self): for item in self._T: yield item._key def pop(self, k): p = self._T.SkipRemove(self._Item(k)) if p is None: raise KeyError(k) return p._elem._value #trouve et retourne l'élément avec la plus petit clé #si la Map n'est pas vide def find_min(self): if len(self._T) > 0: theItem = self._T.Min() return (theItem._key, theItem._value) else: return None #trouve et retourne l'élément avec la plus grande clé #si la Map n'est pas vide def find_max(self): if len(self._T) > 0: theItem = self._T.Max() return (theItem._key, theItem._value) else: return None #retourne ( key, value ), key >= k def find_ge(self, k): #SkipSearch s'arrête sur key <= k p = self._T.SkipSearch(Map._Item(k)) #si on arrête sur la sentinelle à droite #il n'existe pas d'élément dont la clé est >= k if p._next is None: return None #sinon, si l'élément de clé k n'existe pas, #le plus grand est le suivant if p._elem._key < k: p = p._next return (p._elem._key, p._elem._value) #retourne ( key, value ), key <= k def find_le(self, k): #SkipSearch s'arrête sur key <= k p = self._T.SkipSearch(Map._Item(k)) #si on arrête sur la sentinelle à gauche #il n'existe pas d'élément dont la clé est <= k if p._prev is None: return None #sinon, on s'est arrêté dessus return (p._elem._key, p._elem._value) #retourne ( key, value ), key > k def find_gt(self, k): #SkipSearch s'arrête sur key <= k p = self._T.SkipSearch(Map._Item(k)) #si on arrête sur le dernier élément ou la sentinelle à droite #il n'existe pas d'élément dont la clé est > k if p._next is None or p._next._next is None: return None #le plus grand est le suivant #s'il l'élément de clé k existe, le > est le suivant #s'il n'existe pas, le > est aussi le suivant #puisqu'on s'est arrêté sur le premier < p = p._next return (p._elem._key, p._elem._value) #retourne ( key, value ), key < k def find_lt(self, k): #SkipSearch s'arrête sur key <= k p = self._T.SkipSearch(Map._Item(k)) #si on arrête sur le premier élément ou la sentinelle à gauche #il n'existe pas d'élément dont la clé est < k if p._prev is None or p._prev._prev is None: return None #sinon, soit on s'est arrêté sur l'élément de clé k #et on doit prendre son précédent (le premier < devant k) #ou si l'élément de clé k n'existe pas, on est sur le #premier élément de clé < k if p._elem._key == k: p = p._prev return (p._elem._key, p._elem._value) #itérateur des éléments de clé entre start jusqu'au précédent stop def find_range(self, start, stop): #si start est None, on prend start = Min if start is None: start, v = self.find_min() #on cherche l'élément de clé start #on arrête sur ce dernier ou sur le premier élément < p = self._T.SkipSearch(Map._Item(start)) #si l'élément start n'existe pas, on est sur l'élément < #donc, on prend l'élément suivant if p._elem._key < start: p = p._next #tant qu'il y a des éléments dont la clé est < stop #on les rapporte dans l'itérateur while not (p._next is None) and (p._elem._key < stop): yield (p._elem._key, p._elem._value) p = p._next
def __init__(self, _MIN_KEY=_MIN, _MAX_KEY=_MAX): self._T = SkipList(Map._Item(_MIN_KEY, None), Map._Item(_MAX_KEY, None))
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = "neet" from SkipList import SkipList import random if __name__ == '__main__': s = SkipList(10,0.25) print(s) for index in range(1,1000): s.Insert(random.randrange(1,1000,1),"sdfgwef") s.watch() print(s.Search(2)) s.Remove(2) print(s.Search(2)) print(s.Search(3))
__author__ = 'Stephen' from SkipList import SkipList skip = SkipList(5) print skip skip.insert(4) skip.insert(4) skip.insert(4) skip.insert(4) print skip