Здесь больше нет рекламы. Но могла бы быть, могла.

Автор Тема: Каков оптимальный алгоритм поиска седловой точки в матрице?  (Прочитано 13091 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Меанор

  • Гость
Разумеется. Перестановку мы сможем хранить отдельно. Более того, на каждом шаге мы и дальше сможем выбросить половину элементов любой квадратной подматрицы за K*logK, где K её сторона...

               

               

Арвинд

  • Гость
С учетом предложения Меанора не ждать милостей от природы, а сортировать и гарантированно выкидывать половину квадрата (без диагонали), можно предложить второй шаг. Ясно, что на первом мы целиком вычеркнем из матрицы строку, в которой оказался минимум и столбец, в котором оказался максимум. На втором шаге естественно попробовать взять матрицу со стороной N-1, которая остается без указанных строки и столбца. В ней диагональ можно провести перпендикулярно проведенной ранее.
Вот для третьего шага надо будет как-то обобщить перпендикулярность, найти другой критерий максимизации числа невычеркнутых элементов. В частности, там, я думаю, будет уже использоваться не совсем диагональ - ведь мы нигде не использовали то, что эти элементы лежат на прямой. Это просто набор элементов, никакие два из которых не лежат в одной строке и в одном столбце. Такие наборы используются в определителе матрицы, между прочим...

               

               

Mrrl

  • Гость
Есть C*nln 3/ln 2 (для квадратных матриц).

Заметим, что если (p,q) - седловая точка в матрице, то она же будет седловой точкой в любой ее подматрице, содержащей эту точку. После того, как мы знаем, что седловая точка находится в верхней половине матрицы (над диагональю), мы можем разделить матрицу на 4 примерно одинаковых части (правая нижняя не содержит диагональных элементов), сказать, что седловая точка может быть только в первых трех подматрицах, найти для них эти седловые точки (или доказать, что их не существует), и проверить, будет ли какая-нибудь из них седловой для всей матрицы.

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

Кажется, число операций можно еще уменьшить, если делить диагональ на 3 неравные части (большую и две маленьких). Но там придется считать.

               

               

Арвинд

  • Гость
Пока не понял деталей, на выходных попробую. Понятен принцип, интересный.

Думаю, желательно в этой теме доводить идеи, претендующие на оптимальность, до программного кода.

Цитата из: Mrrl on 19-12-2005, 14:21:27
Кажется, число операций можно еще уменьшить, если делить диагональ на 3 неравные части (большую и две маленьких). Но там придется считать.

В порядке полуоффтопика: замечательный источник идей - метод Лупанова. Стоит повспоминать...

               

               

Mrrl

  • Гость
Уфф... n*sqrt(2*log2n)*2^sqrt(2*log2n)

Пусть матрица квадратная, n*n.
Для простоты введем переменную u=sqrt(2*log2n), т.е.  n=2u^2/2.
Определим n1=sqrt(2)*n/2u=2(u-1)^2/2. (округленное до целого).

Разобьем диагональные элементы матрицы на 3 группы - n1 маленьких, n-2*n1 средних, n1 больших. Отсортируем строки-столбцы матрицы, чтобы элементы M[i,n+1-i] для i из [1,n1] были "большими", для i из [n1+1,n-n1] - "средними", а для i из [n-n1+1,n] - "маленькими". Тогда седловая точка, если она есть, будет принадлежать одной из матриц M[1..n1,n-n1+1..n], M[1..n-n1,1..n-n1], M[n-n1+1..n,1..n1]. Размеры двух матриц равны n1, третьей - n-n1. Найдем (рекурсия) седловые точки этих матриц. Проверить, будет ли одна из них (и какая) седловой точкой всей матрицы, можно за 4*n-2*n1 сравнений. Если я нигде не ошибся, то число операций для этого алгоритма не превосходит C*u*2u*n.

Следующий рубеж обороны - n*log(n)2.

Написать код можно, но он уже становится довольно противным.

               

               

Меанор

  • Гость
Как я понимаю, рекурсивный метод проиллюстрирован, собственно, вот этой картинкой:

(http://stratum.ac.ru/textbooks/kgrafic/additional/addit24/img01.gif)

Правда, зачем нужен выбор такого непростого n1? Вообще, мне кажетя при разбивке на неравные квадраты, мы получим только большее количество действий. Ведь мы будем проверять уже проверенные элементы. Сдаётся мне, у вас в счёте что-то неправильно.

               

               

Арвинд

  • Гость

Цитата из: Mrrl on 19-12-2005, 18:31:27
Написать код можно, но он уже становится довольно противным.

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

               

               

Меанор

  • Гость
Правда маленьких треугольничков будет порядка n. Да ещё по 2n действий на каждый, чтобы проверить его на "седловость". Таким образом, опять будет n^2 действий.

               

               

Mrrl

  • Гость
А не надо 2n на проверку. Каждый маленький треугольник проверяется в своем (вдвое большем) квадратике, а выше передается только одна седловая точка (если есть). И она проверяется в квадратике большего размера.

               

               

Меанор

  • Гость
Гм... Да? А если окажется, что не удаётся из трех точек выбрать одну, чтобы передать наверх? То есть, допустим, две оказались в текущем квадрате седловыми?

               

               

Арвинд

  • Гость
Да, кстати, в моем изначальном предложении о том, что делать при равенстве элементов в матрице (даже не обязательно седловых), было скромно умолчено. Надо б в этом разобраться.

               

               

Mrrl

  • Гость
При равенстве значений седловых точек проблемы не возникает - достаточно воспользоваться моим алгоритмом проверки значения (описан где-то в начале). Проблема будет, если среди диагональных элементов больше, чем n1 самых маленьких одинаковых. Надо подумать.



               

               

Mrrl

  • Гость
Нет, все просто. Если все диагональные элементы в подматрице одинаковы, то и значение седловой точки в ней такое же, как эти элементы. Достаточно проверить, есть ли в этой подматрице такая седловая точка. Или не проверять - а отложить до проверки на матрице большего размера.

               

               

Меанор

  • Гость
Не понял. Причем здесь равенство значений? Одна точка - седловая в некоторой подматрице. Вторая - тоже седловая. Пусть они в одном ряду находятся. (Иначе, будет уже четыре седовых.) Но одна из них может быть седловой во всей матрице, а вторая может не быть. Естественно могут быть и обе или ни одна из них. Как, простите, мы можем из рекурсии вернуть только одну (не более чем одну) подозрительную на "седловость" точку?

               

               

Меанор

  • Гость

Цитата из: Mrrl on 19-12-2005, 20:11:54
Достаточно проверить, есть ли в этой подматрице такая седловая точка.


Я пока не видел описания алгоритма для этого, работающего быстрее, чем за M*N.

               

               

Меанор

  • Гость
И в-третьих, объясните, что ваша неравноразмерная рекурсия с n1 даёт по сравнению с обычным, равноразмерным методом? Почему она будет работать быстрее? Пояните, пожалуйста, расчёты.

               

               

Mrrl

  • Гость
1. "То есть, допустим, две оказались в текущем квадрате седловыми?"
  Как мы знаем, если две точки оказались седловыми, то значения в них одинаковы. Поэтому я предлагаю на каждом этапе искать не саму седловую точку, а только ее значение. На каждом шаге алгоритма у нас будут три кандидата на значения седловых точек (те, что вернулись из трех под-подматриц), и нам нужно проверить, какое из них может оказаться значением седловой точки для нашей подматрицы. Для этого можно воспользоваться следующим алгоритмом (сравнивающим значение седловой точки, если она есть, с поданным значением a):


int CheckVal(double [,]M,int m,int n,double a,out int iv,out int jv){
  iv=jv=0;
  int i1=0,j1=0;
  while(i1<m && j1<n){
    if(M[i1,j1]>a) j1++; else i1++;
  }
  if(i1==m) return 1;   // a>val
  int i2=0,j2=0;
  while(i2<m && j2<n){
    if(M[i2,j2]>=a) j2++; else i2++;
  }
  if(j2==n) return -1;   // a<val
  iv=i1; jv=j2;  // some saddle point
  return 0;
}


Алгоритм выдает -1,0 или 1, если a меньше, равно или больше значения седловой точки соответственно. Если выдано 0, то в параметрах iv, jv выдаются координаты потенциальной седловой точки (если хотя бы одна седловая точка со значением a есть, то гарантируется, что (iv,jv) - одна из них).

2. Действительно, можно ничего не проверять. Если в подматрице все диагональные элементы одинаковы, то их значение - единственный кандидат на значение седловой точки. Его и вернем.

3. "Обычный метод" - деление пополам или что-то еще?
Пусть f(n) - число операций, необходимое для поиска седловой точки. Пусть мы умеем искать медиану (и более широко - k-е по порядку значение из массива) + сортировать массив на "большие - меньшие" за C*n операций.
В случае деления пополам получаем:
f(n)=3*f(n/2)+n*(C+4)
(здесь 4*n - наихудшее время работы функции CheckVal).
Очевидно, что f(n)=D*n^(ln(3)/ln(2)), где D - некоторая константа.

Пусть рекурсия неравномерна. Для нее
f(n)=f(n-n1)+2*f(n1)+n*(2*C+4)
2*C понадобилось, поскольку диагональные элементы делятся на части дважды. Можно проверить, что если
n1=n/2^(sqrt(2*log(n)-1/2), то f(n)<D*n*sqrt(2*log(n))*2^sqrt(2*log(n))
(но это примерно страница выкладок). А это функция растет медленнее любой степенной (c показателем, большим 1).

В общем, дело в формуле f(n)=f(n-n1)+2*f(n1)+n*(2*C+4), точнее, в коэффициенте 2 перед f(n1). Поскольку f(n) выпукла вниз, для минимизации этого выражения требуется, чтобы выполнялось условие n1<n-n1. Точнее, f'(n-n1)=2*f'(n), а из-за медленного роста f(n)/n получаем, что n1 гораздо меньше n-n1.






               

               

Меанор

  • Гость
Ну хорошо, а что нам даст поиск предполагаемого значения в седловой точке, если мы даже не будем уверены в том, что такая точка на матрице существует? Допустим, мы поличили: если на матрице есть седловая точка, то значение в ней A. Как нам её найти? Ведь, не любая точка со значением A является седловой.

               

               

Mrrl

  • Гость
Так я же написал: если существует хотя бы одна седловая точка со значением a, то точка (iv,jv), выданная функцией CheckVal, гарантированно является одной из них. Но если мы не уверены в существовании, нам надо потратить еще m+n операций на проверку. Если окажется, что (iv,jv) - не седловая точка, значит, их вообще нет.

               

               

Bindaree

  • Гость
Господа,

я вот это все не читала подробно, но у меня тот же вопрос, что и у Арвинда - есть МОР. Есть Кун с Такером. Есть определители и все прочие прелести.

Я собираюсь эту тему шлепнуть. Не вижу я в ней формата ИР. Можно? Конечно, не сейчас. Но потом,когда она вам всем надоест :)


С уважением,

Шаси

1. Вопрос решен. Можно писать дальше. Тема стерта в любом случае не будет, в худшем (маловероятном) случае - перенесена.
2. А что такое МОР?
Арвинд.

Эй, я не останавливала тему :) Я просто плотоядно на нее косилась  ;D Уже больше не кошусь.Вообще в ее сторону не смотрю.  ;)

МОР - метод оптимальных решений  ;) раздел математики, посвященный как раз этой проблеме :) в частности, поиску эффективных решений для матриц и оптимизиционных задач :)

С уважением,

Шаси.