Ответ 1
Это немного поздно, но эта проблема беспокоила меня в течение некоторого времени. я был уверен, что его можно решить с помощью смешанных методов целочисленного/линейного программирования и попросил помощи в этом вопросе: Идентификация кластеров столбцов и строк с линейным программированием
Однако, получив ответ, я понял, что ваша проблема в по крайней мере, насколько я понимаю, настолько прост (когда он создан как программа ограничения) что вы можете решить его тривиально с помощью простой программы (которую вы уже знал). Другими словами, программирование ограничений было бы крутым способом решения это, но, по крайней мере, с подходом, который я нашел, даст вам тот же ответ как нечто гораздо более простое.
Я объясню ниже свои рассуждения, как я буду реализовывать его с ограничением пакет решений, а затем дать окончательный, тривиальный алгоритм.
Решение смешанного целочисленного программирования
Самая важная деталь - разница между горизонтальной и вертикальной групп. Насколько я могу видеть, все, что выравнивается вертикально, может быть в той же группы. Но горизонтальные группы разные - компоненты должны быть близки вместе.
Самая трудная часть решения проблемы с ограничениями - это найти
способ описать пределы таким образом, чтобы решатель мог понять. Я не буду
входите в подробности здесь, но решатели разочаровывают. К счастью, я
подумайте, что есть способ сделать это здесь, и рассмотреть горизонтальные
соседи: если в строке есть N точек, то мы имеем N-1
множества
соседей (например, с 4 точками A B C и D есть три пары
AB, BC и CD).
Для каждой пары мы можем дать оценку, которая представляет собой количество пробелов между ними
(S_i
), масштабированный некоторым фактором K
, и флаг (F_i
), который равен 0 или 1. Если
пара находятся в одной и той же горизонтальной группе, тогда мы устанавливаем флаг в 1, иначе
равна нулю.
Очень важно видеть, что множество флагов для всех пар полностью определяет решение. Мы можем запускать любую строку, помещая пары с флагом 1 в одной и той же горизонтальной группе и начиная новую горизонтальную группу время флага равно 0. Тогда мы можем взять все горизонтальные группы размером 1 и преобразовать их в вертикальные группы: любая точка, которая не находится в горизонтальной группе должен быть в вертикальной группе (даже если это вертикальная группа только одного).
Итак, все, что нам нужно сейчас, - это способ выразить оптимальное решение в терминах флаги. Я предлагаю свести к минимуму:
sum(1 - F_i) + sum(K * S_i * F_i)
У этого есть два члена. Первая - это сумма "один минус флаг" для каждого
пара. Флаг равен 1, когда точки находятся в одной и той же горизонтальной группе и 0
в противном случае. Таким образом, минимизация этого значения совпадает с тем, что мы хотим, чтобы
возможно, несколько горизонтальных групп. Если бы это было единственное ограничение, то мы
может установить его в ноль, сделав все F_i
1, сделав все пары в строке
членов той же группы.
Но второй термин не позволяет нам выбирать такое экстремальное решение. Это
наказывает группы с пробелами. Если пара находится в одной группе, но
разделенных пробелами S_i
, тогда у нас есть "штраф" K * S_i
.
Итак, у нас есть компромисс. Мы хотим горизонтальные группы, но нам не нужны пробелы.
Окончательное решение будет зависеть от K
- если оно велико, то мы не будем включать
любые пробелы в горизонтальных группах. Но по мере того, как оно уменьшается, мы начнем
поэтому, пока он не будет очень маленьким (стремится к нулю), мы помещаем все подряд
в одной группе.
Чтобы использовать это, вы можете выбрать K
, вычислить S_i
и ввести выражение выше в систему ограничений. Затем система выберет F_i
, чтобы свести к минимуму выражение. Наконец, вы преобразуете F_i
в шаблон групп, просматривая каждую строку, как описано выше, и затем группируйте одиночные точки по вертикали.
Аналитическое решение
ОК, круто. На этом этапе у нас есть способ выразить проблему, которую мы можем дать к механизму ограничения.
Но это тривиально решать! Нам не нужен механизм принуждения stinkin 'to to решим это - мы можем просто взглянуть на выражение:
sum(1 - F_i) + sum(K * S_i * F_i)
Две суммы находятся по тем же парам, поэтому мы можем переместить все в сумму:
sum(1 - F_i + K * S_i * F_i)
sum(1 + F_i * (K * S_i - 1))
И затем извлеките константу (N
здесь общее количество пар):
N + sum(F_i * (K * S_i - 1))
Теперь обратите внимание, что каждый член в сумме является независимым (и аддитивным). Поэтому для каждого мы хотим минимальное значение. У нас есть два варианта:
-
если
F_i
равно 0, тогда весь член равен 0. -
в противном случае
F_i
равно 1, а членK * S_i - 1
.
Таким образом, лучший выбор зависит от того, больше ли K * S_i
1. Если K *
S_i
больше 1, то наименьшее значение этого слова равно 0, а F_i
должно быть 0. В противном случае второй выбор выше отрицателен, а F_i
должен
быть одним.
Тривиальный алгоритм
Что это значит? Это означает, что для каждой пары мы можем просто взглянуть на
количество пробелов, S_i
. Если это больше, чем 1 / K
, то две точки
должны быть в отдельных группах. В противном случае они должны находиться в одной группе.
Итак, все эти причудливые математики и оптимизация и ограничения и мужество сводится к: насколько далеко друг от друга находятся две точки в соседних парах? Если они ближе, чем некоторые отсечки, помещают их в одну и ту же горизонтальную группу. В противном случае поместите их в отдельные группы.
Итак, вот, наконец, ваш алгоритм:
choose some cut-off value, X
place each point in its own, singleton, horizontal group
for each row with more than one point:
for each neighbouring pair in the row:
if the space between the pair is less than X:
join into a single horizontal group
for each column:
join any remaining singleton groups into a single vertical group
Заключение
-
Вы можете использовать методы программирования ограничений для решения этой проблемы, но такие методы ограничены решениями, которые описывают систему в "правильном" (обычно, линейном) способе.
-
Самый простой такой подход, который я могу найти, эквивалентен тривиальному, прямому алгоритм, который делит точки в строке на горизонтальные группы в зависимости от количество пробелов между ними.
-
Все это зависит от целой груды предположений о том, что вы хотели, что, конечно, быть чрезмерно упрощенными, или просто неправильно.