lecture11.ppt
- Количество слайдов: 35
27. 11. 13 Лекция 11 Предикатное программирование 8. Язык, технология и методы верификации других классов программ (прод. ) Класс простых процессов. Примеры. Гадание на кофейных зернах. Электронные часы с будильником Классы реактивных и распределенных систем Языковые средства Параллельная композиция Интерливинговая развертка параллельной композиции Коммуникационные протоколы Протокол рукопожатия
Классы программ 1. Программы-функции (преобразователи) Предикатное программирование Задачи дискретной и вычислительной математики 2. Программы-процессы -- класс программ, для которого применяется Автоматное программирование ……. Языковые процессоры, Операционные системы Объектно-ориентированное расширение классов Параллелизм Разные классы требуют разных методов и технологий !
8. Язык, технология и методы верификации других классов программ (прод). 8. 2. Простые процессы 8. 3. Реактивные и распределенные системы
Автоматное программирование Программа в виде конечного автомата Сегменты кода: Состояния: login: if (exist(get_string())) goto passw login else goto login passw: if (right(get_string())) goto session else goto passw session: <сегмент кода 3> goto login session
программа-функция программа-процесс Программу-функцию можно перестроить таким образом, чтобы все операторы ввода данных находились в начале программы, а весь вывод собран в конце программы Программа-функция обязана всегда завершаться Подклассы программ-процессов: последовательное параллельное исполнение гибридные системы временные автоматы недетерминизм вероятностный автомат реактивные системы распределенные системы встроенные системы реального времени Технология автоматного программирования должна интегрироваться с технологиями других классов программ!
Системы автоматного программирования 1. Графический язык Дракон (НПЦ автоматики и приборостроения, ракетно-космическая отрасль). Эргономические методы. 2. Автоматное программирование, А. Шалыто. switch-технология 3. Рефлекс (Институт автоматики, Новосибирск) 4. SDL 5. UML 6. Стандарт IEC 61131 -3 для программируемых логических контроллеров Понимание автоматных программ – ключевая проблема Эргономичность Визуализация
Автоматная программа – машина конечных состояний в виде гиперграфа Программа состоит из нескольких сегментов кода. Сегмент – имеет структуру гиперфункции i 1 гиперфункция i 4 i 2 i 3 Гипердуга конечного автомата Упростить сегменты автоматной программы!
Подкласс процессов Системы автоматического управления
Языковые средства описания процесса prоcess <имя программы>(<описания аргументов и результатов>) pre <предусловие> { <описания переменных состояния процесса> <сегменты кода> } <оператор приема сообщений>: : = receive <имя сообщения>(<параметры>) <оператор> | receive <имя сообщения> (<параметры>){ <оператор> } else <оператор приема сообщений> Сегмент кода: <имя управляющего состояния>: inv <инвариант> <оператор> Оператор перехода: #<имя управляющего состояния>
Декомпозиция процессов Утверждение. Любой алгоритм можно декомпозировать введением всего лишь одного внутреннего состояния Декомпозиция бесконечного процесса с одним внутренним управляющим состоянием: start A next B process A(X x: Y y); // предварительное определение процесса A process B(X x, Y y: Y y’); // предварительное определение процесса B process C(X x: ) { start: next: } A(x: Y y) #next B(x, y: Y y’) #next
Декомпозиция с одним внутренним состоянием: stop start A next B stop start А B next stop start A next B start А B next
stop start А B next process A(X x: Y y #next : Z z #stop); // предварительное определение процесса A process B(X x, Y y: Y y’ #next : Z z #stop); // предварительное определение процесса B process G(X x: Z z #stop) { start: A(x: Y y #next : z #stop); next: B(x, y: Y y’ #next : z #stop) }
Декомпозиция без внутренних состояний: stop next B process B(X x, Y y: Y y’ #next : Z z #stop); // предварительное определение процесса B process H(X x, Y y: Z z #stop); { next: B(x, y: Y y’ #next : Z z #stop) }
Пример 1. Гадание на кофейных зернах Зерна: черные и белые b — число черных зерен, w — число белых зерен process Гадание(nat b, w: #black : #white) pre b + w 0; post black: b’=1 & w’=0 post white: b’=0 & w’=1; type CHOICE = enum (black_black, white_white, black_white); Взять. Пару. Зерен(nat b, w: CHOICE c) pre b + w > 1; post (b < 2 c black_black) & (w < 2 c white_white) & недетерминированность (b = 0 w = 0 c black_white);
process Гадание(nat b, w: #black : #white) pre b + w 0 { step: invariant b+ w 1; if (b = 1 & w = 0) #black else if (b = 0 & w = 1) #white else Шаг(b, w: nat b’, w’); #step } post black: b’=1 & w’=0 post white: b’=0 & w’=1; black step white Задача верификации: инвариант остается истинным после прохождения очередного витка. pre b + w 1 & (b = 1 & w = 0) & (b = 0 & w = 1) Шаг(b, w: nat b’, w’) post b’ + w’ 1;
process Шаг(nat b, w: nat b’, w’) pre b + w > 1 { switch (Взять. Пару. Зерен(b, w)) { case black_black: b’ = b - 1 || w’ = w case white_white: b’ = b + 1 || w’ = w – 2 case black_white: b’ = b - 1 || w’ = w } } post b’ >= 0 & w’ >= 0 & b’ + w’ >= 1; Дополнительное свойство на переменных состояния процесса: (b‘ = b - 1 or b‘ = b + 1) & (w‘ = w or w‘ = w – 2) Процесс всегда завершается. Мера на состоянии процесса: nat m(nat b, w) = b + w; m(b’, w’) = m(b, w) -1;
process Гадание(nat b, w: #black : #white) pre b + w 0 pre black: even(w); pre white: even(w);
Электронные часы с будильником – H – увеличивает на единицу число часов – M – увеличивает на единицу число минут – A – включает и выключает настройку «будильник» Три управляющих состояния часов: без будильника (off), включение будильника (set), включенный будильник (on)
class Часы { nat hours, minutes; // текущее время (часы, минуты) nat alarm_hours, alarm_minutes; // время срабатывания будильника inc_h(); {. . . } // увеличить время на один час inc_m(); {. . . } // увеличить время на одну минуту inc_alarm_h(); {. . . } // увеличить время будильника на час inc_alarm_m(); {. . . } // увеличить время будильника на минуту tick() {. . . } // приращение времени на тик – минимальный интервал bell_on() {. . . } // Включить звонок bell_off() {. . . } // Выключить звонок bool bell_limit() {. . . }; // звонок звонит уже минуту }
process Работа_часов_с_будильником { Часы t = Часы(); off: receive H { t. inc_h() #off } else receive M { t. inc_m() #off } else receive A #set else tick() #off set: receive H { t. inc_alarm_h() #set } else receive M { t. inc_alarm_m() #set } else receive A { t. bell_on() #on } else tick() #set on: receive H { t. inc_h() #on } else receive M { t. inc_m() #on } else receive A { t. bell_off() #off } else { tick(); if (t. bell_limit()) { t. bell_off() #off } else #on } } инварианты не нужны (равны true)
process Работа_часов_с_будильником { Часы t = Часы(); type State = enum(off, set, on); State state = off; while (true) switch (state) { case off: receive H { t. inc_h() } else receive M { t. inc_m() } else receive A { state = set } else { tick()} case set: receive H { t. inc_alarm_h() } else receive M { t. inc_alarm_m() } else receive A { t. bell_on(); state = on } else { tick() } case on: receive H { t. inc_h() } else receive M { t. inc_m() } else receive A { t. bell_off(); state = off } else { tick(); if (t. bell_limit()) { t. bell_off(); state = off } } }} Версия программы по switch-технологии А. Шалыто
Реактивные и распределенные системы Язык. База – язык простых процессов. Дополнительно Параллельная композиция простых процессов F || G Разделяемые переменные доступны для двух или более параллельных процессов Защищенный оператор with (<список разделяемых переменных>) {<оператор>} Операторы посылки и приема сообщений Сообщение используется для передачи информации между взаимодействующими процессами message <имя сообщения>(<типы параметров>) send m(e), считаются защищенными receive m(x) { B } else C
Сообщения Виды сообщений блокировка остановка процесса, посылающего (принимающего) сообщение блокированные / неблокированные прием / передача синхронный / асинхронный обмен рандеву блокированные прием и передача, синхронный обмен каналы ограниченные, неограниченные
Erlang, Bjarne Däcker, http: //www. erlang. org/ Ericsson <сообщение> : : = … receive <имя сообщения>(<список переменных>) receive { <сообщение 1>: <оператор1> case <сообщение 2>: <оператор2> … case <сообщение. N>: <оператор. N> after <время ожидания>: <оператор. N+1> } if (<сообщение>) … неблокированный прием главный процесс содержит очередь сообщений каналы, порты
Параллельная композиция Простой процесс F (или G) в параллельной композиции F || G представлен в виде автомата – гиперграфа действий. Действие – фрагмент процесса без циклов, соответствующий гипердуге (гиперфункция). Разные концы гипердуги соответствуют разным вершинам автомата. Для каждого действия можно построить логику. Канал A – список (очередь) сообщений L(“send m(e)”) ≅ A’= append(A, e) L(“receive m(x) C else D”)≅ if (A≠nil) x=A. car ∧ A'=A. cdr ∧ L(C) else L(D) Нет конфликтов между параллельно исполняемыми действиями разных процессов. Параллельная композиция a || b действий a и b из разных процессов линеаризуется в виде a; b или b; a. Параллельное исполнение F || G может быть представлено последовательным в виде интерливинга (interleaving - перемешивания) действий.
гранулированность Трасса – это последовательность действий на некотором пути в графе действий. Исполнение простого процесса – исполнение последовательности действий некоторой трассы. Трасса параллельной композиции F || G образуется перемешиванием трасс для F и G. Логика трассы c 1, c 2, …, cn есть L(c 1) & L(c 2)&…&L(cn). Трасса достижима, если ее логика не равна false
Спецификация параллельной композиции F || G в виде интерливинговой развертки – автомата инвариантов. a | b – недетерминированный выбор: либо a, либо b. Гипердуга спецификации имеет вид: m: invariant” <инвариант>; // p. F = “a” & p. G = “b” a(cond 1 #m 1: cond 2 #m 2) | b(cond 3 #m 3: cond 4 #m 4: …) • Развертка должна быть полной. • Гипертройка: <инвариант>{a(cond 1 #m 1: cond 2 #m 2) } m 1: <инвариантm 1 >, m 2: <инвариантm 2> программа, представленная гипертройкой, должна быть корректной.
Коммуникационные протоколы Протокол стандарт, определяющий взаимодействие двух или более объектов (узлов) соединение, аутентификацию, кодирование и передачу данных, … Коммуникационный протокол – стандарт, определяющий правила передачи информации между двумя удаленными узлами a ввод A a передача B a вывод
ввод Канал данных Отправитель Получатель вывод Канал ответов Рис. Схема взаимодействия отправителя и получателя
Протокол n-ABP модификация протокола чередования битов (Alternating Bit Protocol) process n. ABP( ) { Отправитель() || Получатель() } int timeout; // время ожидания в миллисекундах process Отправитель() { int прочитано = 0; //номер текущего блока read: receive ввод(Data блок); прочитано’ = прочитано + 1; send: send Данные(блок, контрольная. Сумма(блок)), прочитано); receive { ОК(int номер): if (номер прочитано) #send else #read after timeout: #send } } process Получатель() { int записано = 0; loop: receive Данные(Data блок, int сумма, int номер); if ( посчитать. Сумму(блок) сумма ) #loop else { send OK(номер); if ( номер записано+1 ) #loop else #write } write: вывод(блок); записано’ : = записано + 1; #loop }
Протокол скользящего окна Блоки посылаются друг за другом без ожидания подтверждения с записью в окно. Если требуется повторить передачу, этот блок берется из окна. Число блоков, посылаемых в текущий момент, регулируется размером окна. Заводится таймер на каждый блок окно - круговой буфер блоков
Протокол рукопожатия s u a S b M 1 M 2 c R r d Передатчик S Приемник R Ненадежные каналы потеря сообщений Медиумы M 1, M 2 process GS { S || M 1 || R || M 2 } spec GS = s? r! u! Протокол
Протокол рукопожатия message a, b bool sa, sb Указатели текущего исполняемого действия: pc. S=s, pc. R=r list ({a}) qa = nil; list ({b}) qb = nil; process S(: #exit) { s: if (b) #exit if (sa) send a; #s } process R() { r: receive(a); if (sb) send b; #r } process Hand. Shake(: #exit) { S(: #exit) || R(: ) } состояние: ( qa, qb, sa, sb) начальное состояние qa=nil; qb=nil
process S(: #exit) { process R() { s: if (b) #exit r: receive(a); if (sa) send a; #s if (sb) send b; #r } } process SR() { //qa = [a+] эквивалентно qa != nil a 0: inv (qa, qb) = (nil, nil); s(sa: #a 1: sa #a 0) a 1: inv ([a+], nil); s #a 1 | r (sb & qa’=nil #a 2: sb & qa’!=nil #a 3 : sb & qa’=nil #a 0: sb & qa’!=nil #a 1) a 2: inv (nil, [b+]); s #exit | r (qa’=nil #a 2: qa’!=nil #a 3) a 3: inv ([a+], [b+]); s #exit | r (qa’=nil #a 2: qa’!=nil #a 3) } Учитывая, что действия a 2 и a 3 одинаковые, их можно объединить в одно: a 2: inv qb != nil; s #exit | r # a 2
[nil, nil] [a+, nil] [a*, b+] exit


