Скачиваний:
24
Добавлен:
01.05.2014
Размер:
292.38 Кб
Скачать

24

  1. Индуктивные функции

    1. Общая схема вычисления индуктивных функций

Основные определения, схема программ и примеры алгоритмов вычисления индуктивных функций на последовательностях подробно изложены в [6]. Более краткое изложение дано в [1] и ориентировано на представление последовательности в виде последовательного файла. Конечно, последовательность может быть реализована и как массив, и как линейный список, и некоторыми другими способами. Далее в заданиях будем рассматривать реализацию последовательности именно в виде файла, так как этот способ делает более естественным использование однопроходных алгоритмов, что и достигается при вычислении индуктивной функции.

В приведенных далее заданиях указана функция f(), значение которой надо вычислить. Будем использовать обозначения, введенные в [1]: – последовательность элементов заданного типа, т. е. = x1x2xn, где xi  X, а X – произвольный алфавит; пустая последовательность обозначается как ; k(X) – пространство всех конечных последовательностей над X длины не менее, чем k; при этом 0(X) (X).

Напомним определение индуктивной функции (см.[1], с.20). Функция f: (X) Y называется индуктивной, если f(x) можно вычислить, зная f() и x, т. е. если существует функция G: XY, такая, что для всех   (X),  X выполняется соотношение f(X) = G(f(), x).

Если последовательность реализована в программе файлом fin типа file of X, то вычисление индуктивной функции может быть реализовано следующим фрагментом программы:

Reset(fin); y:=y0; {y0=f()}

While not Eof(fin) do

begin

Read(fin,x);

y:=G(y,x)

end {while}

Очевидно, что это фактически схема, из которой конкретная программа может быть получена интерпретацией абстрактных типов X и Y, переменных xy и y0, функции G(yx). Эта схема имеет инвариант цикла y = f(L(fin)) и ограничивающую функцию Length(R(fin)). Здесь использованы обозначения: L(fin) – прочитанная часть файла fin, R(fin) – непрочитанная часть, а Length(fin) – длина файла (количество элементов представленной в нем последовательности).

    1. Общая формулировка задания

Заданы алфавит X и функция f: (X) Y. Требуется определить, является ли функция f() индуктивной. Если “да” – выписать функцию G(,), если “нет” – подтвердить это, применяя критерий индуктивности [1, с. 21], а затем придумать индуктивное расширение [1, с. 23] и выписать G для него.

Далее требуется написать на языке Паскаль программу вычисления указанной функции f(), считая, что – это состояние последовательности элементов типа X, находящейся во входном файле.

При формулировке задания используются следующие обозначения типов, реализующих алфавит X: Z – Integer, N – натуральные, N0 – натуральные с нулем, S – Char, B – Boolean, R – Real, R0 – неотрицательные Real, R+ – положительные Real, R2 = R * R (декартово произведение).

Используется также следующая специальная терминология:

а) отрезок – это связная подпоследовательность (т. е. подпоследователь-ность подряд идущих элементов основной последовательности);

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

    1. Цель, требования и рекомендации к выполнению задания

      Цель выполнения задания: ознакомиться с основными приёмами и получить навыки программирования задач обработки последовательностей однотипных элементов с применением однопроходных алгоритмов. В качестве типовой задачи рассматривается частный, но показательный и важный пример – вычисление индуктивных функций на последовательностях. При этом математическая последовательность реализуется в заданиях как последовательный файл.

Требования и рекомендации к выполнению задания:

  1. алгоритм решения задачи должен быть однопроходным и не должен использовать дополнительную память, пропорциональную размеру входного файла (использование массивов для хранения входной последовательности запрещено);

  2. возможны 2 варианта реализации последовательности в виде входного файла: а) файл имеет тип Text, создается с помощью стандартного текстового редактора и просматривается тоже стандартными средствами; б) файл имеет тип file of X, создается и просматривается специальной отдельной программой (или программами) генерации и просмотра;

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

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

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

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

    1. Пример выполнения задания

      Рассмотрим задачу, подробно проанализированную в [1, с.26]: вычисление суммы элементов отрезка заданной последовательности, имеющего максимальную сумму. Далее приводится программа, решающая эту задачу. В комментариях приведены все основные обозначения и рекуррентные (индуктивные) расчетные соотношения, позволяющие понять работу программы.

program Inductive_function_1;

{-------------------------------------------------------------------------------------------------}

{ Пример вычисления индуктивного расширения функции : }

{ f( w ) = " Сумма элементов отрезка с максимальной суммой " , }

{ где отрезок - связная подпоследовательность последовательности w. }

{ Пусть исходная последовательность есть w = x(1)x(2)...x(n) }

{ и пусть S(k,l) = SUM ( k <= i <= l : x(i) ), где 1 <= k <= l <= n . }

{ Тогда заданная функция есть f(w) = max ( S(k,l) : 1 <= k <= l <= n ) }

{ Функция f - неиндуктивна. Рассмотрим индуктивное расширение }

{ F = ( f, t ), где t( w ) = max ( S(j,n) : 1 <= j <= n ) }

{ Содержательно t(w) - потенциальный конкурент текущего рекорда f(w) }

{ при продолжении последовательности w . Вычисление f и t : }

{ t ( w * x ) = max ( x, x + t(w) ), }

{ f ( w * x ) = max ( f(w), t(w*x) ), }

{ t ( $ ) = 0, f( $ ) = MinInt. }

{ Здесь $ обозначает пустую последовательность. }

{ Исходная последовательность читается из файла INITSEQ.DAT . }

{-------------------------------------------------------------------------------------------------}

const MinInt = -32768;

var x, { очередной элемент последовательности }

y, { y = f ( w ) }

z : Integer; { z = t ( w ) }

fin, { input file }

fout : Text ; { output file }

begin

Assign( fin, 'INITSEQ.DAT' );

Assign( fout, {'INFREZ.DAT'}'' );

Rewrite( fout );

WriteLn( fout, 'Элемент Рекорд Конкурент ' );

Reset( fin ); { L(fin)=$ }

y := MinInt; { y=f($) }

z := 0; { z=t($) }

{ inv : y=f(L(fin)) & z=t(L(fin)) }

{ bound: length(R(fin)) }

while not Eof(fin) do

begin

Read( fin, x );

Write( fout, x : 8 );

{ новый конкурент : }

if z>0 then z := z + x else z := x;

{ новый рекорд : }

if z>y

then { обновить рекорд }

begin

y := z;

WriteLn( fout, y : 9 )

end

else { оставить старый }

WriteLn( fout , z : 20 );

end { while };

{ y = f ( fin ) & z = t( fin ) }

WriteLn( fout, '***Максимальная сумма = ', y, '***' );

Close( fin );

Close( fout )

end { Inductive_function_1 } .

Экран результатов

Элемент Рекорд Конкурент

1 1

2 3

-5 -2

3 3

6 9

-10 -1

6 6

9 15

1 16

-5 11

***Максимальная сумма = 16***

Результаты выполнения этой программы приведены в таблице.

В первой колонке выводятся элементы входной последовательности, во второй — значение “текущего” рекорда, если он обновляется (замещается конкурентом) на данном шаге. В третьей колонке выводятся значения конкурента, кроме тех шагов, на которых конкурент становится новым рекордом. Такой вывод исходных и промежуточных данных позволяет проследить за работой алгоритма по шагам и понять способ формирования окончательного результата.