Автор Тема: Инварианты к двум циклам  (Прочитано 35449 раз)

DIzer

  • Гость
Re: Инварианты к двум циклам
« Ответ #90 : Сентябрь 28, 2012, 05:33:10 pm »
Но я хочу сказать всего лишь: "Циклы разные нужны, циклы разные важны".
 При их конструировании нужно учитывать множество факторов, и уже исходя из их оценки выбирать тот или иной подход. Ни один из подходов не является "православным", "кошерным",  "единственно возможным" и "истинно правильным". Это просто подход, и ничего более...
Так то оно так, но пока есть ЦЕНА ошибки...  интерес к методам позволяющим уменьшить их вероятность будет наблюдаться (в этом смысле  Петр может не беспокоится о "популярности" подобных топиков  :)  ). Ну а если он является фаном "метода инвариантов" - то возможно он когда нибудь  и предложит конкурентноспособную  методу (хотя бы для ОПРЕДЕЛЕННОГО класса задач...)

Peter Almazov

  • Sr. Member
  • ****
  • Сообщений: 482
    • Просмотр профиля
Re: Инварианты к двум циклам
« Ответ #91 : Сентябрь 29, 2012, 03:28:02 am »
Приверженцам десятиэтажных охран  и семиэтажных проверок после цикла предлагаю по такому принципу даже не 10 этажей покрасить, а всего лишь один забор. Тогда наступает понимание, что если у нас над циклом 10 этажей условий, то мы неверно построили алгоритм и необходимо повторно провести декомпозицию...
Kemet, чем писать всякие фантазии про 10 этажей (почему не 20, кстати?), приводите примеры.
То же относится к Dizer'у.

DIzer

  • Гость
Re: Инварианты к двум циклам
« Ответ #92 : Сентябрь 29, 2012, 06:14:06 am »
То же относится к Dizer'у.
А причем тут Dizer  - эту  кашу заварили вы... заварив  ее - нормально не ответили ни на один вопрос.. а все ваши ремарки - напоминают мне реакцию школоты решившего по учебнику
пару задач, вообразившего себя богом, поучающего других - причем, с большей степенью апломба... и какие тут фантацизии  :D  -  для подтверждения вышесказанного вполне ДОСТАТОЧНО собрать вместе ВСЕ ваши высказывания в этом топике  :D

qp

  • Newbie
  • *
  • Сообщений: 28
    • Просмотр профиля
Re: Инварианты к двум циклам
« Ответ #93 : Сентябрь 29, 2012, 11:31:05 am »
Цитировать
Инвариант для цикла в последнем решении Александр Шостак: в переменной ChainLen лежит длина хвоста просмотренной области, состоящего из нулей.
А моя ошибка вот в чем: инвариант для решения  Александр Шостак не полон. Ниоткуда не следует, что найденный кусок будет первым от начала массива. Я заметил, да было уже поздно. Желающие могут попробовать сформулировать недостающую часть.
Какой-то неказистый инвариант получается для решения Александра Шостака. Поскольку в отличие от решения info21 цикл не завершается при "заглядывании вперед", то инвариант должен звучать как-то так:

в просмотренной на предпоследней итерации области нет последовательности CHAIN_LEN нулей и  в переменной ChainLen лежит длина хвоста просмотренной на последней итерации области, состоящего из нулей.

Или есть более элегантные варианты?

Peter Almazov

  • Sr. Member
  • ****
  • Сообщений: 482
    • Просмотр профиля
Re: Инварианты к двум циклам
« Ответ #94 : Сентябрь 29, 2012, 05:43:52 pm »
Я так сформулировал: в обработанной :) области содержится не более одного куска нулей длиной CHAIN_LEN и  в переменной ChainLen лежит длина хвоста просмотренной области, состоящего из нулей.


Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: Инварианты к двум циклам
« Ответ #95 : Сентябрь 29, 2012, 07:56:49 pm »
Я предпочитаю не увлекаться формализмом, использовать оправдавшие себя шаблоны вроде линейного поиска, но всё же попробую по шагам в википедии доказать вариант инварианта:

Подготовка:

CONST
  CHAIN_LEN   = 2;
  CHAIN_BYTE  = 0;

ChainLen  := 0;
i         := 0;

WHILE (i < LEN(a)) & (ChainLen < CHAIN_LEN) DO
  IF a[i] = CHAIN_BYTE THEN
    INC(ChainLen);
  ELSE
    ChainLen := 0;
  END;

 INC(i);
END;

GetChainLen - вспомогательная функция, принимающая подмассив и возвращающая длину непрерывной цепочки нулей в нём от конца к началу. Несуществующие индексы игнорируются.

Инвариант:

i         <= LEN(a)     // Из заголовка цикла
ChainLen  <= CHAIN_LEN  // Из заголовка цикла
GetChainLen(a[i - 2.. i - 1]) = ChainLen

Цитировать
1. Доказывается, что выражение инварианта истинно перед началом цикла.
Минимальная длина массива - 0. Максимальная: > 0. i = 0. i <= LEN(a).
ChainLen = 0. CHAIN_LEN = 2. 0 <= 2.
GetChainLen(a[-2..-1]) = 0. 0 <= 2.

Цитировать
2. Доказывается, что выражение инварианта сохраняет свою истинность после выполнения тела цикла; таким образом, по индукции, доказывается, что по завершении цикла инвариант будет выполняться.
Переменная i увеличивается на 1 безусловно. Первая часть охраны цикла останавливает повторы при i = LEN(a). Следовательно, i <= LEN(a) верно после каждой итерации.

Переменная ChainLen может расти вверх максимум на 1 за каждую итерацию. Вторая часть охраны цикла гарантирует равенство ChainLen <= CHAIN_LEN. Скачок с 0 до 3 таким образом невозможен.

Если текущий символ не нулевой, то ChainLen обнуляется. GetChainLen анализирует длину цепочки с хвоста и тоже вернёт 0.
Если текущий символ нулевой, то ChainLen растёт на единицу. Точно также поступает при анализе длины и GetChainLen.
Переменная i в конце итерации указывает на следующий за текущим символ. Следовательно,
GetChainLen(a[i - 2.. i - 1]) = ChainLen выполняется.

Цитировать
3. Доказывается, что при истинности инварианта после завершения цикла переменные примут именно те значения, которые требуется получить (это элементарно определяется из выражения инварианта и известных конечных значениях переменных, на которых основывается условие завершения цикла).
Хотим получить ChainLen = 2 при успехе. Тогда i - 2 есть начало цепочки. При неудаче ChainLen < 2, а i = LEN(a).

Цитировать
4. Доказывается (возможно — без применения инварианта), что цикл завершится, то есть условие завершения рано или поздно будет выполнено.
Безусловное увеличение i на 1 после каждой итерации при положительной длине массива гарантирует конечное время выполнения и завершение. Вторая охрана цикла (ChainLen < CHAIN_LEN) гарантирует выход, когда цепочка наберёт критическую длину.

Цитировать
5. Истинность утверждений, доказанных на предыдущих этапах, однозначно свидетельствует о том, что цикл выполнится за конечное время и даст желаемый результат.
Аминь.

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

qp

  • Newbie
  • *
  • Сообщений: 28
    • Просмотр профиля
Re: Инварианты к двум циклам
« Ответ #96 : Сентябрь 30, 2012, 05:20:31 pm »
Я так сформулировал: в обработанной :) области содержится не более одного куска нулей длиной CHAIN_LEN и  в переменной ChainLen лежит длина хвоста просмотренной области, состоящего из нулей.
Да, так пожалуй лучше.