У меня есть функция генератора, которая создает декартово произведение списков. Реальное приложение использует более сложные объекты, но они могут быть представлены строками:Быстрый способ генерации комбинаций с ограничениями?
import itertools
s1 = ['a', 'b']
s2 = ['c', 'd', 'e', 'f']
s3 = ['c', 'd', 'e', 'f']
s4 = ['g']
p = itertools.product(*[s1,s2,s3,s4])
names = [''.join(s) for s in p]
В этом примере, в результате 32 комбинаций символов:
names
['accg', 'acdg', 'aceg', 'acfg', 'adcg', 'addg', 'adeg', 'adfg', 'aecg',
'aedg', 'aeeg', 'aefg', 'afcg', 'afdg', 'afeg', 'affg', 'bccg', 'bcdg',
'bceg', 'bcfg', 'bdcg', 'bddg', 'bdeg', 'bdfg', 'becg', 'bedg', 'beeg',
'befg', 'bfcg', 'bfdg', 'bfeg', 'bffg']
Теперь, скажем, у меня есть некоторые ограничения так что некоторые комбинации символов являются незаконными. Например, допустим, что допустимы только строки, содержащие регулярное выражение '[ab] .c'. («А» или «б» с последующим любой буквой с последующим «с»)
После применения этих ограничений, мы остались с сокращенным набором всего 8 строк:
import re
r = re.compile('[ab].c')
filter(r.match, names)
['accg', 'adcg', 'aecg', 'afcg', 'bccg', 'bdcg', 'becg', 'bfcg']
В реальном приложении цепи длиннее, могут быть тысячи комбинаций и применение сотен ограничений достаточно интенсивно вычислительно, поэтому я заинтересован в масштабируемости.
Сейчас я просматриваю каждую комбинацию и проверяю ее достоверность. Существует ли алгоритм/структура данных, способный ускорить этот процесс?
EDIT: Может быть, это прояснит немного: В реальном приложении я собираю случайные 2D фотографии зданий из простых базовых блоков (например, столбы, сегменты крыши, окна и т.д.). Ограничения ограничивают, какие блоки (и их вращения) могут быть сгруппированы вместе, поэтому полученное случайное изображение выглядит реалистичным, а не случайным беспорядком.
Данное ограничение может содержать множество комбинаций шаблонов. Но из всех этих комбинаций многие из них недействительны, потому что другое ограничение может запретить часть его. Поэтому в моем примере одно ограничение будет содержать полное декартово произведение символов выше. И второе ограничение - это «[ab] .c»; это второе ограничение уменьшает количество допустимых комбинаций первого ограничения, которое мне нужно рассмотреть.
Поскольку эти ограничения трудно создать; Я хочу представить себе, как выглядят все комбинации блоков в каждом ограничении, но только действительные комбинации, которые передают все ограничения. Отсюда мой вопрос. Благодаря!
Вместо того, чтобы использовать итератор в списке(), просто используйте итератор в своем понимании списка (где p в настоящее время). –
Хорошая добыча! Я отредактировал этот пример. – jasonm76
Не будет 's3 = ['c']' работать так же хорошо? То есть вместо фильтрации выходных данных, как насчет ограничения входов? –