Монте-Карло
Как альтернатива чтение файла строка за строкой *
(* используйте метод Дэвида Робинсона, чтобы прочитать файл gzip как стандартный файл):
Если все строки примерно одинакового размера, вы можете перейти к произвольной позиции в файле, возвращаться символ за символом, пока не дойдете до новой строки и не прочитаете всю строку с этой точки. Если линии имеют одинаковый размер, этот метод является точным.
Если, однако, строки имеют разный размер, но вы знаете, что распределение имеет строку с длиной x
- вы можете сделать метод, как описано выше, но отклонить избыточный x
' s с вероятностью P(x)
такой, что вероятность захвата случайной строки в файле постоянна.
Пример:
Для простоты предположим, что у вас есть 5-строчный файл длиной X={2,3,5,5,5}
. Выбрав случайную точку в файле, вы получаете 10% (2 / (2 + 3 + 5 + 5 + 5)) шанс получить x1
, 15% получить x2
, 50% шанс x3
. То, что вы хотите, это 20%/20%/60%
вероятность соответственно. Соответствующие веса у нас W=(3/2, 1, 6/5)
, это такие числа, что x1*w1 = 20%
, x2*w2 = 20%
, x3*w3=60%
. Нормализующий коэффициент представляет собой сумму этих весов Z = w1+w2+w3 = 37/10
. Отсюда мы знаем вероятность для каждой из линий:
P(w1) = w1/Z = 30/68
P(w2) = w2/Z = 20/68
P(w3) = w3/Z = 18/68
Обратите внимание, что P(w1)+P(w2)+3*P(w3)=1
, как и должно быть.
Для вашего алгоритма выберите случайную точку в файле. Если соответствующая строка имеет длину 2, выберите случайное число между q=[0,1]
. Если q>(30/68)
отклоните это место и попробуйте снова. Если меньше, остановитесь и верните эту строку.
Когда вы знаете X(w)
?
Я признаю, что точное распределение длин строк может показаться ограничительным, однако существует много процедурно сгенерированных файлов (файлов журналов, считывания аппаратных данных и т. Д.), Где распределение точно известно. Кроме того, если распределение известно только приблизительно, мы можем использовать метод, описанный выше, для определения критерия отклонения выборки в качестве наилучшего предположения и оттуда.
Монте-Карло?
Возможно, это не лучший метод (кто может конкурировать с Кнутом?), Но он может дать некоторое представление о решении проблемы совершенно другим способом. Для тех, кто незнаком, вышеописанный метод - это выборка по важности, метод Монте-Карло .
Как искать в файле gzip?
В соответствии с запросом OP здесь приведен учебник по seek
через объект файла Python.
import gzip, random
# Helper function to create some test data
def line(char,n):
return ''.join([("%s"%char)*n,"\n"])
# Create the test data as in the example
filename = "test.zip"
FOUT = gzip.open(filename,'wb')
FOUT.write(line('a',2))
FOUT.write(line('b',3))
FOUT.write(line('c',5))
FOUT.write(line('d',5))
FOUT.write(line('e',5))
FOUT.close()
# Since we know the distribution, we know the length
length = 2+3+3*5+5 # 5 newlines
# Print 7 random points in the file
FIN = gzip.open(filename,'rb')
for n in xrange(7):
FIN.seek(random.randrange(length),0)
print "Position %3i, char: %s" %(FIN.tell(), [FIN.read(1)])
Это имеет выход для образца запуска как:
Position 8, char: ['c']
Position 23, char: ['e']
Position 15, char: ['d']
Position 10, char: ['c']
Position 4, char: ['b']
Position 16, char: ['d']
Position 2, char: ['\n']