алгоритм размещения предметов - PullRequest
1 голос
/ 27 июня 2011

Так что я нахожусь в поиске алгоритма для определения местоположения предметов, однако мне трудно формализовать мое измерение "добротности" местоположения.

Вот проблема: у меня есть набориз k предметов, которые я хочу разместить вдоль линии.Каждый элемент имеет ширину, и никакие два элемента не могут перекрываться.Каждый элемент также имеет соответствующий интервал - все интервалы являются фиксированными, непересекающимися и образуют разбиение некоторого сегмента линии.

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

Итак, в качестве компромисса я готов сдвинуть элементы частично (или полностью) вне их интервала.Однако я не хочу менять порядок элементов (они должны оставаться в порядке их интервалов).

Существует ли хороший алгоритм для нахождения «наилучшего» размещения элементов вдольлиния в соответствии с моей (слабо определенной) мерой?

Ответы [ 2 ]

1 голос
/ 28 июня 2011

Ну, вот решение для, возможно, самого простого способа, которым я мог бы интерпретировать ваш вопрос:

Предположим, что для каждого элемента мы рассматриваем две возможности:

  1. Мы помещаем его в его предполагаемом месте (то есть в центр интервала)

  2. Мы не

Тогда мы можем переформулировать этоЗадача в виде следующей функции: Найти максимальный набор элементов, которые можно поместить в центр их интервала без наложения.

Это похоже на то, что должно иметь жадное решение, но я должен признаться, что лучшийЯ смог сделать довольно наивный алгоритм динамического программирования.Вот как я сформулировал повторение:

Предположим, что мы рассматриваем n-й элемент (начиная с левого), и что мы хотим назначить его таким образом, чтобы левый край этого элемента не проходил наиболее правоеперед всеми предыдущими пунктами.Тогда должно быть верно, что оптимальное присвоение удовлетворяет:

best_align(n, right) = 
     if center[n]-radius[n] > right[n]:
          max(best_align(n+1, right+radii[n], 1+best_align(n+1,center[n]+radius[n])
     else:
          best_align(n+1, right+radius[n])

Это имеет очевидное решение DP, которое я кодировал (в python).Вот результат:

#Assumes that the items are sorted left-to-right by their centers
def best_align(radii, centers):

    assignments = { (radii[0]+centers[0]):[0], (-100000):[] }

    for i in range(1, len(radii)):

        nc = centers[i] + radii[i]
        nassignments = { nc : [i] }

        for right, assigned in assignments.items():

            #Handle case where object is not inserted
            nr = right+radii[i]
            if not nr in nassignments or len(assigned) > len(nassignments[nr]):
                nassignments[nr] = assigned

            #Handle inclusion case
            if right <= centers[i]-radii[i] and len(assigned) >= len(nassignments[nc]):
                nassignments[nc] = assigned + [i]


        assignments = nassignments

    return max([ (len(l), l) for l in assignments.values() ])[1]

Переменные радиусы - это радиусы различных предметов, а центры - это целевые позиции назначения.Алгоритм возвращает наибольшее подмножество элементов, которые могут быть размещены в желаемых позициях.Остальные предметы должны быть вычеркнуты как можно лучше.Например, вот несколько выходных данных:

In [11]: plc.best_align ([1, 5, 1], [0, 2, 3])

Out [11]: [2]

Другой пример:

В [18]: plc.best_align ([1, 10, 1, 1, 1, 1, 1], [0, 2, 4, 6, 8, 10, 12])

Out [18]: [2, 3, 4, 5, 6]

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

0 голосов
/ 27 июня 2011

Это звучит как слабо связанная система ограничений. Грубо говоря, вы можете найти «лучшее» размещение (не обязательно «лучшее», но должно быть «функциональным»), выполнив поиск в глубину в соответствующих ограничениях для ограничивающих элементов.

Позвольте мне описать. Для первого запуска постарайтесь расположить все элементы по центру их интервала. Проверьте, нет ли перекрывающихся объектов. Когда вы сталкиваетесь с перекрывающимся объектом, предварительно отодвиньте его от перекрытия; проверьте эту систему на совпадения. Повторите для всех перекрытий.

Это сохранит порядок объектов в соответствии с порядком интервалов. Должна быть возможность «оценить» значение каждой итерации по величине отклонения от интервалов, чтобы попытаться минимизировать расстояние от интервалов, если такая вещь желательна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...