Использование индукции для доказательства линейного алгоритма максимального подмассива

Вот моя реализация алгоритма Кадане, которую я написал для OCaml:

let rec helper max_now max_so_far f n index = 
  if n < index then max_so_far
  else if max_now + f index < 0 
  then helper 0 max_so_far f n (index+1)
  else helper (max_now + (f index)) 
      (max max_so_far (max_now + (f index))) f n (index+1)

let max_sum f n = helper 0 0 f n 1

Теперь я хочу формально доказать, что это правильно. Спецификация моего кода:

Функция f для аргументов от 1 до n возвращает целое число. Функция max_sum с параметрами f n должна возвращать наибольшую сумму сумм:

сумма

Где 1‹=a‹=b‹=n.

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


person qiubit    schedule 12.10.2014    source источник


Ответы (2)


База индукции не пройдет, так как алгоритм и спецификация расходятся во мнениях относительно допустимости пустого подмассива (имеющего сумму 0). Я буду следовать спецификации, запрещающей пустые подмассивы.

Индуктивный шаг состоит в следующем. Для всех k определите

max_now  = max_{a in 1..k  } sum_{i in a..k  } f(i)
max_now' = max_{a in 1..k+1} sum_{i in a..k+1} f(i)
max_so_far  = max_{b in 1..k  } max_{a in 1..b} sum_{i in a..b} f(i)
max_so_far' = max_{b in 1..k+1} max_{a in 1..b} sum_{i in a..b} f(i).

Нам нужно показать, что

max_now' = max(max_now, 0) + f(k+1)
max_so_far' = max(max_so_far, max_now').

Оба равенства доказываются расщеплением max.

max_now' =      max_{a in 1..k+1} sum_{i in a  ..k+1} f(i)
         = max( max_{a in 1..k  } sum_{i in a  ..k+1} f(i),
                                  sum_{i in k+1..k+1} f(i))
         = max((max_{a in 1..k  } sum_{i in a  ..k  } f(i)) + f(k+1),
                                                              f(k+1))
         = max(max_now, 0) + f(k+1)

max_so_far' =     max_{b in 1..k+1} max_{a in 1..b  } sum_{i in a..b  } f(i)
            = max(max_{b in 1..k  } max_{a in 1..b  } sum_{i in a..b  } f(i),
                                    max_{a in 1..k+1} sum_{i in a..k+1} f(i))
            = max(max_so_far, max_now')
person David Eisenstat    schedule 12.10.2014
comment
Я не могу понять ваш пост. Что означает max, это сумма максимального подмассива или максимума массива? Что означает max_{a в 1..k}? - person Simin Jie; 29.08.2018

Пусть maxSum[i] будет наибольшей суммой непрерывного массива, оканчивающейся на индекс i.
Я хочу доказать это утверждение алгоритма кадане -
maxSum[i] = max(maxSum[i-1] + a[i], a[i])

if a[i] > maxSum[i-1] + a[i]

on considering a[i+1], 
a[i] + a[i+1] > maxSum[i-1] + a[i] + a[i+1]

Поэтому лучше прервать непрерывность и начать новый подмассив с i-го индекса.

person Gaurav Sharma    schedule 13.09.2020