Изучение алгоритма поиска минимальной цепочки, содержащей определенные элементы

Извините, я не могу придумать название алгоритма или задачи для следующего алгоритма. Я изложу проблему, а затем то, что я пробовал, и, возможно, кто-то может указать мне правильное направление.

Представьте, что у вас есть сумка с предметами (неупорядоченными, дубликаты разрешены). На практике сумка может содержать от 2 до 20 предметов, если это поможет.

Цель состоит в том, чтобы найти цепочку минимальной длины (нумерованный список ссылок, если у нас разные представления о цепочке), которая содержит все предметы в мешке в любом порядке.

Цепочка состоит из начального жетона (его нет в сумке), за которым следует любое количество предметов, за которым следует конечный жетон (тоже не в сумке).

Цепочка формируется путем объединения n-кортежей (порядок важен), и в качестве дополнительной послабления допустим, что значение n одинаково для всех кортежей. На практике я работаю с n = 3. Цепочки могут быть «смешанными», а не конкатенированными, если они имеют перекрывающиеся элементы. Например, рассмотрим (a,b,c) и (c,d,e). Могут быть соединены как (a,b,c,d,e). Точно так же (a,b,c) и (b,c,d) могут быть соединены как (a,b,c,d). Некоторые кортежи могут иметь начальный токен в первой позиции, а некоторые токены имеют конечный токен в последней позиции, что, конечно, позволяет найти решение проблемы.

Так что мне кажется, что точное решение задачи вообще неразрешимо. Для получения «хорошего» решения проблемы потребуется какой-то алгоритм оптимизации. «Хорошие» решения, с которыми я могу жить.

Я начал с жадного подхода, когда при первом проходе вы находите кортеж, содержащий наибольшее количество элементов в мешке, произвольно разрывая связи. Создайте структуру данных, содержащую построенную нами цепочку, и вставьте выбранный кортеж в эту структуру данных. Разделите проблему на 2 подзадачи: сторону начального маркера и сторону конечного маркера. До тех пор, пока первый токен структуры данных подзадачи 1 не станет начальным токеном, а последний токен подзадачи 2 не будет конечным токеном, наращивайте цепочку так, чтобы мы пытались как можно скорее найти условие остановки (начальный или конечный токен в зависимости от над подзадачей), одновременно пытаясь исчерпать содержимое мешка как можно скорее. Это может быть нехорошо, потому что каждая подзадача должна сообщаться друг с другом относительно того, сколько предметов осталось в сумке, которые необходимо включить.

Кто-нибудь видел эту проблему где-нибудь? Любые мысли о том, как улучшить (или заставить работать правильно) этот алгоритм? Это реальная проблема, которую я решаю, которая является умной частью гораздо более крупной системы, а не игрушечной проблемой или проблемой домашнего задания.

ИЗМЕНИТЬ

Извините все, что я был далеко от компьютера сегодня. Я постараюсь опубликовать пример решения, которое не слишком тривиально, но и не слишком сложно, чтобы его увидеть.

Данный:

  1. Bag = {A, B, C, D} (я делаю набор для примера, но каждый элемент может появляться более одного раза)
  2. / = Start Token
  3. \ = End Token
  4. 3-Tuples (тройки): я обозначаю их буквами g для простоты именования. Строчные буквы не имеют реальной функции в задаче.

    (/,A, E) a
    (/,C, D) b
    (/,G, H) c
    (D,B, A) d
    (C,G, H) e
    (B,A, \) f
    (G,H, \) g
    

Решение: если соединить вместе b, d и f, получится (/,C,D,B,A,\).
Это кратчайшая возможная цепочка, содержащая все элементы в мешке, длина которой равна 6, если считать начальный и конечный маркеры. В общем случае кратчайший путь имеет длину |BAG| + 2, если он действительно существует. Я надеюсь, что моя формулировка проблемы теперь имеет больше смысла.


person demongolem    schedule 21.10.2012    source источник
comment
Извините, я не понял проблемы. Можете ли вы добавить простой тестовый пример и его оптимальное решение?   -  person amit    schedule 21.10.2012
comment
ИМХО разрешенные дубликаты это ерунда. для пары близнецов 1) если у них одинаковые входящие/исходящие пути, то один из них избыточен. 2) если у них разные пути, то узлы не могут быть идентичными. И кроме того: если они дубликаты, узлы (и их пути) должны быть объединены/объединены.   -  person wildplasser    schedule 21.10.2012
comment
Если бы у меня был ящик, решающий вашу проблему, мог бы я использовать его для решения en.wikipedia.org/wiki/ Гамильтониан_путь?   -  person mcdowella    schedule 21.10.2012
comment
После перечитывания OQ несколько раз действительно кажется, что ОП хочет своего рода гамильтонов путь. Но: посетить узел дважды не возбраняется, так что это становится своего рода проблемой китайского почтальона.   -  person wildplasser    schedule 21.10.2012


Ответы (1)


Поскольку у вас есть только до 20 элементов, я думаю, вы можете вычислить точное решение за разумное время (например, меньше минуты).

Одним из подходов было бы использование динамического программирования, в котором состояние задается следующим образом:

A) a 20 bit number m (which will represent which items have been visited so far)
B) a number b in the range 1..20 
C) a number c in the range 1..20

Это состояние будет соответствовать цепочке вида Start,?,?,?,...,?,b,c. то есть b и c - два самых последних элемента.

Число m — это битовое поле, которое представляет, какие другие элементы были посещены в цепочке. Другими словами, бит i числа m равен 1 тогда и только тогда, когда цепочка включает i-й элемент в мешке.

Алгоритм поиска кратчайшей цепочки будет таким:

  1. Пусть S = множество состояний, состоящее из всех кортежей, имеющих начальный токен. (Все эти состояния будут иметь одинаковую длину цепочки 2)
  2. Для каждой длины цепочки y от 3 и выше пройдите все состояния в S и попробуйте расширить состояние до длины y, используя соответствующий кортеж. Если это возможно, добавьте расширенное состояние в набор S.
  3. Разрешить добавлять кортежи с конечным токеном только в том случае, если битовое поле m будет иметь все установленные биты.

Если вам когда-нибудь удастся добавить кортеж, содержащий конечное состояние, значит, вы нашли кратчайшую цепочку, содержащую все элементы.

Для N предметов в сумке существует примерно 2 ^ N.N.N состояний, которые должны быть почти управляемыми.

person Peter de Rivaz    schedule 21.10.2012
comment
В глубине души я подумал, что, поскольку у меня в сумке максимум предметов, DP может быть подходящим вариантом. Я должен подумать об этом и вернуться к вам. Я уверен, что моя первоначальная проблема заключалась в том, что я смотрел на проблему под неправильным углом. - person demongolem; 22.10.2012
comment
Собираюсь дать вам голос. Я смог успешно решить приведенный выше пример с общей сутью алгоритма. Все еще могут быть некоторые крайние случаи, с которыми нужно иметь дело, например, что произойдет, если мы никогда не сможем достичь конечного токена, но они незначительны. Я думаю, что это будет масштабироваться для всех случаев, я должен продолжить тестирование коллекции Triples, которые мне скормили, просто чтобы убедиться. - person demongolem; 22.10.2012
comment
Я думаю, что другой способ взглянуть на этот подход заключается в том, что он выполняет поиск в ширину от начальной точки до конечной точки, а стоимость - это общее количество посещенных узлов. Поэтому вы можете рассмотреть вариант en.wikipedia.org/wiki/Bidirectional_search или A* - person mcdowella; 22.10.2012
comment
На самом деле, думая об этом, я думаю, что двунаправленный поиск просто разбивает узлы на две половины и посещает все обе половины, в то время как A * с очевидной эвристикой — это просто более дорогая версия поиска в ширину, так что поцарапайте это — извините. - person mcdowella; 23.10.2012