コード例 #1
0
class GD_PQ_Bucketing(object):
    def __init__(self, bucket_bounds, name = None):
        if name:
            self.name = name
        else:
            self.name = self.__class__.__name__

        self.bucket_bounds = bucket_bounds
        self.bucket_costs = [float(a + b)/2 for a,b in zip([0] + bucket_bounds[:-1], bucket_bounds)]
        self.bucket_frac = [(0,0) for _ in bucket_bounds]
        self.bucket_evictions = [0 for _ in self.bucket_bounds]
        self.bucket_misses = [0 for _ in self.bucket_bounds]

        self.nodes = SortedCollection(key=attrgetter("priority"))
        self.H = 0
        self.time = 0
        
        self.error_numer = 0
        self.error_denom = 1

    def update_bucket(self, bucket_ix, new_cost):
        # average of current contents
        bucket_frac = self.bucket_frac[bucket_ix]
        new_frac = (bucket_frac[0] + new_cost, bucket_frac[1] + 1)

        self.bucket_frac[bucket_ix] = new_frac
        self.bucket_costs[bucket_ix] = float(new_frac[0])/new_frac[1]

        return self.bucket_costs[bucket_ix]

    def touch(self, node):
        self.nodes.remove(node)
        
        b_cost = self.bucket_costs[node.bucket]

        node.cost = b_cost
        node.priority = (self.H + b_cost, self.time)

        self.time += 1

        self.error_numer += abs(b_cost - node.real_c)
        self.error_denom += 1

        self.nodes.insert(node)

    def add_node(self, value, cost):
        bucket_ix = bisect_left(self.bucket_bounds, cost)
        b_cost = self.update_bucket(bucket_ix, cost)

        new_node = PQNode(value, b_cost)
        new_node.priority = (self.H + b_cost, self.time)
        new_node.real_c = cost
        new_node.bucket = bucket_ix

        self.bucket_misses[bucket_ix] += cost

        self.time += 1
        self.nodes.insert(new_node)

        self.error_numer += abs(b_cost - cost)
        self.error_denom += 1

        return new_node

    def evict_node(self):
        to_evict = self.nodes[0]

        del self.nodes[0]
        self.H = to_evict.cost

        # update the bucket average
        bucket_ix = to_evict.bucket
        bucket_frac = self.bucket_frac[bucket_ix]
        new_frac = (bucket_frac[0] - to_evict.real_c, bucket_frac[1] - 1)
        self.bucket_frac[bucket_ix] = new_frac
        if(new_frac[1] == 0):
            self.bucket_costs[bucket_ix] = 0
        else:
            self.bucket_costs[bucket_ix] = float(new_frac[0])/new_frac[1]

        self.bucket_evictions[to_evict.bucket] += to_evict.real_c

        return to_evict
コード例 #2
0
class GD_PQ_Bucketing_Old(object):
    def __init__(self, bucket_bounds, name = None, **kwargs):
        if name:
            self.name = name
        else:
            self.name = self.__class__.__name__

        self.bucket_bounds = bucket_bounds
        self.bucket_costs = [float(a + b)/2 for a,b in zip([0] + bucket_bounds[:-1], bucket_bounds)]
        self.bucket_frac = [(0,0) for _ in bucket_bounds]
        self.nodes = SortedCollection(key=self.objective_f)
        self.H = 0
        self.time = 0

    def objective_f(self, node):
        node_L, bucket_ix = node.cost
        return (self.bucket_costs[bucket_ix] + node_L, node.priority) # such an absurd objf.

    def update_ordering(self):
#        self.nodes.key = self.objective_f # will resort the collection.
        pass

    def update_bucket(self, bucket_ix, new_cost):
        # default:: just set bucket to newest.
#        self.bucket_costs[bucket_ix] = float(new_cost)

        # do a moving window?
        bucket_frac = self.bucket_frac[bucket_ix]
        new_frac = (bucket_frac[0] + new_cost, bucket_frac[1] + 1)

        self.bucket_frac[bucket_ix] = new_frac
        self.bucket_costs[bucket_ix] = float(new_frac[0])/new_frac[1]

        return self.bucket_costs[bucket_ix]

    def touch(self, node):
        self.nodes.remove(node)

        node.cost = (self.H, node.cost[1])
        node.priority = self.time

        self.time += 1

        self.nodes.insert(node)

    def add_node(self, value, cost):
        bucket_ix = bisect_left(self.bucket_bounds, cost)
        self.update_bucket(bucket_ix, cost)
        self.update_ordering()

        new_node = PQNode(value, (self.H, bucket_ix))
        new_node.priority = self.time
        new_node.real_c = cost

        self.time += 1
        self.nodes.insert(new_node)

        return new_node

    def evict_node(self):
        to_evict = self.nodes[0]

        del self.nodes[0]
        self.H = self.objective_f(to_evict)[0]

        # update the bucket average
        bucket_ix = to_evict.cost[1]
        bucket_frac = self.bucket_frac[bucket_ix]
        new_frac = (bucket_frac[0] - to_evict.real_c, bucket_frac[1] - 1)
        self.bucket_frac[bucket_ix] = new_frac
        if(new_frac[1] == 0):
            self.bucket_costs[bucket_ix] = 0
        else:
            self.bucket_costs[bucket_ix] = float(new_frac[0])/new_frac[1]
        self.update_ordering()

        return to_evict