diff --git a/DAS/validator.py b/DAS/validator.py index ba33170..88ef42a 100644 --- a/DAS/validator.py +++ b/DAS/validator.py @@ -3,6 +3,7 @@ import random import collections import logging +import sys from DAS.block import * from bitarray import bitarray from bitarray.util import zeros @@ -12,6 +13,34 @@ def shuffled(lis): for index in random.sample(range(len(lis)), len(lis)): yield lis[index] +def sampleLine(line, limit): + """ sample up to 'limit' bits from a bitarray + + Since this is quite expensive, we use a number of heuristics to get it fast. + """ + if limit == sys.maxsize : + return line + else: + w = line.count(1) + if limit >= w : + return line + else: + l = len(line) + r = zeros(l) + if w < l/10 or limit > l/2 : + indices = [ i for i in range(l) if line[i] ] + sample = random.sample(indices, limit) + for i in sample: + r[i] = 1 + return r + else: + while limit: + i = random.randrange(0, l) + if line[i] and not r[i]: + r[i] = 1 + limit -= 1 + return r + class NextToSend: def __init__(self, neigh, toSend, id, dim): self.neigh = neigh @@ -177,8 +206,7 @@ class Validator: self.statsRxInSlot = 0 self.statsTxInSlot = 0 - - def nextColumnToSend(self, columnID): + def nextColumnToSend(self, columnID, limit = sys.maxsize): line = self.getColumn(columnID) if line.any(): self.logger.debug("col %d -> %s", columnID, self.columnNeighbors[columnID] , extra=self.format) @@ -187,9 +215,10 @@ class Validator: # if there is anything new to send, send it toSend = line & ~n.sent & ~n.received if (toSend).any(): + toSend = sampleLine(toSend, limit) yield NextToSend(n, toSend, columnID, 1) - def nextRowToSend(self, rowID): + def nextRowToSend(self, rowID, limit = sys.maxsize): line = self.getRow(rowID) if line.any(): self.logger.debug("row %d -> %s", rowID, self.rowNeighbors[rowID], extra=self.format) @@ -198,6 +227,7 @@ class Validator: # if there is anything new to send, send it toSend = line & ~n.sent & ~n.received if (toSend).any(): + toSend = sampleLine(toSend, limit) yield NextToSend(n, toSend, rowID, 0) def nextToSend(self):