def test_skiplist_copy(): sl = SkipList() case = gen_special_sort_case(900)['rand_dup20'] for x in case: sl.insert(x) sl = sl.deepcopy() sl_verify(sl) assert list(sl.data_iter()) == sorted(case)
def test_sort_perf(): matrix = [] cases = gen_special_sort_case(2000) for entry in sort_funcs: func = entry['func'] desc = entry.get('name', get_func_name(func)) func_name = get_func_name(func) kwargs = getattr(func, 'keywords', {}) if entry.get('skip_large', False): print(desc, 'skipping large testcase.') continue matrix.append([desc, []]) print('BEGIN {}'.format(desc)) if entry.get('is_random', False): times = 5 else: times = 1 for case, arr in cases.items(): durations = [] for n in range(times): with timed_test('{desc}(_{case}_) #{n}'.format_map(locals()), 'performance') as get_duration: func(arr.copy()) durations.append(get_duration()) matrix[-1][1].append((case, statistics.mean(durations))) print('END {}'.format(desc)) print() print_matrix(matrix)
def test_nth_small_perf(): matrix = [] cases = gen_special_sort_case(2000) for entry in all_select_funcs: func = entry['func'] func_name = entry.get('name', get_func_name(func)) if entry.get('is_random', False): times = 10 else: times = 2 matrix.append([func_name, []]) print('BEGIN', func_name) for case, arr in cases.items(): durations = [] for n in range(times): desc = '{func_name}(_{case}_) #{n}'.format_map(locals()) with timed_test(desc, 'performance') as get_duration: func(arr.copy(), len(arr) // 3) durations.append(get_duration()) matrix[-1][1].append((case, statistics.mean(durations))) print('END', func_name) print() print_matrix(matrix)
def test_nth_small(): for entry in all_select_funcs: func = entry['func'] desc = entry.get('name', get_func_name(func)) if entry.get('skip_large', False): print(desc, 'skipping large testcase.') case_size = 500 else: case_size = 5000 with timed_test(desc): for seq in chain(gen_sort_case(7), gen_special_sort_case(case_size).values()): copy = seq.copy() if len(copy) == 0: continue sorted_input = sorted(copy) if len(copy) > 20: ranger = range(0, len(copy), len(copy) // 10) else: ranger = range(len(copy)) for i in ranger: n = i + 1 selected = func(copy.copy(), n) assert selected == sorted_input[i], \ '{desc}({copy}, {n}) -> {selected}'.format_map(vars()) for large_func in (nth_large, nth_large_mm): with timed_test(get_func_name(large_func)): assert large_func(list(range(100)), 5) == 95
def test_insert(): cases = gen_special_sort_case(2000) matrix = [] for entry in all_trees: tree_type = entry['tree'] tree_name = tree_type.__name__ if entry.get('is_random', False): times = 5 else: times = 3 matrix.append([tree_name, []]) for case_name, arr in cases.items(): durations = [] for n in range(times): tree = tree_type() with timed_test( '{tree_name}, _{case_name}_, #{n}'.format_map(vars()), 'performance') as get_duration: for x in arr: tree.insert(x) durations.append(get_duration()) matrix[-1][1].append((case_name, statistics.mean(durations))) print() print_matrix(matrix)
def test_depth_distribution_by_insert(): cases = gen_special_sort_case(2000) for entry in all_trees: tree_type = entry['tree'] tree_name = tree_type.__name__ if entry.get('is_random', False): times = 5 else: times = 3 for case_name, arr in cases.items(): dists = [] for n in range(times): tree = tree_type() for x in arr: tree.insert(x) dists.append(measure_nil_depth(tree)) stats = list(map(get_stats_from_nil_depth, dists)) mean_stats = average_depth_stats(stats) dist = get_percentage_dist(dists) print(tree_name, case_name, mean_stats) min_depth, max_depth = min(dist.keys()), max(dist.keys()) for d in range(min_depth, max_depth + 1): if d not in dist: dist[d] = 0 pairs = list(dist.items()) pairs.sort(key=lambda p: p[0]) print_histogram(pairs) print()
def test_skiplist_lower_upper_bound(): def list_lower_bound(lst, data): return lst[bisect.bisect_left(lst, data):] def list_upper_bound(lst, data): return list(reversed(lst[:bisect.bisect_right(lst, data)])) assert list_lower_bound([1, 1, 2, 2, 3], 2) == [2, 2, 3] assert list_lower_bound([1, 1, 2, 2, 3], 1.5) == [2, 2, 3] assert list_upper_bound([1, 1, 2, 2, 3], 2) == [2, 2, 1, 1] assert list_upper_bound([1, 1, 2, 2, 3], 1.5) == [1, 1] def run(col): sl = SkipList() for x in col: sl.insert(x) lst = sorted(col) for x in sorted(set(lst)): for data in (x, x + 0.5): assert list(sl.lower_bound(data)) == list_lower_bound(lst, data) assert list(sl.upper_bound(data)) == list_upper_bound(lst, data) assert list(sl.lower_bound(float('-inf'))) == list_lower_bound(lst, float('-inf')) assert list(sl.lower_bound(float('+inf'))) == list_lower_bound(lst, float('+inf')) assert list(sl.upper_bound(float('-inf'))) == list_upper_bound(lst, float('-inf')) assert list(sl.upper_bound(float('+inf'))) == list_upper_bound(lst, float('+inf')) for name, case in gen_special_sort_case(900).items(): with timed_test(('SkipList::lower_bound()' ' & SkipList::upper_bound(), {name}').format_map(locals())): run(case)
def test_skiplist_insert(): size = 900 cases = [ (name, case) for name, case in gen_special_sort_case(size).items() if name in {'ascending', 'descending', 'dup', 'rand_dup20'} ] for name, case in cases: with timed_test('SkipList::insert(), {name}'.format_map(locals())): sl = SkipList() for i, x in enumerate(case): sl.insert(x) sl_verify(sl) assert list(sl.data_iter()) == sorted(case[:(i + 1)])
def test_remove(): rand_case = gen_special_sort_case(2000)['rand'] sorted_case = sorted(rand_case) shuffled_case = rand_case.copy() random.shuffle(shuffled_case) remove_orders = dict( ascending=sorted_case, descending=list(reversed(sorted_case)), origin=rand_case, random=shuffled_case ) matrix = [] for entry in all_trees: tree_type = entry['tree'] tree_name = tree_type.__name__ if entry.get('is_random', False): times = 5 else: times = 3 matrix.append([tree_name, []]) tree = tree_type() for x in rand_case: tree.insert(x) for case_name, arr in remove_orders.items(): durations = [] for n in range(times): test_tree = tree.deepcopy() with timed_test( '{tree_name}, {case_name}, #{n}'.format_map(vars()), 'performance') as get_duration: for x in arr: test_tree.remove(x) assert test_tree.root is None durations.append(get_duration()) matrix[-1][1].append((case_name, statistics.mean(durations))) print() print_matrix(matrix)
def test_skiplist_remove_find(): rand_case = gen_special_sort_case(900)['rand_dup20'] sorted_case = sorted(rand_case) shuffled_case = rand_case.copy() random.shuffle(shuffled_case) remove_orders = dict( ascending=sorted_case, descending=list(reversed(sorted_case)), origin=rand_case, random=shuffled_case ) for name, case in remove_orders.items(): all_nums = MultiTreeSet(rand_case) sl = SkipList() for x in rand_case: sl.insert(x) sl_verify(sl) with timed_test('SkipList::remove() & SkipList::find(), {name}'.format_map(locals())): for x in case: # test find() found = sl.find(x) assert found.data == x assert sl.find(x + 0.5) is None # not exists removed = sl.remove(x) assert removed.data == x sl_verify(sl) assert sl.remove(x + 0.5) is None # not exists sl_verify(sl) all_nums.remove(x) assert list(sl.data_iter()) == list(all_nums) # not exists assert sl.find(float('-inf')) is None assert sl.remove(float('-inf')) is None sl_verify(sl)
def gen_spec_case(size): spec_cases = gen_special_sort_case(size) for case in ('rand', 'dup', 'dup99'): yield spec_cases[case]