2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Оптимизация генерации слов Линдона с условиями
Сообщение08.02.2023, 06:51 
Аватара пользователя


18/10/18
96
В ходе решения одной задачи(до сих пор в процессе), мне пришлось
создавать все слова Линдона постоянной длины на даных буквах с заданным числом повторений. То есть, делать из элементов мультимножества, на пример $\left\lbrace{a,a,a,b,b,b,c,c}\right\rbrace$ используя все буквы из него

Это обобщение. Мой кейс - поиск для бинарных слов. Я уже спрашивал на Quora и мне ответили, но там предложили не очень эффективный способ.. и работал медленно, может быть, из-за реализации на питоне.
Так же понятно, что если в случае двух букв одна повторяется довольно много - можно получить мало валидных.

Я пока работаю над ним в js. Всё уже и есть, но лучше обрубать цикл на какой-то позиции, поближе к последнему слову, что будет валидно по условию. В идеале на таком слове, которое минимально из тех, кто (лексически) больше всех валидных, скажем, имеющих 5 единиц. Не забываем, что все рассмотреные слова постоянной длины.
( Так же интересен и вариант наоборот: максимальное (с 5 единицами), меньше всех остальных (с 6-ю единицами) )

И вот, либо находить эти.. "критические" слова как-то быстро, либо какие-то части - префиксы/суфиксы проверять, для выхода с цикла генерации. Можно строить какую-то ..характеристику.
(ещё поигравшись с этими строками - возникла совсем отчаянная идея - посмотреть на это как на эволюцию 1-мерного клеточного автомата)

Вообще, это похоже на ситуацию, когда есть последовательность(необычная) и функционал от её элементов. И нам надо найти минимальный элемент со значением функционала, которое больше, чем на всех предыдущих элементах, либо... элементы последовательности, что имеют значения функционала в заданых пределах.
У меня подсчёт единичек в бинарных кодах. НО, лексический порядок слов Линдона такой, что количества единиц то возрастают, то падают...немонотонно. Надо что-то придумать, что бы не сортировать, но избавиться от вот тех прыжков/падений.

Я мог бы показать график числа единичек, но не уверен, что у ЛаТеХа есть функционал для этого. Попросите? - попробую... У меня есть датасет(массив) слов длины 11.. их 186 нашло (у 13 их 630).
Пока выложу просто отфильтрованые слова из всего массива(порядок в слове перевернул! ладно, пусть будет). Как обычно $0<1$ :

$\begin{tabular}{r|c|c}
число 1-чек & макс. & мин. больше\\
\hline
1 & 1\,0\,0\,0\,0\,0\,0\,0\,0\,0\,0 & 1\,1\,0\,0\,0\,0\,0\,0\,0\,0\,0 \\
2 & 1\,0\,0\,0\,0\,1\,0\,0\,0\,0\,0 & 1\,1\,0\,0\,0\,1\,0\,0\,0\,0\,0 \\
3 & 1\,0\,0\,1\,0\,0\,0\,1\,0\,0\,0 & 1\,1\,0\,1\,0\,0\,0\,1\,0\,0\,0 \\
4 & 1\,0\,1\,0\,0\,1\,0\,0\,1\,0\,0 & 1\,1\,1\,0\,0\,1\,0\,0\,1\,0\,0 \\
5 & 1\,0\,1\,0\,1\,0\,1\,0\,1\,0\,0 & 1\,1\,1\,0\,1\,0\,1\,0\,1\,0\,0 \\
6 & 1\,1\,0\,1\,0\,1\,0\,1\,0\,1\,0 & 1\,1\,1\,1\,0\,1\,0\,1\,0\,1\,0 \\
7 & 1\,1\,0\,1\,1\,0\,1\,1\,0\,1\,0 & 1\,1\,1\,1\,1\,0\,1\,1\,0\,1\,0 \\
8 & 1\,1\,1\,0\,1\,1\,1\,0\,1\,1\,0 & 1\,1\,1\,1\,1\,1\,1\,0\,1\,1\,0 \\
9 & 1\,1\,1\,1\,1\,0\,1\,1\,1\,1\,0 & 1\,1\,1\,1\,1\,1\,1\,1\,1\,1\,0 \\
10 & 1\,1\,1\,1\,1\,1\,1\,1\,1\,1\,0 & (\,1\,)\\
\end{tabular}$

Примечание: я немного приврал.. мне нужны не только слова Линдона, - просто слова, наименьшие в классе сорпряженности. Всего-то надо добавить слова-степени тех линдоновских, кто по размеру есть делителем указаной(макс.) длины.
Для простых длин таких слов не будет. Да и опыт генерации подсказывает, что лишняя работа при генерации будет только для нечётных "порядков" слов.. а при чётных словах последнее валидное - почти в конце. Те дополнительные, непримитвы, как правило, стоят существенно дальше по порядку. Они немного портят картину, но деваться некуда.

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение08.02.2023, 08:37 


12/07/15
3361
г. Чехов
Вы уж определитесь, какую задачу решаете. В начале одно, в конце другое. Точную постановку задачи вы дали в начале. И в итоге я запомнил лишь выделенное жирным шрифтом. Исправьтесь, пожалуйста.

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение08.02.2023, 20:31 
Аватара пользователя


18/10/18
96
Ладно. Вот вам чистая задача без моих предложений, полученых результатов, а так же без обобщений задачи.

Найдите эффективный алгоритм генерации всех слов длины \textstyle{n}$ с над упорядоченым алфавитом из двух символов, таких, что имеют постоянное число букв каждого вида, заданое как пара $\textstyle{m,k\in\mathbb{N} : m+k=n}$ $\phantom{x}$и лексически меньше всех своих сопряженных(цикл.перестановок).


Стартовое сообщение составлял около двух часов) Только в конце заметил, что мне для удобства лучше делать слова с правосторонним порядком, не $\textstyle{00001}$, а $\textstyle{10000}$. Но это вообще не влияет особо, просто что бы поняли, почему мои результаты перевёрнуты.

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение08.02.2023, 20:33 
Заслуженный участник
Аватара пользователя


15/10/08
30/12/24
12599
Nartu в сообщении #1580817 писал(а):
меньше всех своих сопряженных.
Что здесь означает "меньше"?

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение08.02.2023, 20:43 
Аватара пользователя


18/10/18
96
отредактировал теперь правильно

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение10.02.2023, 07:54 


12/07/15
3361
г. Чехов
Надо бы попробовать прикрутить динамическое программирование к задаче...
Конкатенация двух слов Линдона к чему приводит? Случайно не оказывается, что достаточно проверить четыре или два варианта (мало вариантов), чтобы найти правильную перестановку? Есть какие-то теоремы на счёт наращивания слов Линдона?

-- 10.02.2023, 10:14 --

Теорема: при сложении двух слов Линдона $A$ и $B$ получается новое слово Линдона $AB$, если $A < B$ лексикографически. Без доказательства.

Элементарное слово Линдона - это слово, начинающееся нулями и заканчивающееся единицами, например, 01; 0001; 011; 00000111.

Для перехода к динамическому программированию нужно сделать так, чтобы к
ранее найденному слову с $(m-i)$ нулями и $(n-j)$ единицами можно было малозатратно подобрать всевозможные элементарные слова с $i$ нулями и $j$ единицами, которые лексикографически больше исходного слова...

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение10.02.2023, 12:46 
Заслуженный участник
Аватара пользователя


16/07/14
9219
Цюрих
Mihaylo в сообщении #1580992 писал(а):
Теорема: при сложении двух слов Линдона $A$ и $B$ получается новое слово Линдона $AB$, если $A < B$ лексикографически.
Контрпример: $A = 01$, $B = 10$.

-- 10.02.2023, 11:05 --

А если просто сгенерировать все слова с нужным числом нулей, выкинуть периодические и из каждого взять лексикографически минимальный поворот? Мы тратим немного времени на генерацию периодических (но их мало по сравнению со всеми), и еще каждое слово генерируем по $n$ раз, но вроде разница между $C_n^k$ и $C_n^k / n$ не такая уж большая, так что это не сильно медленнее чем просто записать ответ.

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение10.02.2023, 14:42 


12/07/15
3361
г. Чехов
mihaild в сообщении #1581011 писал(а):
Контрпример: $A = 01$, $B = 10$.

$B = 10$ не является словом Линдона.

Однако 0; 00; 000; 0000 и т.д. являются словами Линдона. Но пусть в теореме будет оговорка "кроме нулевых слов Линдона".

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение10.02.2023, 14:50 
Заслуженный участник
Аватара пользователя


16/07/14
9219
Цюрих
Mihaylo в сообщении #1581016 писал(а):
$B = 10$ не является словом Линдона.
Да, пардон, бред написал. Вроде правда, кроме случая $B = 0$.
$00$ и дальше словами Линдона тоже не являются (как и все периодические; иначе не будет единственности декомпозиции).

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение10.02.2023, 20:22 


12/07/15
3361
г. Чехов
Пытаюсь реализовать свой алгоритм. Понимаю, что я как нейросеть ChatGPT, пытаюсь максимально просто и быстро воссоздать видимые циклы, но как всегда есть ошибки, то забыл какой-то цикл, то забыл проверку условия, то цикл не включает начальный или конечный элемент, то наоборот имеет лишние элементы.

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение12.02.2023, 10:02 


12/07/15
3361
г. Чехов
код: [ скачать ] [ спрятать ]
Используется синтаксис Python
import time
start_time = time.time()
m = 5
k = 15
sample_words = [('', 0, 0, 0, 0)]
final_words = []
for word in sample_words:
    for i in range(1, m - word[3] + 1):
        for j in range(1, k - word[4] + 1):
            if word[0] == '' or i < word[1] or (i == word[1] and j <= word[2]):
                new_word = word[0] + '0'*i + '1'*j
                if word[3] + i == m and word[4] + j == k:
                    final_words.append(new_word)
                else:
                    sample_words.append((new_word, i, j, word[3] + i, word[4] + j))
print("Сгенерировано %s слов Линдона за %s секунд." % (len(final_words), time.time() - start_time))
print(final_words)
 


-- 12.02.2023, 12:09 --

Это алгоритм генерации нетривиальных слов Линдона, когда $m \ne 0$, $k \ne 0$. Несложно доработать алгоритм, чтобы он умел генерировать тривиальные слова, когда $m = 0$ или $k = 0$.

-- 12.02.2023, 12:23 --

sample_word - это список слов Линдона с числом нулей и единиц меньшим, чем $m$ и $k$. Каждое слово сопровождается четырьмя вспомогательными характеристиками, для ускорения вычислений: число нулей и число единиц головного элементарного слова, число нулей и число единиц всего слова.
Головное элементарное слово - это то, что выделено жирным в примерах: 00000111010001, 010101.

-- 12.02.2023, 12:56 --

Извиняюсь, нашел в алгоритме ошибку, он генерирует не все слова Линдона. Но алгоритм корректный и очень быстрый. Просто я похоже нашел эвристику, которая позволяет не обходить дерево целиком.
Если развивать идею этого алгоритма и доводить решение до конца, то придется добавить цикл проверки слова на принадлежность к словам Линдона вместо этого простого условия:
Используется синтаксис Python
if word[0] == '' or i < word[1] or (i == word[1] and j <= word[2]):
 


Mihaylo в сообщении #1581236 писал(а):
число нулей и число единиц головного элементарного слова

И поправлюсь еще, здесь следовало написать "число нулей и число единиц последнего (хвостового) элементарного слова".

 Профиль  
                  
 
 Re: Оптимизация генерации слов Линдона с условиями
Сообщение19.02.2023, 20:22 
Аватара пользователя


18/10/18
96
Я не ожидал, что тема продолжится.. Но если тут начали составлять алгоритм для поиска слов конкретного числа "букв" нулей/единиц. То я должен напомнить, что есть алгоритм Дюваля для нахождения всех слов До заданой длины. Дюваль нашел метод создания лексически следующего слова. Он проходит в три этапа:

Выбираем какое-то слово Линдона, пусть $w=001$, бинарный алфавит.
1. Заполняем указаную максимальную длину ($\textstyle{n=5}$) буквами избранного слова (для $n$ будет $00100$);
2. Если заканчивается на любую букву кроме последней $\;-$ меняем её на следующую по алфавиту.
3. Если заканчивается на последнюю, то обрезаем ее и возвращаемся на п 2. до того момента, пока п. 2 не сработает( $n=6 : 001001 \to 00101$ )

Я работал именно с ним. И отталкивался от него. Сложность - линейная, а если работать с массивами, то может быть вообще $\operator{O}(1)$

Кажется, вот код, который я получил на Quora (на Python но я не питонист, уж извините):
Код:
def binary_lyndon_words(k, n):
    # Make the array 1..n instead of 0..n-1, for each of comparison to the original
    w = [None] + [0 for _ in range(n-k)] + [1 for _ in range(k)]
    i = n
    count = k
    while i > 0:
        for j in range(1, n-i+1):
            count -= w[i+j]
            count += w[j]
            w[i+j] = w[j]
        if i == n and count == k:
            yield w[1:] 
        i = n
        while i > 0 and w[i] == 1:
            i = i - 1
        if i > 0:
            count += 1
            w[i] = w[i] + 1

Примеры
Код:
>>> list( binary_lyndon_words( 3, 8) )
[[0, 0, 0, 0, 0, 1, 1, 1], 
[0, 0, 0, 0, 1, 0, 1, 1], 
[0, 0, 0, 0, 1, 1, 0, 1], 
[0, 0, 0, 1, 0, 0, 1, 1], 
[0, 0, 0, 1, 0, 1, 0, 1], 
[0, 0, 0, 1, 1, 0, 0, 1], 
[0, 0, 1, 0, 0, 1, 0, 1]]
>>> sum( 1 for _ in binary_lyndon_words( 6, 24))
5598
>>> sum( 1 for _ in binary_lyndon_words( 8, 32))
876525  # but takes too long

Могу дать ссылку на источник, там расписано, но... Quora любит рекламу...

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group