Моей первой мыслью было линейное программирование с симплексным алгоритмом, но я думаю, что это либо неправильно, либо, по крайней мере, неполно. По сути, большинство, если не все ваши правила являются линейными правилами "это равно", где линейное программирование имеет дело с правилами "это меньше, чем то" (или <= или что-то еще). </p>
Исправление может быть объединением. То есть выражайте свои правила WRT как можно меньшим количеством переменных. Если у вас есть правило f (a) = g (b), вы можете эффективно исключить b, определив b = g '(f (a)) и подставив его везде, где найдете b. Так как на самом деле замена неэффективна, вы можете просто отметить связь между a и b.
При незначительных осложнениях основной подход - поиск союза. В случае точного равенства вы удалили бы b, добавив ссылку из b в a. Когда вы «находите» b, вы вместо этого идентифицируете a (или то, с чем оно было связано). Таким образом, в любое время вы можете эффективно преобразовать любое правило в форму, в которой используются только неисчезающие переменные. Сложность в этом случае - вам нужно следить за вещами в стиле g '(f (a)), когда вы переходите по ссылкам. Поскольку все это линейно, это не должно быть такой большой проблемой, но и не тривиальным.
Возможно, вам понадобится иметь возможность откатить объединение - запишите ссылки, которые вы установили в стеке, чтобы вы могли снова обнулить их в правильном порядке при размотке стека.
Я не уверен, есть ли у вас какие-либо относительные условия (меньше или меньше), но если это так, как только вы удалите столько переменных, сколько возможно, вам все равно потребуется некоторое линейное программирование. Если у вас есть две оставшиеся переменные, это концептуально просто. Для каждого линейного условия на этих двух переменных нарисуйте линию на двухмерном графике так, чтобы одна сторона линии представляла действительную область. Условия традиционно «нормализуются», поэтому действительная сторона всегда включает происхождение. Исходя из точек пересечения, отрезки, ближайшие к началу координат, образуют выпуклый многоугольник. Оптимальное решение находится на одном из углов и оценивается с использованием линейного правила оценки (то, что вы оптимизируете), которое в вашем случае будет определено, чтобы придать «лучшую» форму, где есть некоторая неопределенность или некоторый конфликт приоритетов ваши правила - например Вы не можете протолкнуть точку через линию, поэтому в определенных точках все блокируется.
Если у вас осталось более двух переменных, вам нужен многомерный эквивалент выпуклого многоугольника - и это называется симплекс. Практическая реализация симплексного алгоритма включает в себя матрицы.
Это уже упрощено до такой степени, что, возможно, это неправильно в некоторых деталях, и это, насколько я могу объяснить. IIRC вы можете получить хорошие описания этих техник компонентов в Седжвике, хотя Википедия может быть столь же хороша в наши дни.
Симплексные решатели иногда используются для макетов окон - я думаю, что wxWidgets использует один для изменения размеров элементов управления в окне, например. Унификация является определяющей особенностью логического программирования (Пролог и т. Д.), Но лежащие в основе принципы поиска объединения достаточно просты. Ключевой трюк состоит в том, чтобы выяснить, как преобразовать 2D-фигуру в набор правил, выражающих, как она будет меняться, и понять, как представлять и управлять этими правилами, особенно в матричной форме.