Минимизация f(x,y), где x и y — целые числа

Мне было интересно, есть ли у кого-нибудь предложения по минимизации функции f (x, y), где x и y - целые числа. Я исследовал множество методов минимизации и оптимизации, таких как BFGS и другие из GSL, а также вещи из Numerical Recipes. До сих пор я пытался внедрить несколько разных схем. Первый работает, выбирая направление наибольшего спуска f(x+1,y),f(x-1,y),f(x,y+1),f(x,y-1) и следуя этому направлению с минимизацией строки. Я также пробовал использовать симплексный метод спуска (Nelder-Mead). Оба метода застревают далеко от минимума. Оба они работают с более простыми функциями, такими как нахождение минимума параболоида, но я думаю, что оба, и особенно первый, предназначены для функций, где x и y являются действительными значениями (двойными). Еще одна проблема заключается в том, что мне нужно вызывать f(x,y) как можно меньше раз. Он взаимодействует с внешним оборудованием, и каждый вызов занимает пару секунд. Любые идеи для этого были бы очень признательны.

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

double Error(x,y)
{
  SetDeviceParams(x,y);
  double a = QueryParamA();
  double b = QueryParamB();
  double c = QueryParamC();
  double _fReturnable = 0;
  if(a>=A_desired)
  {
    _fReturnable+=(A_desired-a)*(A_desired-a);
  }
  if(b>=B_desired)
  {
    _fReturnable+=(B_desired-b)*(B_desired-b);
  }
  if(c>=C_desired)
  {
    _fReturnable+=(C_desired-c)*(C_desired-c);
  }
  return Math.sqrt(_fReturnable)
}

person Tim    schedule 24.07.2009    source источник
comment
Любые идеи относительно класса и поведения вашей функции также будут оценены.   -  person EFraim    schedule 24.07.2009
comment
Интересный вопрос. Забавно, как математика сначала становится сложной, когда вы начинаете изучать дроби и действительные числа, и снова становится сложной, когда вы удаляете их и возвращаетесь к натуральным числам. знак равно   -  person Jan Aagaard    schedule 24.07.2009
comment
Вы знаете уравнение для f(x, y)?   -  person Noldorin    schedule 24.07.2009
comment
Это не совсем вопрос программирования. Но это интереснее, чем Почему у меня не работает камера с ноутбуком? так что я ничего не говорю!   -  person Daniel Earwicker    schedule 24.07.2009
comment
Конечно, это вопрос программирования. Если только вы не считаете алгоритмы программами. Что касается меня, я думаю, что все, что не является алгоритмом, не является вопросом программирования. Например, как сделать X на языке Y — вопрос языка, а не программирования.   -  person Daniel C. Sobral    schedule 24.07.2009
comment
Это вопрос по алгоритму, но он касается очень хорошо изученного предмета чистой математики. Если бы у меня был такой вопрос, я бы пошел в группу новостей по математике или что-то в этом роде.   -  person Daniel Earwicker    schedule 24.07.2009
comment
Группы новостей по математике, вероятно, не будут очень полезны, если вас интересуют практические решения, а не теоретические решения для этого типа задач.   -  person SplittingField    schedule 13.08.2009


Ответы (8)


Как вы определяете f(x,y) ? Минимизация — сложная задача, зависящая от сложности вашей функции.

Генетические алгоритмы могут быть хорошим кандидатом.

Ресурсы:

Генетические алгоритмы поиска, оптимизации и машинного обучения

Реализация генетических алгоритмов на С#

Простой общедоступный C#

person Indy9000    schedule 24.07.2009
comment
Есть ли у вас какие-либо предложения о хороших ресурсах для начала работы с генетическими алгоритмами? - person Tim; 24.07.2009
comment
На эту тему есть масса книг. То, что заставило меня начать, было книгой Голдберга. amazon.com/Genetic-Algorithms-Optimization-Machine-Learning/ дп/ - person Indy9000; 24.07.2009

Здесь есть много, много решений. На самом деле, существуют целые книги и академические дисциплины, основанные на предмете. Я читаю отличный прямо сейчас: Как это решить: Современная эвристика.

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

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

person Brian Ramsay    schedule 24.07.2009
comment
Почему мои ссылки не работают? На превью такого не видно. - person Brian Ramsay; 24.07.2009

Вы смотрели на генетические алгоритмы? Они очень хорошо умеют находить минимумы и максимумы, избегая при этом локальных минимумов/максимумов.

person Daniel C. Sobral    schedule 24.07.2009
comment
Ну, они постепенно улучшаются, одно поколение за раз! - person Daniel Earwicker; 24.07.2009
comment
Но они нелинейны :) - person Indy9000; 24.07.2009

Если это произвольная функция, нет простого способа сделать это.

Предположим, у нас есть функция, определенная как:

f(x, y) = 0 for x==100, y==100
          100 otherwise

Как любой алгоритм может реально найти (100, 100) как минимум? Это может быть любая возможная комбинация значений.

Знаете ли вы что-нибудь о тестируемой функции?

person Jon Skeet    schedule 24.07.2009
comment
f(x,y) — функция ошибки калибровки. Меня интересуют два параметра. На оба влияют изменения x и y. Функция довольно непрерывна, но ее производная может и не быть, потому что, как только один из параметров находится в спецификации, я просто устанавливаю ее в 0 - person Tim; 24.07.2009
comment
@Jon Skeet: Это, конечно, при условии, что функция может быть любой, что действительно заставляет вас пробовать все комбинации (x, y). Если вы знаете, что функция псевдонепрерывна, все значительно упрощается. - person Noldorin; 24.07.2009
comment
@Noldorin: Вот почему я спросил, что ОП знает об этой функции. В то время, когда я опубликовал, функция, которую я дал, удовлетворила бы все, что мы знали. - person Jon Skeet; 24.07.2009
comment
@Jon Skeet: Действительно, функция, которую вы разместили, была примером довольно произвольной функции. Однако очень маловероятно, что функция не полностью произвольна (как мы теперь знаем, это не может быть так, поскольку она является функцией ошибок), а это означает, что возможен лучший подход. - person Noldorin; 24.07.2009

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

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

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

person Noldorin    schedule 24.07.2009
comment
Как я уже говорил, он будет использоваться в программе калибровки, поэтому будет много устройств, которые имеют похожие, но не идентичные формы для их функции ошибки. Я не знаю точно, как выглядит фигура, потому что мне нужно получить много данных. оба x и y находятся в диапазоне от 0 до 65535, и сбор одного фрагмента данных занимает пару секунд. - person Tim; 24.07.2009
comment
@Tim: Достаточно честно. Однако не могли бы вы дать нам форму этой функции ошибок? Я не очень оптимистично настроен на успех здесь, если запрос занимает считанные секунды! - person Noldorin; 24.07.2009
comment
Это в основном то, что происходит. Прошу прощения, если немного двусмысленно. двойная ошибка (x, y) { SetDeviceParams (x, y); двойной а = QueryParamA(); двойной б = QueryParamB(); двойной c = QueryParamC(); double _fReturnable = 0 if(a›=A_желаемый) { _fReturnable+=(A_желаемый-a)*(A_желаемый-a); } if(b›=B_желаемый) { _fReturnable+=(B_желаемый-b)*(B_желаемый-b); } if(c›=C_желаемый) { _fReturnable+=(C_желаемый-c)*(C_желаемый-c); } вернуть Math.sqrt(_fReturnable) } - person Tim; 24.07.2009
comment
+1, чтобы не попасть в ловушку локального минимума, попробуйте запустить градиентный спуск несколько раз из случайных начальных точек. - person Gabe Moothart; 24.07.2009
comment
@Гейб: Да, точно. Если у вас нет четкого представления о том, где находится минимум, вам нужно запустить алгоритм из диапазона начальных точек. - person Noldorin; 24.07.2009

Ответ Джона Скита правильный. Вам действительно нужна информация о f и ее производных, даже если f везде непрерывна.

Самый простой способ оценить трудности того, о чем вы просите (минимизация f только при целочисленных значениях), — это просто подумать о f: R->R (f — функция действительных чисел) одной переменной, которая делает большие отклонения между отдельными целыми числами. Вы можете легко построить такую ​​функцию, чтобы НЕ было корреляции между локальными минимумами на реальной линии и минимумами в целых числах, а также не было связи с первой производной.

Для произвольной функции я не вижу другого пути, кроме грубой силы.

person Community    schedule 24.07.2009
comment
Исходя из проведенного мной тестирования, градиент везде мал, поэтому функция не сильно меняется между целочисленными значениями, но я не могу предсказать, в каком направлении она изменится. Грубая сила не сработает, потому что получение одного фрагмента данных занимает слишком много времени. - person Tim; 24.07.2009
comment
так вы теперь говорите, что, помимо проблемы просмотра только целочисленных значений, вы даже не знаете f и собираетесь только отобрать подмножество {(x, y)} и попытаться сделать выводы из ограниченного подмножества? - person ; 24.07.2009
comment
@pgast К сожалению, я примерно это и говорю. У меня достаточно данных, чтобы угадать начальную точку, но на этом все. Хорошая новость заключается в том, что мне не обязательно заботиться о лучшем решении, пока решение, которое я получаю, соответствует спецификации. - person Tim; 24.07.2009
comment
Если это приложение, зависящее от жизни, я бы начал искать другую работу, так как то, что вас просят сделать, было бы халатностью первого порядка. Если нет, то я, вероятно, переборщил бы его с разумным выбором подмножества. Каков предел, nsamples, на количество образцов, которые вы можете взять? Я бы попробовал наложить сетку на 64Kx64 так, чтобы количество точек сетки было nsamples, семплировал в точках сетки и выбирал минимум. - person ; 24.07.2009
comment
Если у вас есть реальные знания о функции, то исходная сетка может иметь меньше точек, скажем, nsamples-m, и вы и вы можете использовать последние m выборок для грубой силы вокруг минимума первых (nsamples-m) выборок. Если я вас понимаю вы ищете пару параметров (x,y), чтобы настроить устройство так, чтобы ошибка была небольшой - person ; 24.07.2009

Итак, давайте посмотрим на вашу проблему с точки зрения математики. Это все при условии, что я полностью понимаю вашу проблему. Не стесняйтесь поправлять меня, если я ошибаюсь.

мы хотим минимизировать следующее:

\sqrt((a-a_желаемый)^2 + (b-b_желаемый)^2 + (c-c_желаемый)^2)

или в других обозначениях ||Pos(x - x_desired)||_2

где x = (a,b,c) и Pos(y) = max(y, 0) означает, что нам нужна «положительная часть» (это учитывает ваши операторы if). Наконец, мы хотим ограничиться решениями, в которых x является целым числом.

В отличие от приведенных выше плакатов, я не думаю, что генетические алгоритмы — это то, что вам нужно.
На самом деле, я думаю, что решение намного проще (при условии, что я понимаю вашу проблему).

1) Запустите любую процедуру оптимизации для указанной выше функции. Это даст вам решение x^* = (a^*, b^*,c^*). Поскольку эта функция возрастает по отношению к переменным, лучшее целочисленное решение, на которое вы можете надеяться, это (ceil(a^*),ceil(b^*),ceil(c^*)).

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

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

person SplittingField    schedule 13.08.2009
comment
+1 за оптимизацию без производных, но математическое переформулирование может использовать явное упоминание того факта, что x является функцией, и, возможно, переименовать x, чтобы оно не сталкивалось с переменными из опубликованного источника. - person outis; 13.08.2009
comment
x - это не функция, а просто набор переменных a, b, c в один вектор. - person SplittingField; 13.08.2009
comment
Тим хочет минимизировать не Err_A(x) = ||Pos(x - A)||₂, а Err_A(Dev(u)), где Dev(u):Z² -> R³. Если раствор. находится в x, он не обязательно должен быть целым числом. Кроме того, ceil·x' может быть недопустимым решением. в x, так как не может быть u' такого, что ceil·x'=Dev(u'). Для расширений Dev до некоторых Dev'(u):R² -> R³ я могу себе представить (террасы, сетки), растворы. в u будет иметь целые значения. Если экзотическое Dev'(u) имеет минимум в u'∉Z², элементы {ceil, floor}² · u' могут не быть решениями. - person outis; 13.08.2009
comment
Интересно... Мне нужно еще немного подумать об этом, но я явно что-то недопонимаю в его функции def. Тем не менее, я думаю, что есть и другие неэвристические решения, которые, насколько я знаю, используются в промышленности для решения такого рода проблем... например, MADS. - person SplittingField; 13.08.2009
comment
Dev представляет устройство. Это первые 4 строки его функции Error(x,y). - person outis; 13.08.2009

Извините, форматирование было таким плохим раньше. Вот пример функции ошибки

double Error(x,y)
{
SetDeviceParams(x,y);
double a = QueryParamA();
double b = QueryParamB();
double c = QueryParamC();
double _fReturnable = 0;
if(a>=A_desired)
{
  _fReturnable+=(A_desired-a)*(A_desired-a);
}
if(b>=B_desired)
{
 _fReturnable+=(B_desired-b)*(B_desired-b);
}
if(c>=C_desired)
{
  _fReturnable+=(C_desired-c)*(C_desired-c);
}
return Math.sqrt(_fReturnable)
}
person Tim    schedule 24.07.2009
comment
Ах, хорошо, я сделал это для вас. Форматирование в итоге получилось другим, так как я сдуру скопировал из отображаемого текста вместо редактируемого текста. - person Daniel C. Sobral; 24.07.2009