```python
import hashlib
import numpy as np
import math
import collections
from zlib import crc32
import random
import operator
import scipy.stats as stats
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
from scipy.optimize import brentq
from sympy import Symbol, solve, log
from scipy.optimize import fsolve
import scipy
import hashlib
import array
import matplotlib.cm as cm
import operator
from collections import defaultdict
import pandas as pd
import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))
# use matplotlib: 3.1.0

```

    matplotlib: 3.1.0

```python
from spacesaving import SpaceSaving
from githubCountMin import CountMinSketch
from CSSS import CSSS_CountSketch, CSSS_sketch
```

```python
# read CAIDA TCP traces
# the path may need to be updated for others
df = pd.read_csv('./data/tcp/20151217_125911_dirA.csv',sep='\t')
dip = df[df.columns[3]]
```

```python
    # A simple test
    test = SpaceSaving(2)
    stream = ['a','b','c', 'a', 'a','-a']
    dic = defaultdict(int)
    for item in stream:
        if len(item) == 1:
            test.update(item, 1)
            dic[item]+=1
        else:
            test.update(item[1:], -1)
            dic[item[1:]] -= 1
    test.output()
    print("item, F', F")
    for item in set(stream):
        if len(item) == 1:
            print(item, test.query(item), dic[item])
```

    weight_heap:  [['c', 2], ['a', 2]]
    error_heap (-1*error):  [['c', -1], ['a', -1]]
    map:  defaultdict(<class 'list'>, {'c': [0, 0], 'a': [1, 1]})
    item, F', F
    b 0 1
    a 2 2
    c 2 1

```python
    def create_recall(stream_type, arr, skew=1.0, s = 10**5, u = 2**16):
        phis = []
        if stream_type == "zipf":
            phis = [2**(-4),2**(-5),2**(-6), 2**(-7)]
        elif stream_type == "bin":
            phis = [2**(-9),2**(-10),2**(-11), 2**(-12)]
        else:
            phis = [2**(-7),2**(-8),2**(-9), 2**(-10)]

        ss_recall = {}
        lazy_ss_recall = {}
        csss_recall = {}
        cm_recall = {}
        cs_recall = {}

        total_spaces = {}
        Turnstile_model_maker = ['^:','^-.']
        markers = {0.5:['kv-','kv--','kv:', '*:', '*-.']}

        runs = 5
        universe = u
        size = s
        a = skew
        rates = [0.5]
        alphas = [2]
        p = 0.1
        CAIDASIZE = 2*(10**6)

        for i in range(len(rates)):
            rate = rates[i]
            alpha = alphas[i]

            ss_avg_recalls = []
            lazy_ss_avg_recalls  = []
            csss_avg_recalls = []
            cm_avg_recalls = []
            cs_avg_recalls = []

            total_space = []

            for j in range(len(phis)):

                sum_ss_avg_recall = 0
                sum_lazy_ss_avg_recall = 0
                sum_csss_avg_recall = 0
                sum_cm_avg_recall = 0
                sum_cs_avg_recall = 0

                phi = phis[j]
                epsilon_prime = phi/32
                k = 1/epsilon_prime
                first_run = True

                for run in range(runs):
                    ss_space = math.ceil(alpha/phi) #number of counters
                    SS = SpaceSaving(ss_space)
                    LAZY_SS = SpaceSaving(ss_space, True)
                    CM = CountMinSketch( math.ceil((1.0/phi)), math.ceil(math.log2(universe))) #cols, rows
                    CS = CSSS_CountSketch(math.ceil(math.log2(universe)), math.ceil((1.0/phi)))

                    if first_run:
                        first_run = False
                        temp = total_spaces.get("SS"+str(rate), [])
                        temp.append(ss_space*math.log2(universe))
                        total_spaces["SS"+str(rate)] = temp

                        temp = total_spaces.get("CM"+str(rate), [])
                        temp.append( ss_space*math.log2(universe)*math.log2(universe)/2.0)
                        total_spaces["CM"+str(rate)] = temp

                    insertions = []
                    deletions = []

                    if stream_type == "zipf":
                        range_x = np.arange(1,universe)
                        weights = range_x ** (-a)
                        weights /= weights.sum()
                        bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(range_x, weights))

                        insert_size = int(size/(1-rate))
                        insertions = bounded_zipf.rvs(size=insert_size)

                        deletions = random.sample(list(insertions), int(rate*insert_size))

                    elif stream_type == "bin":
                        insert_size = int(size/(1-rate))
                        insertions = list(np.random.binomial(u, p, insert_size))
                        deletions = random.sample(list(insertions), int(rate*insert_size))

                    else:
                        insertions = arr[run*CAIDASIZE:(run+1)*CAIDASIZE]
                        deletions = random.sample(list(insertions), int(rate*CAIDASIZE))

                    true_result = {}
                    for item in insertions:
                        SS.update(str(item), 1)
                        LAZY_SS.update(str(item), 1)
                        true_result[str(item)] = true_result.get(str(item), 0) + 1
                        CM.add(str(item), 1)
                        CS.add(str(item), 1)

                    for item in deletions:
                        SS.update(str(item), -1)
                        LAZY_SS.update(str(item), -1)
                        true_result[str(item)] -= 1
                        CM.add(str(item), -1)
                        CS.add(str(item), -1)

                    true_frequent_items = set()
                    frequent_threshold = phi*(len(insertions)-len(deletions))
                    for key, val in true_result.items():
                        if val > frequent_threshold:
                            true_frequent_items.add(key)

                    ss_avg_tp = 0
                    lazy_ss_avg_tp = 0
                    cm_avg_tp = 0
                    cs_avg_tp = 0

                    ss_avg_fn = 0
                    lazy_ss_avg_fn = 0
                    cm_avg_fn = 0
                    cs_avg_fn = 0

                    for item in true_frequent_items:
                        if SS.query(item) > frequent_threshold:
                            ss_avg_tp+=1
                        else:
                            ss_avg_fn+=1

                        if LAZY_SS.query(item) > frequent_threshold:
                            lazy_ss_avg_tp+=1
                        else:
                            lazy_ss_avg_fn+=1

                        if rate == 0.5:
                            cm_estimate = CM.query(item)
                            if cm_estimate > frequent_threshold:
                                cm_avg_tp+=1
                            else:
                                cm_avg_fn+=1

                            cs_estimate = CS.query(item)
                            if cs_estimate > frequent_threshold:
                                cs_avg_tp+=1
                            else:
                                cs_avg_fn+=1

                    ss_avg_recall = 1.0*ss_avg_tp / (ss_avg_tp +ss_avg_fn)
                    lazy_ss_avg_recall = 1.0*lazy_ss_avg_tp / (lazy_ss_avg_tp+lazy_ss_avg_fn)
                    if rate == 0.5:
                        cm_avg_recall = 1.0*cm_avg_tp / (cm_avg_tp + cm_avg_fn)
                        cs_avg_recall = 1.0*cs_avg_tp / (cs_avg_tp + cs_avg_fn)

                    sum_ss_avg_recall += ss_avg_recall
                    sum_lazy_ss_avg_recall += lazy_ss_avg_recall
                    if rate == 0.5:
                        sum_cm_avg_recall += cm_avg_recall
                        sum_cs_avg_recall += cs_avg_recall

                ss_avg_recalls.append(sum_ss_avg_recall/ runs)
                lazy_ss_avg_recalls.append(sum_lazy_ss_avg_recall/ runs)
                cm_avg_recalls.append(sum_cm_avg_recall/ runs)
                cs_avg_recalls.append(sum_cs_avg_recall/ runs)

            ss_recall[rate] = ss_avg_recalls
            lazy_ss_recall[rate] = lazy_ss_avg_recalls

            cm_recall[rate] = cm_avg_recalls
            cs_recall[rate] = cs_avg_recalls

        fig = plt.figure()
        if stream_type == "zipf":
            plt.title("Zipf("+str(a)+")", fontsize=20)

        elif stream_type == "bin":
            plt.title("Binomial("+str(p)+")", fontsize=20)

        else:
            plt.title("CAIDA", fontsize=20)

        plt.xlabel('\u03C6', fontsize=19)
        plt.ylabel('Recall', fontsize=19)
        plt.xscale('log', basex=2)

        plt.rc('xtick',labelsize=15)
        plt.rc('ytick',labelsize=15)

        position = [[],[],[],[],[]]
        widths = [[],[],[],[]]
        position_arr = []
        if stream_type == 'zipf':
            position_arr = [(-7.5, -6.5),(-6.5, -5.5),(-5.5, -4.5),(-4.5, -3.5)]
        elif stream_type == 'bin':
            position_arr = [(-12.5, -11.5),(-11.5, -10.5),(-10.5, -9.5),(-9.5, -8.5)]
        else:
            position_arr = [(-10.5, -9.5),(-9.5, -8.5),(-8.5, -7.5),(-7.5, -6.5)]

        for start,end in position_arr:
            x = np.logspace(start,end, num=6, base=2)
            w = np.diff(x)
            temp = 0
            for idx, item in enumerate(x[1:-1]):
                position[temp%4].insert(0,item)
                temp+=1
            temp = 0
            for i in w[1:]:
                widths[temp%4].insert(0,i)
                temp+=1

        ax = fig.add_subplot(111)
        ax.xaxis.set_ticks_position('none')
        ax2 = ax.twinx()
        ax2.set_ylabel("Space(bits)", fontsize=21)
        ax2.set_yscale('log', basey=2)

        for i in range(1):
            b1 = ax.bar(position[0], ss_recall[rates[i]], width=widths[0], color = 'dimgrey', label='SpaceSaving\u00B1')
            b2 = ax.bar(position[1], lazy_ss_recall[rates[i]], width=widths[1], color = 'silver',label='Lazy')
            b4 = ax.bar(position[2], cm_recall[rates[i]], width=widths[2], color = 'cornflowerblue', label='Count-Min')
            b5 = ax.bar(position[3], cs_recall[rates[i]], width=widths[3], color = 'bisque', label='Count Median')

        for i in range(1):
            l6 = ax2.plot(phis, total_spaces['SS0.5'], 'x--', color = 'k', label='SpaceSaving\u00B1 Space')
            l7 = ax2.plot(phis, total_spaces['CM0.5'], 'v--', color = 'red', label='CMin/CMedian Space')

        ax.legend(prop={'size': 12}, loc='lower left')
        ax2.legend(prop={'size': 12}, loc='lower right')

        plt.show()
        print("SS:", ss_recall)
        print("Lazy SS:", lazy_ss_recall)
        print("CM:", cm_recall)
        print("CS:", cs_recall)
```

```python

```

```python
     create_recall("bin", [], 0.1, 1000)
```

```python
    create_recall("zipf", [], 1.0)
```

```python
create_recall("CAIDA", dip)
```

```python

```

```python
    def create_precision(stream_type, arr, skew=1.0, s = 10**5, u = 2**16):
        phis = []
        if stream_type == "zipf":
            phis = [2**(-4),2**(-5),2**(-6), 2**(-7)]
        elif stream_type == "bin":
            phis = [2**(-9),2**(-10),2**(-11), 2**(-12)]
        else:
            phis = [2**(-7),2**(-8),2**(-9), 2**(-10)]

        ss_precision = {}
        lazy_ss_precision = {}
        csss_precision = {}
        cm_precision = {}
        cs_precision = {}
        total_spaces = {}
        Turnstile_model_maker = ['^:','^-.']
        markers = {0.5:['kv-','kv--','kv:', '*:', '*-.']}

        runs = 5
        universe = u
        size = s
        a = skew
        rates = [0.5]
        alphas = [2]
        p = 0.1
        CAIDASIZE = 2*(10**6)

        for i in range(len(rates)):
            rate = rates[i]
            alpha = alphas[i]

            ss_avg_precisions = []
            lazy_ss_avg_precisions = []
            csss_avg_precisions = []
            cm_avg_precisions = []
            cs_avg_precisions = []

            total_space = {}

            for j in range(len(phis)):

                sum_ss_avg_precision = 0
                sum_lazy_ss_avg_precision = 0
                sum_csss_avg_precision = 0
                sum_cm_avg_precision = 0
                sum_cs_avg_precision = 0

                phi = phis[j]
                epsilon_prime = phi/32
                k = 1/epsilon_prime

                first_run = True
                run = 0
                while run < runs:
                    run += 1
                    ss_space = math.ceil(alpha/phi) # number of counters
                    SS = SpaceSaving(ss_space)
                    LAZY_SS = SpaceSaving(ss_space, True)

                    CM = CountMinSketch( math.ceil((1.0/phi)), math.ceil(math.log2(universe))) # cols, rows
                    CS = CSSS_CountSketch(math.ceil(math.log2(universe)), math.ceil((1.0/phi)))

                    insertions = []
                    deletions = []

                    if stream_type == "zipf":
                        range_x = np.arange(1,universe)
                        weights = range_x ** (-a)
                        weights /= weights.sum()
                        bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(range_x, weights))

                        insert_size = int(size/(1-rate))
                        insertions = bounded_zipf.rvs(size=insert_size)
                        deletions = random.sample(list(insertions), int(rate*insert_size))

                    elif stream_type == "bin":
                        insert_size = int(size/(1-rate))
                        insertions = list(np.random.binomial(u, p, insert_size))
                        deletions = random.sample(list(insertions), int(rate*insert_size))

                    else:
                        insertions = arr[run*CAIDASIZE:(run+1)*CAIDASIZE]
                        deletions = random.sample(list(insertions), int(rate*CAIDASIZE))

                    if first_run:
                        first_run = False
                        temp = []
                        temp = total_spaces.get("SS"+str(rate), [])
                        temp.append(ss_space*math.log2(universe))
                        total_spaces["SS"+str(rate)] = temp

                        temp = total_spaces.get("CM"+str(rate), [])
                        temp.append(ss_space*math.log2(universe)*math.log2(universe)/2.0)
                        total_spaces["CM"+str(rate)] = temp

                    true_result = {}
                    for i in insertions:
                        SS.update(str(i), 1)
                        LAZY_SS.update(str(i), 1)
                        CM.add(str(i), 1)
                        CS.add(str(i), 1)

                        true_result[str(i)] = true_result.get(str(i), 0) + 1

                    for i in deletions:
                        SS.update(str(i), -1)
                        LAZY_SS.update(str(i), -1)
                        true_result[str(i)] -= 1
                        CM.add(str(i), -1)
                        CS.add(str(i), -1)

                    true_frequent_items = set()
                    frequent_threshold = phi*(len(insertions)-len(deletions))
                    for key, val in true_result.items():
                        if val >= frequent_threshold:
                            true_frequent_items.add(key)

                    csss_avg_tp = 0
                    ss_avg_tp = 0
                    lazy_ss_avg_tp = 0
                    cm_avg_tp = 0
                    cs_avg_tp = 0

                    csss_avg_fp = 0
                    ss_avg_fp = 0
                    lazy_ss_avg_fp = 0
                    cm_avg_fp = 0
                    cs_avg_fp = 0

                    for item,_ in true_result.items():

                        if SS.query(item) >= frequent_threshold:
                            if item in true_frequent_items:
                                ss_avg_tp+=1
                            else:
                                ss_avg_fp+=1

                        if LAZY_SS.query(item) >= frequent_threshold:
                            if item in true_frequent_items:
                                lazy_ss_avg_tp+=1
                            else:
                                lazy_ss_avg_fp+=1

                        cm_estimate = CM.query(item)
                        if cm_estimate >= frequent_threshold:
                            if item in true_frequent_items:
                                cm_avg_tp+=1
                            else:
                                cm_avg_fp+=1

                        cs_estimate = CS.query(item)
                        if cs_estimate >= frequent_threshold:
                            if item in true_frequent_items:
                                cs_avg_tp+=1
                            else:
                                cs_avg_fp+=1

                    if lazy_ss_avg_tp+lazy_ss_avg_fp != 0:
                        lazy_ss_avg_precision = 1.0*lazy_ss_avg_tp / (lazy_ss_avg_tp+lazy_ss_avg_fp)
                    else:
                        print("need to be skewed")
                        exit()

                    if (ss_avg_tp +ss_avg_fp ) != 0:
                        ss_avg_precision = 1.0*ss_avg_tp / (ss_avg_tp +ss_avg_fp )
                    else:
                        print("need to be skewed")
                        exit()

                    if (cm_avg_tp + cm_avg_fp) != 0:
                        cm_avg_precision = 1.0*cm_avg_tp / (cm_avg_tp + cm_avg_fp)
                    else:
                        print("need to be skewed")
                        exit()

                    if (cs_avg_tp + cs_avg_fp)!=0:
                        cs_avg_precision = 1.0*cs_avg_tp / (cs_avg_tp + cs_avg_fp)
                    else:
                        print("need to be skewed")
                        exit()

                    sum_ss_avg_precision += ss_avg_precision
                    sum_lazy_ss_avg_precision += lazy_ss_avg_precision

                    sum_cm_avg_precision += cm_avg_precision
                    sum_cs_avg_precision += cs_avg_precision

                ss_avg_precisions.append(sum_ss_avg_precision/ runs)
                lazy_ss_avg_precisions.append(sum_lazy_ss_avg_precision/ runs)
                cm_avg_precisions.append(sum_cm_avg_precision/ runs)
                cs_avg_precisions.append(sum_cs_avg_precision/ runs)

            ss_precision[rate] = ss_avg_precisions
            lazy_ss_precision[rate] = lazy_ss_avg_precisions
            cm_precision[rate] = cm_avg_precisions
            cs_precision[rate] = cs_avg_precisions

        fig = plt.figure()
        if stream_type == "zipf":
                plt.title("Zipf("+str(a)+")", fontsize=20)
        elif stream_type == "bin":
                plt.title("Binomial("+str(p)+")", fontsize=20)
        else:
                plt.title("CAIDA", fontsize=20)

        plt.xlabel('\u03C6', fontsize=19)
        plt.ylabel('Precision', fontsize=19)

        plt.rc('xtick',labelsize=15)
        plt.rc('ytick',labelsize=15)

        plt.xscale('log', basex=2)
        position = [[],[],[],[],[]]
        widths = [[],[],[],[]]
        if stream_type == 'bin':
            position_arr = [(-12.5, -11.5),(-11.5, -10.5),(-10.5, -9.5),(-9.5, -8.5)]
        elif stream_type == 'zipf':
            position_arr = [(-7.5, -6.5),(-6.5, -5.5),(-5.5, -4.5),(-4.5, -3.5)]
        else:
            position_arr = [(-10.5, -9.5),(-9.5, -8.5),(-8.5, -7.5),(-7.5, -6.5)]

        for start,end in position_arr:
            x = np.logspace(start,end, num=6, base=2)
            w = np.diff(x)
            temp = 0
            for idx, item in enumerate(x[1:-1]):
                position[temp%4].insert(0,item)
                temp+=1
            temp = 0
            for i in w[1:]:
                widths[temp%4].insert(0,i)
                temp+=1

        ax = fig.add_subplot(111)
        ax.xaxis.set_ticks_position('none')
        ax2 = ax.twinx()
        ax2.set_ylabel("Space(bits)", fontsize=19)
        ax2.set_yscale('log', basey=2)

        for i in range(1):
            b1 = ax.bar(position[0], ss_precision[rates[i]], width=widths[0], color = 'dimgrey', label='SpaceSaving\u00B1')
            b2 = ax.bar(position[1], lazy_ss_precision[rates[i]], width=widths[1],color = 'silver',label='Lazy')
            b4 = ax.bar(position[2], cm_precision[rates[i]], width=widths[2],color = 'cornflowerblue', label='Count-Min')
            b5 = ax.bar(position[3], cs_precision[rates[i]], width=widths[3],color = 'bisque', label='Count Median')

        for i in range(1):
            l6 = ax2.plot(phis, total_spaces['SS0.5'], 'kx--', label='SpaceSaving\u00B1 Space')
            l7 = ax2.plot(phis, total_spaces['CM0.5'], 'rx--',label='CMin/CMedian Space')

        ax.legend(prop={'size': 12}, loc='lower left')
        ax2.legend(prop={'size': 12}, loc='lower right')

        plt.show()
        print("SS:", ss_precision)
        print("Lazy SS:", lazy_ss_precision)
        print("CM:", cm_precision)
        print("CS:", cs_precision)
```

```python
    create_precision("bin", [], 0.1)
```

```python
    create_precision("zipf", [], 1.0)
```

```python
    create_precision("CAIDA", dip)
```

```python
    def frequency_estimation(stream_type, shuffled, arr, skew=1.0, s = 10**5, univ = 2**16):
        ss_avg = {}
        lazy_ss_avg = {}
        csss_avg = {}
        cm_avg = {}
        cs_avg = {}

        total_spaces = {}

        Turnstile_model_maker = ['^:','^-.']
        markers = {0.5:['kv-','kv--','kv:']}
        runs = 5
        universe = univ
        size = s
        R = size # assume we can capture R without any error. It is used for the CSSS Sketch
        a = skew
        CAIDASIZE = 2*(10**6)

        epsilons = []
        if stream_type != 'bin':
            epsilons = [2**(-1),2**(-2),2**(-3),2**(-4)]
        else:
            epsilons = [0.8,0.6,0.4,0.2]
        rates = [0.5]
        alphas = [2]

        for i in range(len(rates)):
            rate = rates[i]
            alpha = alphas[i]
            ss_avg_errors = []
            lazy_ss_avg_errors = []
            csss_avg_errors = []
            cm_avg_errors = []
            cs_avg_errors = []

            total_space = []

            for eps in epsilons:
                sum_ss_avg_error = 0
                sum_lazy_ss_avg_error = 0
                sum_csss_avg_error = 0
                sum_cm_avg_error = 0
                sum_cs_avg_error = 0

                first_run = True

                for run in range(runs):

                    CSSS = CSSS_sketch(eps, universe, 1.0/eps, alpha)

                    # CSSS space output the total bits used
                    # SpaceSaving and Linear Sketch use logU bits per counter

                    ss_space = math.ceil( CSSS.space()/math.log2(universe) )

                    SS = SpaceSaving(ss_space)
                    LAZY_SS = SpaceSaving(ss_space, True)

                    CM = CountMinSketch( math.ceil(1.0*ss_space/math.log2(universe)), math.ceil(math.log2(universe))) #cols, rows
                    CS = CSSS_CountSketch(math.ceil(math.log2(universe)), math.ceil(1.0*ss_space/math.log2(universe)))

                    if first_run:
                        first_run = False
                        total_space.append(CSSS.space())

                    insertions = []
                    deletions = []

                    # makeing sure size = |F| = I-D = insert_size(1-r)
                    insert_size = int(size/(1-rate))

                    if stream_type == 'zipf':
                        range_x = np.arange(1,universe)
                        weights = range_x ** (-a)
                        weights /= weights.sum()
                        bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(range_x, weights))

                        insertions = bounded_zipf.rvs(size=insert_size)
                        if shuffled:
                            deletions = random.sample(list(insertions), int(rate*insert_size))

                    elif stream_type == 'bin':
                        insertions = list(np.random.binomial(universe, a, insert_size))
                        if shuffled:
                            deletions = random.sample(list(insertions), int(rate*insert_size))

                    else:
                        assert(len(arr)>0)
                        insertions = arr[run*CAIDASIZE:(run+1)*CAIDASIZE]
                        if shuffled:
                            deletions = random.sample(list(insertions), int(rate*len(insertions)))

                    if not shuffled:
                        dic = collections.Counter(insertions)
                        ordered_dic = collections.OrderedDict(sorted(dic.items(), key=operator.itemgetter(1)))
                        targeted_length = int(rate*len(insertions))
                        for item, val in ordered_dic.items():
                            for i in range(val):
                                if len(deletions)<targeted_length:
                                    deletions.append(item)
                                else:
                                    break
                            if len(deletions)>=targeted_length:
                                break

                    true_result = {}
                    for i in insertions:
                        CSSS.update(str(i), 1)
                        SS.update(str(i), 1)
                        LAZY_SS.update(str(i), 1)
                        CM.add(str(i), 1)
                        CS.add(str(i), 1)
                        true_result[str(i)] = true_result.get(str(i), 0) + 1

                    for i in deletions:
                        CSSS.update(str(i), -1)
                        SS.update(str(i), -1)
                        LAZY_SS.update(str(i), -1)
                        CM.add(str(i), -1)
                        CS.add(str(i), -1)
                        true_result[str(i)] -= 1

                    csss_avg_error = 0

                    ss_avg_error = 0
                    lazy_ss_avg_error = 0

                    cm_avg_error = 0
                    cs_avg_error = 0

                    for item in true_result.keys():
                        csss_estimate = CSSS.query(item)
                        csss_error = abs(true_result.get(item,0) - csss_estimate)

                        ss_estimate = SS.query(item)
                        ss_error = abs(true_result.get(item,0) - ss_estimate)

                        lazy_ss_estimate = LAZY_SS.query(item)
                        lazy_ss_error = abs(true_result.get(item,0) - lazy_ss_estimate)

                        cm_estimate = CM.query(item)
                        cm_error = abs(true_result.get(item,0) - cm_estimate)

                        cs_estimate = CS.query(item)
                        cs_error = abs(true_result.get(item,0) - cs_estimate)

                        csss_avg_error += csss_error**2
                        ss_avg_error += ss_error**2
                        lazy_ss_avg_error += lazy_ss_error**2
                        cm_avg_error += cm_error**2
                        cs_avg_error += cs_error**2

                    u = len(true_result.keys())
                    csss_avg_error = 1.0*csss_avg_error / u
                    ss_avg_error = 1.0*ss_avg_error / u
                    lazy_ss_avg_error = 1.0*lazy_ss_avg_error / u
                    cm_avg_error = 1.0*cm_avg_error / u
                    cs_avg_error = 1.0*cs_avg_error / u

                    sum_ss_avg_error += ss_avg_error
                    sum_lazy_ss_avg_error += lazy_ss_avg_error
                    sum_csss_avg_error += csss_avg_error
                    sum_cm_avg_error += cm_avg_error
                    sum_cs_avg_error += cs_avg_error

                ss_avg_errors.append(sum_ss_avg_error/ runs)
                lazy_ss_avg_errors.append(sum_lazy_ss_avg_error/ runs)

                csss_avg_errors.append(sum_csss_avg_error/ runs)

                cm_avg_errors.append(sum_cm_avg_error/ runs)
                cs_avg_errors.append(sum_cs_avg_error/ runs)

            ss_avg[rate] = ss_avg_errors
            lazy_ss_avg[rate] = lazy_ss_avg_errors
            csss_avg[rate] = csss_avg_errors
            cm_avg[rate] = cm_avg_errors
            cs_avg[rate] = cs_avg_errors
            total_spaces[rate] = total_space

        plt.figure()
        if stream_type == 'zipf':
            if shuffled:
                plt.title("Zipf("+str(a)+")", fontsize=20)
            else:
                plt.title("Zipf("+str(a)+"), Delete Least Frequent", fontsize=20)
            plt.ylim([10**1, 10**9])
        elif stream_type == 'bin':
            if shuffled:
                plt.title("Binomial("+str(a)+")", fontsize=20)
            else:
                plt.title("Binomial("+str(a)+"), Delete Least Frequent", fontsize=20)
            plt.ylim([10**3, 10**9])
        else:
            if shuffled:
                plt.title(str(stream_type)+"", fontsize=20)
            else:
                plt.title(str(stream_type)+", Delete Least Frequent", fontsize=20)
            plt.ylim([10**2.5, 10**11])

        plt.xlabel('Space(bits)', fontsize=19)
        plt.ylabel('MSE', fontsize=19)

        plt.rc('xtick',labelsize=15)
        plt.rc('ytick',labelsize=15)

        plt.yscale('log', basey=10)
        plt.xscale('log', basex=2)
        for i in range(len(rates)):
            plt.plot(total_spaces[rates[i]], ss_avg[rates[i]], markers[rates[i]][0], label='SpaceSaving\u00B1, '+"D"+str(rates[i]))
            plt.plot(total_spaces[rates[i]], lazy_ss_avg[rates[i]], markers[rates[i]][2], label='Lazy, '+"D"+str(rates[i]))
            plt.plot(total_spaces[rates[i]], csss_avg[rates[i]], markers[rates[i]][1],label='CSSS, '+"D"+str(rates[i]))
            plt.plot(total_spaces[rates[i]], cm_avg[rates[i]], Turnstile_model_maker[0] ,label='Count-Min, '+"D"+str(rates[i]))
            plt.plot(total_spaces[rates[i]], cs_avg[rates[i]], Turnstile_model_maker[1],label='Count Median, '+"D"+str(rates[i]))
        print(total_spaces)
        print(ss_avg)
        print(lazy_ss_avg)
        print(csss_avg)
        print(cm_avg)
        print(cs_avg)
        plt.legend(prop={'size': 12})

```

```python

```

```python
    frequency_estimation('zipf', True, [], 1.0)
```

```python
    frequency_estimation('zipf', False, [], 1.0)
```

```python
    frequency_estimation('bin', True, [], 0.1)
```

```python
    frequency_estimation('bin', False, [],0.1)
```

```python

```

```python
    frequency_estimation('CAIDA', True, dip)
```

```python
    frequency_estimation('CAIDA', False, dip)
```

```python
import time
def update_time(stream_type, shuffled, arr, skew=1.0, u = 2**16):

        stream_length = [3**8, 3**9, 3**10, 3**11]

        ss_updatetime = {}
        lazy_ss_updatetime = {}
        csss_updatetime = {}
        cm_updatetime = {}
        cs_updatetime = {}

        total_spaces = {}
        Turnstile_model_maker = ['^:','^-.']
        markers = {0.5:['kv-','kv--','kv:', '*:', '*-.']}

        runs = 5
        universe = u
        a = skew
        rates = [0.5]
        alphas = [2]

        for i in range(len(rates)):
            rate = rates[i]
            alpha = alphas[i]

            ss_avg_updatetime = []
            lazy_ss_avg_updatetime  = []
            csss_avg_updatetime = []
            cm_avg_updatetime = []
            cs_avg_updatetime = []

            for j in range(len(stream_length)):
                size = stream_length[j]

                sum_ss_avg_updatetime = 0
                sum_lazy_ss_avg_updatetime = 0
                sum_csss_avg_updatetime = 0
                sum_cm_avg_updatetime = 0
                sum_cs_avg_updatetime = 0

                first_run = True

                for run in range(runs):
                    #1000 logU counters
                    SS = SpaceSaving(1000)
                    LAZY_SS = SpaceSaving(1000, True)
                    CM = CountMinSketch(62, 16) #cols, rows
                    CS = CSSS_CountSketch(16, 62)
                    CSSS = CSSS_sketch(1.0/17, universe, 17, 2)

                    insertions = []
                    deletions = []

                    if stream_type == "zipf":
                        range_x = np.arange(1,universe)
                        weights = range_x ** (-a)
                        weights /= weights.sum()
                        bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(range_x, weights))

                        insert_size = int(size/(1-rate))
                        insertions = bounded_zipf.rvs(size=insert_size)

                        if shuffled:
                            deletions = random.sample(list(insertions), int(rate*insert_size))

                    start = time.time()
                    for item in insertions:
                        SS.update(str(item), 1)
                    for item in deletions:
                        SS.update(str(item), -1)
                    end = time.time()
                    SS_times = 1.0*(end-start)/(len(insertions)+len(deletions))

                    start = time.time()
                    for item in insertions:
                        LAZY_SS.update(str(item), 1)
                    for item in deletions:
                        LAZY_SS.update(str(item), -1)
                    end = time.time()
                    LAZY_SS_times = 1.0*(end-start)/(len(insertions)+len(deletions))

                    start = time.time()
                    for item in insertions:
                        CM.add(str(item), 1)
                    for item in deletions:
                        CM.add(str(item), -1)
                    end = time.time()
                    CM_times = 1.0*(end-start)/(len(insertions)+len(deletions))

                    start = time.time()
                    for item in insertions:
                        CS.add(str(item), 1)
                    for item in deletions:
                        CS.add(str(item), -1)
                    end = time.time()
                    CS_times = 1.0*(end-start)/(len(insertions)+len(deletions))

                    start = time.time()
                    for item in insertions:
                        CSSS.update(str(i), 1)
                    for item in deletions:
                        CSSS.update(str(i), -1)
                    end = time.time()
                    CSSS_times = 1.0*(end-start)/(len(insertions)+len(deletions))

                    sum_ss_avg_updatetime += SS_times
                    sum_lazy_ss_avg_updatetime += LAZY_SS_times
                    sum_cm_avg_updatetime += CM_times
                    sum_cs_avg_updatetime += CS_times
                    sum_csss_avg_updatetime += CSSS_times

                ss_avg_updatetime.append(sum_ss_avg_updatetime/ runs)
                lazy_ss_avg_updatetime.append(sum_lazy_ss_avg_updatetime/ runs)
                cm_avg_updatetime.append(sum_cm_avg_updatetime/ runs)
                cs_avg_updatetime.append(sum_cs_avg_updatetime/ runs)
                csss_avg_updatetime.append(sum_csss_avg_updatetime/runs)

            ss_updatetime[rate] = ss_avg_updatetime
            lazy_ss_updatetime[rate] = lazy_ss_avg_updatetime
            cm_updatetime[rate] = cm_avg_updatetime
            cs_updatetime[rate] = cs_avg_updatetime
            csss_updatetime[rate] = csss_avg_updatetime

        fig = plt.figure()
        if stream_type == "zipf":
            if shuffled:
                plt.title("Zipf("+str(a)+") Update Time", fontsize=20)

        plt.xlabel('Stream Length', fontsize=19)
        plt.ylabel('Time Per Item (sec)', fontsize=19)

        plt.rc('xtick',labelsize=15)
        plt.rc('ytick',labelsize=15)

        plt.yscale('log', basey=10)
        plt.xscale('log', basex=3)
        for i in range(len(rates)):
            plt.plot(stream_length, ss_updatetime[rates[i]], markers[rates[i]][0], label='SpaceSaving\u00B1')
            plt.plot(stream_length, lazy_ss_updatetime[rates[i]], markers[rates[i]][2], label='Lazy')
            plt.plot(stream_length, csss_updatetime[rates[i]], markers[rates[i]][1],label='CSSS')

            plt.plot(stream_length, cm_updatetime[rates[i]], Turnstile_model_maker[0] ,label='Count-Min')
            plt.plot(stream_length, cs_updatetime[rates[i]], Turnstile_model_maker[1],label='Count Median')
        plt.legend(prop={'size': 12})
        print('ss', ss_updatetime)
        print('lss', lazy_ss_updatetime)
        print('cm', cm_updatetime)
        print('cs', cs_updatetime)
        print('csss', csss_updatetime)

```

```python
    update_time("zipf", True, [])
```

```python

```

```python
def different_delete_ratio_mse(stream_type, counters, shuffled, arr, skew=1.0, u = 2**16):

        stream_length = [10**6]

        ss_mse_errors = {}
        lazy_mse_errors = {}
        csss_mse_errors = {}
        cm_mse_errors = {}
        cs_mse_errors = {}

        Turnstile_model_maker = ['^:','^-.']
        markers = {stream_length[0]:['bo-','bo--', 'bo:', '^:','^-.'], 0.5:['kv-','kv--','kv:', '*:', '*-.'], 0.25:['rP-','rP--', 'rP:']}

        runs = 5
        universe = u
        a = skew
        rates = [0.25, 0.5, 0.75, 0.9, (1-1.0/16)]
        alphas = [4/3, 2, 4, 10, 16]

        counters = counters

        for j in range(len(stream_length)):
            size = stream_length[j]

            ss_avg_mse_error = []
            lazy_ss_avg_mse_error  = []
            csss_avg_mse_error = []
            cm_avg_mse_error = []
            cs_avg_mse_error = []

            for i in range(len(rates)):
                rate = rates[i]
                alpha = alphas[i]

                sum_ss_mse_error = 0
                sum_lazy_ss_mse_error = 0
                sum_csss_mse_error = 0
                sum_cm_mse_error = 0
                sum_cs_mse_error = 0

                first_run = True

                for run in range(runs):
                    SS = SpaceSaving(counters)
                    LAZY_SS = SpaceSaving(counters, True)
                    CM = CountMinSketch(counters/16.0, 16) # cols, rows
                    CS = CSSS_CountSketch(16, counters/16.0)
                    csssK = counters/(math.log2(alpha)) #
                    CSSS = CSSS_sketch(1.0/csssK, universe, csssK, alpha)

                    insertions = []
                    deletions = []

                    if stream_type == "zipf":
                        range_x = np.arange(1,universe)
                        weights = range_x ** (-a)
                        weights /= weights.sum()
                        bounded_zipf = stats.rv_discrete(name='bounded_zipf', values=(range_x, weights))

                        insert_size = int(size/(1+rate))
                        insertions = bounded_zipf.rvs(size=insert_size)

                        if shuffled:
                            deletions = random.sample(list(insertions), int(rate*insert_size))

                    true_result = {}
                    for item in insertions:
                        SS.update(str(item), 1)
                        LAZY_SS.update(str(item), 1)
                        CM.add(str(item), 1)
                        CS.add(str(item), 1)
                        CSSS.update(str(item), 1)
                        true_result[str(item)] = true_result.get(str(item), 0) + 1

                    for item in deletions:
                        SS.update(str(item), -1)
                        LAZY_SS.update(str(item), -1)
                        CM.add(str(item), -1)
                        CS.add(str(item), -1)
                        CSSS.update(str(item), -1)
                        true_result[str(item)] -= 1
                        if true_result[str(item)] == 0:
                            del true_result[str(item)]

                    csss_sum_mse_error = 0
                    ss_sum_mse_error = 0
                    lazy_ss_sum_mse_error = 0
                    cm_sum_mse_error = 0
                    cs_sum_mse_error = 0

                    total_items = 0
                    for item, freq in true_result.items():
                        total_items+=1

                        csss_estimate = CSSS.query(item)
                        csss_sum_mse_error += (freq - csss_estimate)**2

                        ss_estimate = SS.query(item)
                        ss_sum_mse_error += (freq - ss_estimate)**2

                        lazy_ss_estimate = LAZY_SS.query(item)
                        lazy_ss_sum_mse_error += (freq - lazy_ss_estimate)**2

                        cm_estimate = CM.query(item)
                        cm_sum_mse_error += (freq - cm_estimate)**2

                        cs_estimate = CS.query(item)
                        cs_sum_mse_error += (freq - cs_estimate)**2

                    sum_ss_mse_error += (1.0 * ss_sum_mse_error / len(true_result.items()) )
                    sum_lazy_ss_mse_error +=  (1.0 * lazy_ss_sum_mse_error / len(true_result.items()) )
                    sum_csss_mse_error += (1.0 * csss_sum_mse_error/ len(true_result.items()))
                    sum_cm_mse_error += (1.0 * cm_sum_mse_error/ len(true_result.items()))
                    sum_cs_mse_error += (1.0 * cs_sum_mse_error/ len(true_result.items()))

                ss_avg_mse_error.append(1.0 * sum_ss_mse_error/ runs)
                lazy_ss_avg_mse_error.append(1.0 * sum_lazy_ss_mse_error/ runs)
                cm_avg_mse_error.append(1.0 * sum_cm_mse_error / runs)
                cs_avg_mse_error.append(1.0 * sum_cs_mse_error / runs)
                csss_avg_mse_error.append(1.0 * sum_csss_mse_error / runs)

            ss_mse_errors[size] = ss_avg_mse_error
            lazy_mse_errors[size] = lazy_ss_avg_mse_error
            cm_mse_errors[size] = cm_avg_mse_error
            cs_mse_errors[size] = cs_avg_mse_error
            csss_mse_errors[size] = csss_avg_mse_error

        fig = plt.figure()
        if stream_type == "zipf":
            if shuffled:
                plt.title("Zipf("+str(a)+")", fontsize=20)

        plt.xlabel('Delete:Insert Ratio', fontsize=19)
        plt.ylabel('MSE', fontsize=19)

        plt.rc('xtick',labelsize=15)
        plt.rc('ytick',labelsize=15)

        plt.yscale('log', basey=10)
        plt.xticks(rates)
        #plt.autofmt_xdate()
        plt.gcf().autofmt_xdate()
        print('ss', ss_mse_errors)
        print('lss', lazy_mse_errors)
        print('cm', cm_mse_errors)
        print('cs', cs_mse_errors)
        print('csss', csss_mse_errors)
        for s in stream_length:
            plt.plot(rates, ss_mse_errors[s], markers[0.5][0], label='SpaceSaving\u00B1')
            plt.plot(rates, lazy_mse_errors[s], markers[0.5][2], label='Lazy')
            plt.plot(rates, csss_mse_errors[s], markers[size][1],label='CSSS')

            plt.plot(rates, cm_mse_errors[s], Turnstile_model_maker[0] ,label='Count-Min')
            plt.plot(rates, cs_mse_errors[s], Turnstile_model_maker[1],label='Count Median')
        plt.legend(prop={'size': 12})
```

```python

```

```python
different_delete_ratio_mse("zipf", 1000, True, [])
```

```python

```