NetNado
  Найти на сайте:

Учащимся

Учителям



1. /_Методички/Мультимедиа-системы. Архитектура, стандарты, алгоритмы.pdf
2. /_Методички/Организация ЭВМ 2006.doc
3. /_Методички/Основы сетевых технологий.djvu
4. /_Методички/Программирование/Биные Деревья Поиска/2_01БДПоиска.doc
5. /_Методички/Программирование/Биные Деревья Поиска/2_02БинДП.doc
6. /_Методички/Программирование/Биные Деревья Поиска/2_03СлучайБДП.doc
7. /_Методички/Программирование/Деревья Хаффмана/1.doc
8. /_Методички/Программирование/Деревья Хаффмана/1_1ДХафф.doc
9. /_Методички/Программирование/Деревья Хаффмана/1_2_3_ДХафф.doc
10. /_Методички/Программирование/Деревья Хаффмана/1_4_ДХафф.doc
11. /_Методички/Программирование/Деревья Хаффмана/1_5_ДХафф.doc
12. /_Методички/Программирование/Деревья Хаффмана/1_6_7_ДХафф.doc
13. /_Методички/Программирование/Деревья Хаффмана/1_8ДХафф.doc
14. /_Методички/Программирование/Деревья Хаффмана/1_9ДХафф.doc
15. /_Методички/Программирование/Деревья Хаффмана/ДерХафф full.doc
16. /_Методички/Программирование/Деревья Хаффмана/КарлКлара.doc
17. /_Методички/Программирование/Деревья Хаффмана/Кодируется текст АБРАКАДАБРА.doc
18. /_Методички/Программирование/Динамические СД/00Титул.rtf
19. /_Методички/Программирование/Динамические СД/0Введение.rtf
20. /_Методички/Программирование/Динамические СД/1Списки.doc
21. /_Методички/Программирование/Динамические СД/2СтекОчДек1.rtf
22. /_Методички/Программирование/Динамические СД/3Деревья.rtf
23. /_Методички/Программирование/Динамические СД/4прим_лит.rtf
24. /_Методички/Программирование/Динамические СД/5оглавление.doc
25. /_Методички/Программирование/Динамические СД/Динамическое программирование - Задача о перемножении матриц.doc
26. /_Методички/Программирование/Пособие по разработке корректных программ/00Титул1_3.doc
27. /_Методички/Программирование/Пособие по разработке корректных программ/01Введение.rtf
28. /_Методички/Программирование/Пособие по разработке корректных программ/1АлгоритмЕвклида.doc
29. /_Методички/Программирование/Пособие по разработке корректных программ/2ОсновыАналитВерифПрогРовно.doc
30. /_Методички/Программирование/Пособие по разработке корректных программ/3ИндуктФункции.doc
31. /_Методички/Программирование/Пособие по разработке корректных программ/4Массивы.doc
32. /_Методички/Программирование/Пособие по разработке корректных программ/5Поиск.doc
33. /_Методички/Программирование/Пособие по разработке корректных программ/ОглавФонар.doc
34. /_Методички/Программирование/Пособие по разработке корректных программ/СписЛит&УслОбознач.doc
35. /_Методички/Сетевые технологии.pdf
36. /_Методички/Средства моделирования вычислительных сетей.pdf
37. /_Методички/Управление вычислительными сетями.pdf
Учебное пособие Редактор А. В. Крейцер Издательство спбгэту «лэти» 1 97376, С. Петербург, ул. Проф. Попова, 5
2. Деревья поиска Идеально сбалансированные бинарные деревья
2 Случайные бинарные деревья поиска
Абракадабра!, содержащий 12 символов, включая специальный символ !
Задача кодирования сообщений. Префиксные коды и деревья Пусть задан алфавит
1 Код Фано-Шеннона
1 Метод Хаффмана
1 Реализация алгоритмов кодирования
1 Доказательство оптимальности кода Хаффмана Лемма 1
1 Энтропийная оценка средней длины кода
1 Динамическое кодирование по Хаффману
Абракадабра!, содержащий 12 символов, включая специальный символ !
Абракадабра!, содержащий 12 символов, включая специальный символ !
А. Ю. Алексеев с. А. Ивановский д. В. Куликов
При обучении программированию особую трудность вызывает работа с динамическими структурами данных
2. стеки и очереди спецификация стека и очереди
3 Определения дерева, леса, бинарного дерева. Скобочное представление
Примечания и библиографические указания
Списки
Задача о порядке перемножения матриц
С. А. Ивановский разработкакорректныхпрограм м санкт-Петербург 2003
Программирования
Разработка, доказательство корректности и анализ алгоритма
2. основы аналитической верификации программ основные правила аналитической верификации программ
3. индуктивные функции на последовательностях
4. корректность программ при работе с массивами
5. поиск в массиве линейный поиск
Разработка, доказательство корректности
Шень А. Программирование: теоремы и задачи: Учеб пособие

скачать doc


2. ИНДУКТИВНЫЕ ФУНКЦИИ НА ПОСЛЕДОВАТЕЛЬНОСТЯХ 0 17 1

2.1. Последовательности и файлы 17 1

2.2. Индуктивные функции 20 4

2.3. Стационарные значения индуктивных функций 22 6

2.4. Индуктивные расширения функций 23 7

2.5. Примеры задач с индуктивными функциями 24 8

.
3. ИНДУКТИВНЫЕ ФУНКЦИИ НА ПОСЛЕДОВАТЕЛЬНОСТЯХ
3.1. Последовательности и файлы
Пусть X – произвольный алфавит (конечное множество). Рассмотрим последовательности символов из этого алфавита: x1 x2 … xn (xi  X). Пустую последовательность обозначим . Пусть:

  • (X) или для краткости просто   пространство всех конечных последовательностей над X, т. е.

(X) = {x1 x2 … xnnN0xi  X   i1..n},

при этом   ;

  • k(X) или для краткости просто k  пространство конечных последовательностей длины не менее k, т. е.

k(X) = {x1 x2 … xnn  knN0xi  X   i1..n};

таким образом,  = 0  1  2 ... .

Определим операцию postfix:   X   добавления элемента в конец последовательности, т. е. если   = x1 x2 … xn, то postfix(, x) = x1 x2 … xn x , а postfix(, x) = x. Иногда эту операцию удобнее записывать в инфиксной форме, используя для нее специальный знак, например «*», т. е. postfix(, x) =  * x. В этих обозначениях  * x = x1 x2 … xn x и  * x = x. Если   k, то  * x  k + 1.

Тогда конструктивно последовательность можно определить так:

1)   есть последовательность;

2) если   последовательность, то и  * x  последовательность;

3) ничто другое (кроме пп.1 и 2) не есть последовательность.

Полезно дополнительно определить следующие операции над последовательностями:

first: 1  X, rest: 1  , prefix: X    1,

и если    и   = x1 x2 … xn, то

first() = x1, rest() = x2 … xn, prefix(first(), rest()) = .

Последовательный файл (или далее просто файл) из записей типа X (file of X)  это реализация математического понятия последовательности с ограниченными способами доступа к элементам. Наглядная модель файла представлена на рис. 3.1. Положение ленты относительно головки чтения-записи определяется разбиением ее (ленты) на две части: левую L(F) и пра-







L(F)





R(F)






Начало ленты 




















Лента












































Головка

чтения-записи

Метка

конца

файла




Рис. 3.1. Наглядная модель последовательного файла
вую R(F). Кроме того, файл может находиться в одном из трех режимов: неопределенном (n), чтения (r), записи (w). Таким образом, файл можно определить как упорядоченную тройку F = (L(F), R(F), St(F)), где индикатор режимов St(F)  {nrw}. Состояние файла R(F) =  идентифицируется предописанной функцией (предикатом) Eof(F): если R(F) = , то Eof(F) = true, иначе Eof(F) = false (рис. 3.2).


F:





















F:


























































Eof(F) = false













Eof(F) = true


Рис. 3.2. Действие функции Eof(F)
Определим основные операции над файлами.

1. Установка режима записи: Rewrite(F). Семантика этой операции задается свойством {true} Rewrite(F) {Eof(F) & (L(F) =  ) & (St(F) = w)}  и иллюстрируется на рис. 3.3.


F:





















F:



























































Рис. 3.3. Установка режима записи Rewrite(F): слева  состояние до

операции, справа  состояние после операции
2. Запись в файл: Write(F, x). Семантика этой операции (аналога postfix) задается свойством

{(St(F) = w) & Eof(F) & (L(F) =   )}

Write(Fx);

{(St(F) = w) & Eof(F) & (L(F)=  * x )}

и иллюстрируется на рис. 3. 4.


F:






















F:






















































x:
















x:



























Запись


Рис. 3.4. Запись в файл Write(Fx): слева – состояние до операции,

справа – состояние после операции
3. Установка режима чтения: Reset(F). Семантика операции задается свойством {F =   } Reset(F) {(L(F) = ) & (R(F) = ) & (St(F) = r)} и иллюстрируется на рис. 3.5.


F:





















F:
























































Рис. 3.5. Установка режима чтения Reset(F): слева – состояние

до операции, справа – состояние после операции


F:





















F:






















































x:
















x:



























Чтение


Рис. 3.6. Чтение из файла Read(Fx): слева – состояние до операции,

справа – состояние после операции
4. Чтение из файла: Read(Fx). Семантика этой операции задается свойством

{(St(F) = r) & not Eof(F) & (L(F) = ) & (R(F) = )}

Read(Fx)

{(St(F) = r) & (L(F) = *first()) & (R(F) = rest()) & (x = first())}

и иллюстрируется на рис. 3.6.
3.2. Индуктивные функции
Пусть в файле fint записана последовательность целых чисел   (Z), требуется найти максимальное из них, т. е. Max(). Программа может быть написана из естественного соображения: читаем последовательность  и для каждого очередного элемента x определяем максимальный элемент прочитанной части последовательности. Очевидно, что Max(*x) = max(Max(), x), где max(ab) обозначает максимальное из двух чисел a и b. Доопределив Max() = , получаем фрагмент программы, вычисляющий Max():

var  x, y: Integer; fint: file of Integer; …

Reset(fint); y := 32768; {y := }

while not Eof(fintdo

begin

Read(fintx);

if x > y then y := x

end {while} {y = Max()}

Инвариантом цикла здесь является соотношение y = Max(L(fint)), а ограничивающей функцией  Length(R(fint)).

Функции от последовательностей, подобные рассмотренной, встречаются часто и могут быть названы индуктивными [14], или марковскими [18].

Определение. Функция f: (X)  Y называется индуктивной, если f(*x) можно вычислить, зная f() и x, т. е. если существует

G:Y  X  Y,

такая, что для всех   (X), x  X выполняется соотношение

f(*x) = G(f(), x).

Рассмотренный пример с Max() записывается в этих обозначениях следующим образом:

f() = Max(), X = Z, f: (Z)  Z, G(yx) = max(yx).

Еще один пример индуктивной функции:

f = «число положительных элементов последовательности».

Здесь f: (Z)  N0. Функция f() индуктивна. Действительно, для всех   (Z), x  Z имеем f(*x) = G(f(), x), f() = 0, где GN0Z  N0 и

 y + 1, если > 0,

G(yx) =  

 y, если  0.

Индуктивные функции удобно вычислять. Пусть известно значение f0 = f(). Тогда значение fn = f(n), где n x1 x2 … xn , можно найти так:

1 = 0*x1, f1 = f(1) = G(f0x1),

2 = 1*x2, f2 = f(2) = G(f1x2),



n = n  1*xn, fn = f(n) = G(fn  1xn).

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

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


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

while not Eof(findo

begin

Read(finx);

y := G(yx)

end {while}

Пример неиндуктивной функции:

f = «число максимальных элементов последовательности».

Пусть, например x  R, тогда f: (R)  N0. Очевидно, можно положить f() = 0 и записать

1, если x > Max(),

f(*x) =   f() + 1, если x = Max(),

 f(), если x < Max().

Поскольку для вычисления f(*x) необходимо кроме f() и x знать еще Max(), то функция f не является индуктивной.

Можно ввести формальный критерий индуктивности [14].

Утверждение. Функция f индуктивна тогда и только тогда, когда

,   : (f() = f())  (f(*x) = f(*x))

для любого x  X.

Для предыдущего примера  = (0, 1, 0, 1),  = (1, 2, 1, 2), f() = 2, f() = 2. При x = 1 получим f(*x) = 3 и f(*x) = 2, т. е. f(*x)  f(*x), и, следовательно, f  неиндуктивна.
3.3. Стационарные значения индуктивных функций
Пусть f: (X)  Y индуктивная функция, т. е. существует G:Y  X  Y, такая, что для всех   (X), x  X выполняется соотношение f(*x) = G(f(), x).

Значение ysY называется стационарным, если ys = G(ysx) для любого x  X.

Пример. Пусть = «среди элементов   (Z) нет нулевых». Здесь f: (Z)  Boolean и решение имеет вид f() = true,  f(*x) = (f() & (x  0)). Ясно, что f() = false – стационарное значение, так как для любого bBoolean имеем false & b = false. В этом случае программу можно записать с учетом стационарного значения:

Reset(fin);

y := true; {y = f()}

while not Eof(fin) & y do

begin

Read(fin, x);

y := ( 0)

end {while}

Здесь оператор := y & (x  0) заменен на := (x  0), поскольку в условие продолжения цикла добавлен конъюнктивный член y.

В общем случае схема вычисления индуктивной функции, имеющей стационарное значение, такова:

Reset(fin);

y := y0; {y0 = f()}

while not Eof(fin) & (y  стационарное значениеdo

begin

Read(finx);

y := G*(yx)

end {while}

Здесь G* либо совпадает с G, либо является ее сужением с учетом выполнения условия «y  стационарное значение» в теле цикла.
3.4. Индуктивные расширения функций
Многие функции не являются индуктивными. Это значит, что информация, заключенная в f(), недостаточна для вычисления f(*x). Однако можно определить, какой именно информации не хватает, и попытаться ее получить. Тогда рассмотрим более сложную функцию, чем исходная, но она уже будет индуктивной.

Пример. Пусть f = «число максимальных элементов последовательности». Эта функция уже рассматривалась в 3.2 как пример неиндуктивной функции. В полученные рекуррентные соотношения

1, если x > Max(),

f(*x) =   f() + 1, если x = Max(),

 f(), если x < Max()

входит еще функция Max(). Если вычислять и ее значение, то на каждом шаге можно будет определять f(*x).

Пусть x  R, тогда f: (R)  N0. Введем в рассмотрение функцию Max: (R)  R*, где R* = R  {  },  «»  идеальный элемент, используемый как значение Max(). Добавляя к соотношению для f(*x)  соотношение Max(*x) = max(Max(), x), можно написать следующую программу:

Reset(fin);

y := 0; {y = f()} z := ; {z = Max()}

while not Eof(findo

begin

Read(fintx);

if x > z then begin := x; y := 1 end

else {x  Max()}

if x = z then y := y + 1 else {ничего}

end {while} {f() & z = Max()}

Обобщая этот пример, введем понятие индуктивного расширения.

Определение. Функция F:  Y называется индуктивным расширением функции f:  Yf, если

1) Fиндуктивна,

2) h Yf , такая, что для всех : f() = h(F()).

Условие 2 означает, что, зная F(), можно получить f().
3.5. Примеры задач с индуктивными функциями
Пример 1. Вычисление значения полинома, заданного последовательностью коэффициентов по убывающим степеням.

Пусть  x1 x2 … xn  1 xn  и p(; t) = x1 n  1 x2 t n  2 + ... + xn  1 t + xn.

Рассмотрим f() = p(; t), тогда

f(*x) = x1 n x2 n  1 + ... + xn  1 t2 + xn t + x =

= f() t + x. (3.1)

Из f(1) = x1 = f() t + x1 следует f() = 0 для всех t.

Эти соотношения лежат в основе следующей программы вычисления значения полинома (t задано).

Эту программу естественно назвать схемой Горнера.

Reset(fin); y :=0; {f()=0}

while not Eof(findo

begin

Read(finx);

y := y*t + x

end {while} {y = p(; t)}

Простым и показательным примером практического использования данной вычислительной схемы является чтение натурального числа z, представленного в текстовом файле записью в позиционной системе счисления с основанием q (2  q  qmax), т. е. z = <x1 x2 ... xn  1 xn>q , где xi  0..(q  1) для i  1..n  и x1  0. Очевидно, что z = x1 n  1 x2 q n  2 + ... + xn  1 q + xn и может быть вычислено по схеме Горнера:

const q = 3; {2  q  10}

var x: Char; z: Integer; y: Word; fin: Text;

begin

Assign(fin, 'Number.dat'); Reset(fin); y :=0;

while not Eof(findo

begin

Read(finx);

z := Ord(x)  48;

y := y*q + z

end {while};

WriteLn('прочитано число = ', y)

end.

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

Можно рассмотреть f1() = pt(; t)  как новую функцию и попытаться для неё решить задачу заново, а можно поступить иначе  продифференцировать по t уже полученное рекуррентное соотношение (3.1):

[f(*x)]t = [f()]t t + f(),

т. е. f1(*x) = f1() t + f(). Функция f1 неиндуктивна, и следует рассмотреть индуктивное расширение F() = (f1() , f()):

F(*x) = ( f1() t + f(), f() t + x).

Из соотношений f1(1) = [x1]t = 0 = f1(0t + f(0) = f1() t + 0 для всех t  R следует f1() = 0. Тогда для вычисления F() имеем программу

Reset(fin);

y := 0; {f() = 0} y1 := 0; {f1() = 0}

while not Eof(findo

begin

Read(finx);

y1:= y1*t + y;

y := y*t + x

end {while} {f() & y1= f1()}

Полученную программу можно назвать схемой Горнера для вычисления значения производной многочлена.

Пример 3. Вычисление максимальной длины равнины (площадки) в заданной последовательности. Пусть задана последовательность  x1 x2 … xn  1 xn . Площадкой длины k называется отрезок (связная подпоследовательность) равных элементов, т. е. xi = x+ 1 = … = xi +  1 (при этом либо i = 1, либо xi 1  xi  , а также либо xi +  1 xi + k, либо i k  1 = n). Функция f = «длина самой длинной площадки в » неиндуктивна. Чтобы показать это, воспользуемся критерием индуктивности. Действительно, пусть

 = (1, 1),  = (2, 2), f() = 2, f() = 2.

При x = 1 получим f(*x) = 3 и f(*x) = 2, т. е. f(*x)  f(*x) , и, следовательно, f  неиндуктивна.

Рассмотрим индуктивное расширение:

F() = ( f(), last(), конкурент()),

где last()  последний элемент последовательности, а конкурент()  длина хвостовой площадки (только площадка, заканчивающаяся последним элементом, может конкурировать с текущим рекордом f()).

Запишем рекуррентные (индуктивные) соотношения:

f(*x) = max(f(), конкурент(*x)),

 конкурент() + 1, если x = last(),

конкурент(*x) =  

 1, если x  last(),

last(*x) = x.

Все эти функции на пустой последовательности  можно доопределить согласованно с индуктивными соотношениями:

f() = 0, конкурент() = 0, last() = 0.

Тогда получаем программу

Reset(fin);

y := 0; {f() = 0}

z := 0; {z  конкурент, z() = 0}

last :=0; {last()  любой}

while not Eof(findo

begin

Read(finx);

if   x = last  then z := z + 1

else  z := 1;

if z > y then y := z;

last := x

end {while}

Пример 4. Вычисление максимальной суммы элементов среди всех отрезков последовательности. Пусть задана последовательность  x1 x2 … xn  1 xn . Требуется вычислить

f() = «сумма элементов отрезка с максимальной суммой»,

где отрезок  связная подпоследовательность последовательности .

Пусть S(km) =  ik..m xi, где 1  k  m  n. Тогда

f() = max(S(km): 1  k  m  n).

Функция f – неиндуктивна. Действительно, по критерию индуктивности: пусть  = (5, 1),  = (1, 5), f() = 5, f() = 5, но при x = 1 получим f(*x) = 5 и f(*x) = 6, т. е. f(*x)  f(*x), и, следовательно, f  неиндуктивна.

Рассмотрим индуктивное расширение F() = ( f(), t()), где роль потенциального конкурента текущему рекорду f() при продолжении последовательности  играет t()  максимальная сумма среди отрезков, прилегающих к правому концу последовательности, т. е. t() = max(S(jn): 1  j  n).

Вычисление f и t можно проводить следующим образом:

f(*x) = max(f(), t(*x)),

t(*x) = max(xx + t()),

t() = 0, f() =  .

В результате получим программу

const MinInt = 32768; {}

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

y, { f() }

z: Integer; { t() }

fin: Text; { input file}

begin ...

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

y := MinInt; z := 0; { f(), t() }

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

{ bound: length(R(fin)) }

while not Eof(findo

begin

Read( fin, x );

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

if z > y then { обновить рекорд } y := z;

end { while }…

end.