DRAKON.SU

Текущее время: Среда, 17 Апрель, 2024 01:16

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 188 ]  На страницу Пред.  1, 2, 3, 4, 5, 6 ... 10  След.
Автор Сообщение
СообщениеДобавлено: Пятница, 25 Май, 2018 19:31 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Но тут такое дело: если стрелка всё-таки есть, то yield иконку логично рисовать на самой стрелке. Так понятнее, что возврат управления происходит не "до вопроса", а "на самой стрелке, т.е. в случае неудачного значения". При этом будет и симметрия между "циклом, с паузами в n секунд и yield-циклом"

Т.е., примерно так ("ожидать 0 сек"):
viewtopic.php?f=78&t=6068&start=40#p100412

Однако, имеется и такое дело. Если говорить о каких-то автоматных подходах, то следует отметить, что автоматы, как правило, "добычей" своих входных данных не занимаются, они "реагируют" на вход, когда об этом попросит "хозяин". Т.е. для операции "ожидания", всё-таки, не должно быть каких-то стрелок "ожидающего цикла", такой некий условный цикл есть внешний по отношению к алгоритму. В таком случае будет совместимость с формальными теориями и прочими методиками, и автоматы (или процессы с событиями) могут быть выражены в разных формах, где Дракон-схемы являются лишь одним из вариантов представления.
Если в рамках универсального способа выражения "ожидания" можно обойтись без обратных стрелок, то тогда будет удовлетворён и частный случай политики ожидания события: сначала проверяем условие и в случае неуспеха можно перекурить до следующей попытки (для тех случаев, когда о каких-то там автоматах толком и не говорят).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 25 Май, 2018 19:38 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Всё-таки, впечатление, что методика Зюбина для блок-схем (в том числе) адекватно адаптирована для выражения "автоматных" процессов, как раз в "максимально императивном" стиле, что характерно для блок-схем (к примеру, методика Esterel/Lustre/Signal более продвинутая и "по-высокоуровневее", но для графических представлений необходимы специализированные диаграммы или Р-схемы, у блок-схем и Дракон-а "напряжёнка" с выражением блоков и структур).

Ещё одна попытка отразить "автоматный" силуэт по мотивам результатов Зюбина:
Вложение:
process2.png
process2.png [ 51.97 КБ | Просмотров: 7262 ]

Здесь "автоматный" процесс имеет несколько "функций-состояний", исполнение начинается с "Подготовка". Внутри этого состояния есть ожидание "условия 1". Это безальтернативное ожидание, которое возможно в любом алгоритмическом месте. В случае потребности альтернатив ожидания необходимо использовать "автоматный силуэт". Состояние "Работа" имеет несколько "веток", где каждая должна начинаться с "ожидания". Если ветка "заканчивается" (выполняется "вход" по маршруту в нижнюю линию силуэта) без овала-"перехода", то нет переключения в иное "состояние".
В "силуэте" целенаправленно нет "классических" заголовков веток и адресов перехода, чтобы не было никакой каши. Как и у Зюбина, такие схемы выражают "процессы" с "логикой верхнего уровня" (аля автоматные спецификации в виде таблиц в стиле "состояние + событие + реакция + переход"). Если внутри "веток" возникает потребность, к примеру, ликвидировать пересечение линий (скажем, из-за возникающих внутренних условий при обработке события), то необходимо действия с условиями оформлять отдельно в виде своей схемы (с обычным силуэтом как для вычислительного алгоритма) и выполнять "вставку".

"Ожидающие вопросы" не имеют обратных стрелок и альтернативной ветки без потребности. Для композиции условий используется "ожидающая группа".
Иконка "ожидание", прикрученная к "Таймер 1", означает срабатывание таймера, который где-то был ранее "взведён" такой же иконой "установка таймера", но без "кружочка со стрелкой".
Икона "пауза" с "ожиданием" означает таймаут (с отчётом от начала ожидания).
Иконку "ожидание", по-видимому, можно прикрутить и для икон ввода/вывода.


Если я не ошибаюсь, то метод Ашкрофта-Манны служил нечто вроде основой для "математических" обоснований имеющейся конструкции "силуэт". В результатах Зюбина, вроде как, также прослеживается некая "математика" для обоснования "автоматного" силуэта, может быть чем-то можно воспользоваться.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 26 Май, 2018 18:31 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
Т.е., примерно так ("ожидать 0 сек"):

Да (про местоположение иконки)



PSV100 писал(а):
Однако, имеется и такое дело. Если говорить о каких-то автоматных подходах, то следует отметить, что автоматы, как правило, "добычей" своих входных данных не занимаются


Я бы различал 'автомат ради автомата' и 'решение практической задачи'. Первое мне не интересно.

Простой пример: 'пауза 2 секунды' в общей последовательности действий это 'добыча данных самим алгоритмом'? По-моему, да. Означает ли это, что нужно всячески пытаться уйти от подобных конструкций и заменять их на отдельную ветку, 'запускаемую' отдельным таймером? Нет, конечно.

Я не вижу ничего плохого в том, чтобы обработку длинных вычислений разбивать yield'ами (особенно в рамках кооперативной многозадачности).


Ещё нерешённая задача - композиция автоматов. Условно говоря, кое как придумали yield, но ещё нужен способ, чтобы одна Дракон схема управляла другой.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Воскресенье, 27 Май, 2018 23:14 

Зарегистрирован: Воскресенье, 09 Март, 2008 22:38
Сообщения: 341
Ребята, какая у вас здесь интересная дискуссия идет...

PSV100 прав. У автомата Мили в некотором смысле "пассивная природа", переход из состояния в состояние связан с поступлением входящего сигнала. В этом смысле ветка силуэта Дракона не является состоянием - она по умолчанию ничего не ждет, запускается и производит выполнение цепочки действий.

Кстати, простые конечные автоматы не подходят для адекватного отображения реальных управляющих систем. В силу отсутствия в них временных шкал и таймеров. Можно использовать временные автоматы и временные сети Петри. Но они опять же основаны на концепции состояний.

Посмотрите, кстати, мое сообщение здесь на форуме по адаптивным расписаниям как семантике управляющих алгоритмов реального времени.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Май, 2018 19:43 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Простой пример: 'пауза 2 секунды' в общей последовательности действий это 'добыча данных самим алгоритмом'? По-моему, да. Означает ли это, что нужно всячески пытаться уйти от подобных конструкций и заменять их на отдельную ветку, 'запускаемую' отдельным таймером? Нет, конечно.

Ранее в теме был пример насчёт светофора:
https://forum.drakon.su/viewtopic.php?f=176&t=6221#p101364
Вложение:
zak-svet.png
zak-svet.png [ 23.54 КБ | Просмотров: 7179 ]

Вложение:
20180225160011.png
20180225160011.png [ 145.47 КБ | Просмотров: 7179 ]

У Закревского на графах (принцип построения графов соответствует правилам для его формул процессов) действия обозначаются квадратиками (как в блок-схемах), ожидание -- кружочками, и возникающие события указываются на дугах из вершин-ожиданий. В начале после события "ожидание 60 сек" фактически происходит проверка всех значений переменной "х" (нет явного ожидания поскольку отражены все возможные альтернативы), а перед "ЖК" ожидается, когда "х" станет валидным. Однако не раскрывается как именно выполняется это ожидание, ожидание есть "высокоуровневая" операция. В каких-то случаях моделирования с учётом конкретики "абстрактное" ожидание заменяется, к примеру, "ожидающим циклом" с определенным периодом.

А в общем случае для моделирования необходимо на борту иметь и абстрактное ожидание. Семантику как у Закревского несложно повторить в Р-схемах. В Дракон-е же есть потребность соблюдать "метафоры" (операции на таймерах -- один стиль икон, "вопросы" и "выборы" -- иной набор икон, ввод/вывод -- ещё один и т.д.). И те же "вопросы" всегда имеют две ветки результатов (да/нет), по-Драконовски рекомендуется единое сложное условие (если возникает) заменять на композицию "вопросов", в итоге точка ожидания "растягивается" по схеме.

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

Аналог "ожидающего цикла" как некий "цикл-событие" менее "радикален" в качестве универсального варианта "ожидания":
Вложение:
await_cycle.png
await_cycle.png [ 11.04 КБ | Просмотров: 7179 ]

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

Однако, в каких-то случаях, даже если "добычей" события занимается "активный" процесс, объекты для событий могут не иметь операций вида "теста текущей валидности" или "опроса значений". Т.е. обращение к объекту для выявления событий предполагает только лишь конкретное "ожидание" (с возможной блокировкой) вида "await x" (что также актуально и для случаев дискретно-непрерывной семантики системы или аля "гибридных" автоматов). В таких случаях наличие маршрутов в "цикле-событие" (а также и тест условия в самом начале акта возможного ожидания) вносит неоднозначность, даже при использовании одной иконы "вопрос". По-видимому, тогда есть потребность в каких-то особых соглашениях, и такой цикл необходимо интерпретировать комплексно в виде единой макроиконы в качестве условно неделимой операции "ожидание", подкрепляя правилами для валидных точек присоединения икон, мол на обратных стрелках не должно быть ничего кроме "паузы-ожидания", и т.п.

У меня нет однозначного предложения для единого способа выражения событий. В каждом рассмотренном варианте есть недостатки.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Май, 2018 19:49 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Я бы различал 'автомат ради автомата' и 'решение практической задачи'. Первое мне не интересно.

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

Ранее был примерчик автоматной спецификации интерфейса класса (объекта) для работы с файлами:
https://forum.drakon.su/viewtopic.php?f=142&t=6246#p101640
Код:
class File
  [RAW -> READY]
  open(fname, attr);
  create(fname, attr);

  [READY]
  read(data);
  write(data);

  [READY -> RAW]
  close();
end;

Можем локализовать сам автомат, идентифицируя состояния через операции для расписаний (или "scheduling policy"), в некотором смысле идентично "адаптивным расписаниям" выше в теме, но без количественных оценок времени:
Код:
automaton
| init RAW => (open | create) -> READY
| READY => ((read* || write*) | (close -> RAW))
end;

, где состояние RAW есть начальное, "(open | create)" -- либо операция open, либо create (несовместимость во времени), "->" -- следование, "||" -- параллельная композиция как произвольное исполнение методов в любом порядке, "*" -- исполнение от нуля и более раз (как в регулярных выражениях).

Вариация на интервальных событиях:
Код:
automaton
| init RAW => (close in READY) to (open | create)
| READY => (open in RAW | create in RAW | read* | write*) to close
end;

, где "(e1 to e2)" -- через оператор "to" указывается интервал, в котором событие e1 "включает" состояние, событие e2 "выключает". В рамках начальных событий оператор "in" в выражениях вида "close in READY" указывает на состояние-источник (в конечных событиях необязательно указывать событие-приёмник). Операции без источника, как read, интерпретируются как "внутренние шаги".

В рамках "продвинутых" средств программирования/моделирования возможен учёт ограничений аля:
function some_func(data: File in READY): int {...}

(кроме помощи для составления документации, конечно же, "продвинутость" предполагает и какой-то контроль т.н. "type state" или протоколов в алгоритмах).

В контексте подобных спецификаций для графического представления применять императивные блок-схемы и Дракон, вроде как, семантически некорректно.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Май, 2018 19:55 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Ещё нерешённая задача - композиция автоматов. Условно говоря, кое как придумали yield, но ещё нужен способ, чтобы одна Дракон схема управляла другой.

У Зюбина есть команды запуска/останова процессов, с нормальным завершением и с ошибками и т.д., плюс характерная методика применения, а также понятие "функции-состояния" (вариант работы процесса):
https://forum.drakon.su/viewtopic.php?f=142&t=6246#p101655

Эти же команды по запускам процессов есть и в Дракон-е, вроде как (плюс возможны и переходы в "функции-состояния"). При потребности набор операций с процессами можно расширить, напр., "приостановить" и "возобновить" (продолжить работу с сохранением внутреннего состояния). Для асинхронных процессов (или для всех), т.е. с собственным исполнителем, напрашивается отдельная операция аля "join" (соединение потоков), т.к. завершение таких процессов не мгновенное, в т.ч. и после отмены исполнения. И в случае реальной параллельности доступ к глобальным переменным не такой уж и произвольный (в любом случае напрашивается предметная конкретика в семантике исполнителей, манипулировании общими объектами и т.д.).

Такая форма управления процессами приобретает характер линейности и соответствует некоему "микроуровню". Например, у того же Шалыто "макроуровень" задаётся в виде классических диаграмм состояний, иерархических (вложенных) со своими особенностями (ранее уже была ссылка):
http://is.ifmo.ru/download/switch.pdf

Т.е. макроуровень есть некая обвёртка или свёрнутое представление. Но идентичный функционал имеется и на микроуровне, но в "разорванном" виде, разнесённом по "функциям-состояниям" (в т.ч. возможны, к примеру, и опросы вида "в каком состоянии находится такое-то макросостояние?", что соответствует оценкам состояния процессов по Зюбину).
Для "макроуровня", как возможная альтернатива диаграммам состояний, необходимы алгоритмические конструкции в стиле "reset ... every", "do ... until" здесь (по-своему удобные):
https://forum.drakon.su/viewtopic.php?f=142&t=6246&start=20#p101685

Плюс не помешает политика "интервалов событий" для вкл./выкл. процессов (или разрешение/запрет вычислений) по мотивам примера выше в теме.
Однако, в целом с выделением блоков в Дракон-е непростая ситуация.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Май, 2018 20:00 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Да, и "параллельные действия" есть в арсенале. Причём возможны некоторые упрощения, к примеру:
Код:
var a, b: future int;
...
comp1();
a := async comp2();
b := async comp3();
comp4();
comp5(*a, *b);

На Р-схеме:
Вложение:
defer_var.png
defer_var.png [ 5.72 КБ | Просмотров: 7178 ]

, где выражен типовой паттерн операций "async/await" для вычислительных задач. Оператор "async" запускает асинхронный процесс (параллельное действие со своим исполнителем) и в рамках comp5 выполняется синхронизация. Вместо оператора "await" (который мол может принуждать к отражению на схемах явной операции "ожидание") используется синоним "*" как "разыменование" указателя (объект типа future<тип> и есть объект косвенного доступа).
(Р-схемы несколько гибче для выражения всяких отношений (в том числе и для точек дивергенции/конвергенции потоков, которые в общем случае могут быть в разных местах), чем те же "параллельные линии" в блок-схемах и Дракон-е).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Май, 2018 22:25 

Зарегистрирован: Воскресенье, 09 Март, 2008 22:38
Сообщения: 341
PSV100 писал(а):
"Адаптивные расписания" выше в теме -- также макроуровень во временных разрезах. При потребности, кроме формальной верификации, возможен и синтез программ с генерацией "микроуровня", с автоматической расстановкой по коду (моделям) операций управления процессами, событиями, таймерами и прочими паузами и т.д. (во всяком случае, так декларировалось ранее на форуме)

Совершенно верно!

Приятно,что есть человек, который тебя понимает :)

Увы, даже в среде матерых профессионалов и докторов наук к непониманию привык...

А то, что это - макроуровень, выгодно отличает модель от основанных на состояниях временных автоматов и временных сетей Петри, кои для описания систем промышленного уровня малопригодны вследствие проблемы комбинаторного взрыва числа состояний...

Более того, на макромодели можно уже работать и делать выводы, например, с точки зрения верификации алгоритма, например свойств безопасности.

И еще. Модель подходит для описания самых разных видов деятельности, не только программ для ЭВМ. Это могут быть и организационно-технические системы, включающие персонал и аппаратно-программные комплексы с различными видами работ, требующими правильного согласования во времени и с точки зрения логики (физики процессов).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 30 Май, 2018 01:05 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
Кстати, таки да, автоматы -- они как бы ради себя, вне императивных алгоритмов (на чём акцентировалось ранее в теме), понимая последние как детальные однозначные предписания действий (хотя в целом автоматные спецификации есть также алгоритмы). И автоматная трактовка некоторых императивных алгоритмов есть лишь частный случай применения автоматов.

Ранее был примерчик автоматной спецификации интерфейса класса (объекта) для работы с файлами:

Простите, но пример с файлом едва ли решает какую-то реальную проблему.
Если включаете состояния прямо в класс File, то почему бы не сделать несколько подтипов ReadyFile, RawFile. Понятно, что системы типов разные бывают. Но raw-ready вовсе не выглядит задачей, ради которой нужно за уши притягивать автоматы и высокую науку.

Я бы с файлами другое предложил рассматривать.
Задача: асинхронный вывод в файл. Т.е. нужно файл открыть, записать в него что-нибудь, файл закрыть.
Сложность в том, что "открываться файл может довольно долго". Иными словами, мы каждый цикл подаём управляющую команду "файл, откройся" и он рано или поздно откроется. Точно так же, запись сообщения в файл может сработать несразу.

Код к примеру: http://www.owen.ru/forum/showthread.php ... post259860
Если что, то код "CASE state_res OF" это реальный код, который рекомендуют использовать специалисты ОВЕН.
На мой взгляд, так писать код вручную уж точно не стоит.

Даже при простой записи получается, что императивный подход гораздо понятнее, чем автоматный.

Тут можно заметить, то почти в любой из упомянутых графических схем для этой задачи рисунок совсем простой ("просто" на среду разработки возлагается задача по превращению в автомат): "открываем файл" => "пишем" => "закрываем файл".


Но тут можно рассмотреть вторую задачу: два файла. Из одного читаем, в другой пишем (т.е. копируем данные из одного в другой). Оба файла асинхронные. Это пример задачи, когда "есть одна схема, которая читает файл", есть вторая схема, которая пишет в файл, и нужно сделать третью схему, которая координирует работу первых двух.

Икона "вставка" не решает задачу, т.к. она не отражает ситуации, что у нас по сути 3 автомата, у каждого из которых своё состояние.
Копирующий периодически попинывает читателя и писателя, при этом и читатель и писатель помнят в каком "автоматном состоянии" они находятся, но у копирующего состояние своё. Иными словами, если "yield" иконка означает "вернуть управление в вызывающий код", то нужна дуальная "дать один квант времени на такую-то схему" (выполнить до ближайшей yield точки).

В этом плане мне понравилось как в Kotlin сделали suspending functions.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 31 Май, 2018 19:32 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
PSV100 писал(а):
Кстати, таки да, автоматы -- они как бы ради себя, вне императивных алгоритмов (на чём акцентировалось ранее в теме), понимая последние как детальные однозначные предписания действий (хотя в целом автоматные спецификации есть также алгоритмы). И автоматная трактовка некоторых императивных алгоритмов есть лишь частный случай применения автоматов.

Ранее был примерчик автоматной спецификации интерфейса класса (объекта) для работы с файлами:

Простите, но пример с файлом едва ли решает какую-то реальную проблему.
Если включаете состояния прямо в класс File, то почему бы не сделать несколько подтипов ReadyFile, RawFile. Понятно, что системы типов разные бывают. Но raw-ready вовсе не выглядит задачей, ради которой нужно за уши притягивать автоматы и высокую науку.

Вы как-то буквально воспринимаете. Выше был тезис о том, что автоматные спецификации это прежде всего некий протокол, чем детальный строгий императив (спецификации и таковыми могут быть, конечно же). Пример с File всего лишь демонстрирует способы идентификаций состояний, в данном случае на некоем "макроуровне" (в разрезе одностороннего протокола или протокола над ресурсом), что может пригодиться для согласования взаимодействий.
Владимир Ситников писал(а):
Код к примеру: http://www.owen.ru/forum/showthread.php ... post259860
...
Даже при простой записи получается, что императивный подход гораздо понятнее, чем автоматный.

"Автоматные" алгоритмы разные бывают, удобные под соответствующие задачи, не только в стиле "switch-технологии". К примеру, те же протоколы действий могут быть заданы и императивно, для чего имеются и спецсредства, некоторые собраны здесь:
Session types in programming languages -- a collection of implementations

Выше по ссылке на странице есть в т.ч. и пример на языке Scribble (плюс ссылки на проект) -- "яркий" представитель императива в соответствующей области (для него и блок-схемы применимы). При желании (всё-таки возникает потребность поверхностно взглянуть на описание языков) подобную технику можно сопоставить, скажем, с P Language от Microsoft:
https://www.infoq.com/news/2016/10/microsoft-p-language-opensourced
https://github.com/p-org/P

, где автоматы представляются как "акторы", обменивающимися типизированными сообщениями. Р Language, в отличие от Scribble, полноценный язык программирования/разработки (с генерацией для С/С++ или чего там нужно) с верификацией уже на борту (разработка от модели). Одна из ключевых фишек -- техника "отложенных" сообщений -- автомат при потребности может декларировать на "макроуровне" (что учитывается при верификации) для системы, чтобы такие-то сообщения, которые он пока не может отрабатывать в таких-то состояниях, откладывались на потом, и система будет контролировать, чтобы ничего не было "забыто" и было отработано тогда, когда можно, и пр. (подобные штуковины впихивать в аля Scribble проблематично, как и ряд других техник, хотя возможно, если расширить семантику для учёта смены поведения из-за предыстории действий).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 31 Май, 2018 19:41 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Иными словами, если "yield" иконка означает "вернуть управление в вызывающий код", то нужна дуальная "дать один квант времени на такую-то схему" (выполнить до ближайшей yield точки)

Полезно рассмотреть вариации основных техник кооперативной многозадачности или взаимного исполнения процессов в каком-либо виде (активном и пассивном), даже если при моделировании явно нет речи о какой-то там диспетчеризации процессов. Акцент, прежде всего, на способе выражения операции "ожидание" и "возврат управления" (оставляя за рамками непосредственно возможные предметки, где задача организации операций может иметь явный прикладной характер управления расписанием).

Первый вариант -- как у того же Зюбина, в рамках платформы для контроллеров: упрощённо, в контексте глобального управляющего цикла условный диспетчер перебирает все возможные логические процессы и даёт каждому шанс поработать. И каждый процесс сам решает, готов ли он продолжать трассу исполнения. В таком случае для ожидания возникает "цикл-событие", как выше в теме (мол процесс, фактически, "сам себе доктор"), и возможен произвольный характер условия для акта ожидания, возникает любая композиция условий.
Икона аля "yield" означает возврат управления диспетчеру (мол теперь пусть другие поработают).
Владимир Ситников писал(а):
В этом плане мне понравилось как в Kotlin сделали suspending functions

В техниках как в Kotlin условный полный перебор (потенциально огромного количества) логических процессов не осуществляется, диспетчеризация выполнятся в зависимости от возникновения конкретных событий, к последним есть непосредственная привязка (упрощённый взгляд, в целом возможны и фоновые процессы и т.д.).
Ключевая схема:
result = computation.await()

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

Таким образом, для схем точки ожидания возникают в общем случае в двух формах. С одной стороны, когда вызывается suspend-функция, вроде как, происходит ожидание завершения её работы, т.е. ожидание окончания действия. С другой стороны, с "маршрутной" точки зрения, возникает предикат для дальнейшего прохождения пути. В общем, по-видимому, по вкусу -- отмечать или нет возникающие потенциальные задержки действий и возможные точки переключения контекста. Может быть косвенно при потребности неким способом, как здесь флажки:
https://forum.drakon.su/viewtopic.php?f=78&t=6068&start=40#p100412

В то же время могут быть и ожидания как предикаты:
Код:
suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
    select<Unit> {
        fizz.onReceive { value -> 
            println("fizz -> '$value'")
        }
        buzz.onReceive { value ->
            println("buzz -> '$value'")
        }
    }
}

Если вдруг "переводить" на язык Дракон-схем (ибо "лямбды" вписывать в схемы пока, вроде как, толком нет однозначного решения), то для операций аля "onReceive" напрашиваются какие-то "вопросы"-условия. Причём существует потребность в альтернативном ожидании (как в примере функция "select"). Но сам предикат (для каждого варианта) есть единая операция ожидания -- нет "добывающих себе данных" циклов с маршрутами, "разруливание" события происходит извне (предикат есть нечто вроде "заголовка" в ветке силуэта, или как идентификатор взведённого таймера при использовании "классического синхронизатора").

По-видимому, аналогичную размытость в семантике ожидания (да и в "расписании" совершаемых действий -- размытое семантическое понимание когда и где выполняется работа и реальная передача данных) имеют техники "мониторов" или "критических секций" как в различных методиках "активных объектов" или "задач" в Ada:
https://en.wikibooks.org/wiki/Ada_Programming/Tasking

Однозначно идентифицировать сеть работ (т.е. однозначно определить исполняемые функциональные задачи с передачей "предметов труда") вместе с предикатами маршрутов позволяют техники Esterel 80-х гг., где для императивной событийной формы (в целом формы алгоритмических систем в тех краях есть разные, и очень разные) вместо "лямбды на лямбде" используют разделяемые переменные, что предусматривает в т.ч. и "широковещательные" реакции на события как на "макроуровне" (не только локализованную двустороннюю связь, поставщик данных может не знать потребителей, как и потребители друг друга, все они могут возникать и в динамике).
В качестве примера можно взглянуть на упрощённый проект Céu -- полуакадемическая разработка по мотивам (не все оригинальные техники используются, в чём-то есть и свои перегибы):
http://ceu-lang.org/

(для поверхностного взгляда достаточно видео-демки). Кратко: объекты-автоматы общаются через спецпеременные входа/выхода (input/output), включая и асинхронные процессы. После возникновения входа могут быть внутренние каскады событий (переменные event), после завершения которых может быть оформлен выход. В данном случае используются как раз "дуальные" операции ожидания await и "широковещательной эмиссии" данных emit (при "публикации" данных процесс приостанавливается до тех пор, пока не отработают все связанные по событию внутренние и внешние автоматы). Есть вспомогательные операторы поверх базовых операций, как "every" -- ожидающий цикл. Однако такие операторы как "watching" есть аля наблюдательные спецсекции, которые прерывают исполнение всех вложенных блоков, в т.ч. на произвольной глубине текущего контекста исполнения.
В общем, альтернатива для той же switch-технологии как на "макроуровне".


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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 31 Май, 2018 19:42 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
Вы как-то буквально воспринимаете. Выше был тезис о том, что автоматные спецификации это прежде всего некий протокол, чем детальный строгий императив (спецификации и таковыми могут быть, конечно же). Пример с File всего лишь демонстрирует способы идентификаций состояний, в данном случае на некоем "макроуровне" (в разрезе одностороннего протокола или протокола над ресурсом), что может пригодиться для согласования взаимодействий.


Конечно, буквально. Вы показываете пример с файлом, и понятно, что конкретный пример с raw-ready едва ли похож на реальный.
Я сторонник того, чтобы для примеров использовать похожие на реальность задачи.

Совсем жесть, это когда показывают такой пример:
Код:
class C1
  [S1 -> S2]
  m1(a1, a2);
  m2(a1, a2);

  [S2]
  m3(a3);
  m4(a4);

  [S2 -> S1]
  m5();
end;


А что? Не нужно его воспринимать буквально. Всё же показано. Каждому должно быть понятно как этот подход работает в реальных задачах.

Но, нет. Пример всё-таки должен быть похож на реальность, иначе похоже на наукообразный подход "ради наукообразия".


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 31 Май, 2018 20:02 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
В техниках как в Kotlin условный полный перебор (потенциально огромного количества) логических процессов не осуществляется

Я говорил именно про механизм suspending functions. Т.е. механизм, когда ключевым словом suspend можно указать компилятору, что нужно из обычного кода сделать автомат.

При этом, на этих же самых suspended functions можно сделать и описываемый вами "полный перебор".

Достаточно сделать верхнеуровневую suspend функцию, которая будет заключаться в пробежке по списку и вызывать эти самые "логические процессы".
Прелесть и заключается в том, что одним концептом можно выразить и композицию автоматов, и "полный перебор" (по сути то же самое), и при этом не возникает callback hell'а.


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


Пока получается, что текстовых вариантов -- вагон (и они нормальные!), а вот на Дракон-схему они не напяливаются.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 07 Июнь, 2018 20:11 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
PSV100 писал(а):
Вы как-то буквально воспринимаете. Выше был тезис о том, что автоматные спецификации это прежде всего некий протокол, чем детальный строгий императив (спецификации и таковыми могут быть, конечно же). Пример с File всего лишь демонстрирует способы идентификаций состояний, в данном случае на некоем "макроуровне" (в разрезе одностороннего протокола или протокола над ресурсом), что может пригодиться для согласования взаимодействий.

Конечно, буквально. Вы показываете пример с файлом, и понятно, что конкретный пример с raw-ready едва ли похож на реальный.
Я сторонник того, чтобы для примеров использовать похожие на реальность задачи.

Задачи контроля протоколов очень даже реальные, и не всегда достаточно "визуального" контроля с runtime-тестированием.
Владимир Ситников писал(а):
Совсем жесть, это когда показывают такой пример:
...

К примеру, у Microsoft почти что такая жесть и есть, или была в рамках проекта Vault (сейчас страница проекта уже недоступна):
http://research.microsoft.com/vault/
https://web.archive.org/web/20010510004116/http://research.microsoft.com:80/vault/main.htm

Vault -- некий аналог языка Cyclone (последний, фактически, есть предок для Rust) -- "безопасный" диалект Си, с контролем памяти и времени жизни объектов через систему регионов и пр. А также в Vault реализована система линейных или уникальных типов, контролирующая упорядоченность операций над объектами. Протокол задаётся в виде интерфейса примерно в таком стиле (схематично по мотивам оригинала):
Код:
interface Socket {
    state Raw, Named, Listening, Ready;

    type sock = (...);
    type sockaddr = (...);

    type status[s at r: sock] = Ok [r in Named] | Error(code: int) [r in Raw];

    function socket(...): sock at r [new r in Raw];
    function bind(var s at r: sock, addr: sockaddr): status[s] [r in Raw];
    function listen(s at r: sock, n: int): void [r in Named -> Listening];
    function accept(s at r: sock, addr: sockaddr): sock at n [r in Listening, new n in Ready];
    function receive(s at r: sock, var b: bytes): void [r in Ready];
    function close(s at r: sock): void [-r];
}

Оператор "at" в виде "s at r" указывает на то, что объект в переменной "s" связан с виртуальным регионом "r", для которого задаются "управляющие состояния" (сам возникающий автомат может быть представлен отдельно в каком-нибудь виде). Выражение "new r" -- инициализация объекта, "-r" -- деструкция объекта. Причём состояния подразумеваются виртуальными. К примеру, такая функция как "listen" может не изменять свойства самого объекта (какие-то изменения могут происходить во внешней среде, с которой имеется взаимодействие через подобные функции), поэтому не всегда возможен анализ реального физического состояния объекта (для последующей ориентировки действий).
Компилятор отслеживает операции над переменными, в т.ч. с учётом связей по типам как для функции "bind" (компилятор не позволит использовать функцию "listen" без анализа результата исполнения "bind"):
Код:
var addr: sockaddr = (...);
var s: sock = socket(...);

switch (bind(s, addr)) {
    case Ok:
        listen(s, 0);
        ...
    case Error(code):
        ...
}

В статейке ниже пример выражения протокола через формулы упорядоченности действий ("объектная" модификация SCADE/Lustre):
Synchronous Objects with Scheduling Policies (Introducing safe shared memory in Lustre)

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

Такие системы как Vault, SCADE ограничены статикой объектов, т.е. все объекты не должны "пропадать из вида" для компиляторов/анализаторов (или требуются runtime-средства восстановления протокола типа).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 07 Июнь, 2018 20:21 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Простите, но пример с файлом едва ли решает какую-то реальную проблему.
Если включаете состояния прямо в класс File, то почему бы не сделать несколько подтипов ReadyFile, RawFile. Понятно, что системы типов разные бывают. Но raw-ready вовсе не выглядит задачей, ради которой нужно за уши притягивать автоматы и высокую науку.

Примеры выше как раз и указывают на особые реализации системы типов. Если пытаться виртуальные состояния отразить через обычные системы типов для императивного языка, то возникает примерно такая жесть:
Код:
type Sock = (...);
type RawSock(Sock);
type NamedSock(Sock);
type ListeningSock(Sock);
type ReadySock(Sock);

type SockAddr = (...);

type Status = Ok(s: NamedSock) | Error(s: RawSock, code: int);

function socket(...): RawSock;
function bind(var s: RawSock, addr: sockaddr): Status;
function listen(s: NamedSock, n: int): ListeningSock;
function accept(s: ListeningSock, addr: sockaddr): ReadySock;
function receive(s: ReadySock, var b: bytes): void;
function close(s: Sock);

Тип как "RawSock(Sock)" определен неким наследником от "Sock", но ничего не добавляется/изменяется. Использование в стиле:
Код:
var addr: SockAddr = (...);
var rs: RawSock = socket(...);

switch (bind(rs, addr)) {
    case Ok(ns: NamedSock):
        var ls: ListeningSock = listen(ns, 0);
        var ls1: ListeningSock = listen(ns, 0); //Error !!!
        ...
    case Error(_, code):
        ...
}

В примере вторая попытка исполнения функции "listen" над одной и той же переменной "ns" должна быть отброшена, в идеале ещё компилятором. Т.е. система типов должна предусматривать (с соответствующими обозначениями для объектов) линейные/уникальные значения или реализовывать как-то "move"-семантику.
И в общем случае, на ровном месте, вместо императивного изменения одного и того же объекта, возникает множество объектов с потребностью копирования/пересылки данных (не всегда возможны оптимизации через ссылки, переаллокации по месту и пр.). Runtime-стоимость может добавить и "move"-семантика объектов.
Положения сохраняются и при использовании какого-то механизма классов/объектов, где часть операций содержаться в конструкторах/деструкторах.

Разработчики Rust-а когда-то пытались исправить проблемы через механизм "переключения" типа "по месту", но не работают такие приёмы в императивном языке:
https://pcwalton.github.io/2012/12/26/typestate-is-dead.html
Владимир Ситников писал(а):
Но, нет. Пример всё-таки должен быть похож на реальность, иначе похоже на наукообразный подход "ради наукообразия"

Задачи верификации и решаются через "наукообразие", и в любом случае без "жести" не обойтись, даже если протоколы или интерфейсы заполучить в каком-то виде, слепить и оценить модели взаимодействия в каком-нибудь аля Spin/Promela, и переносить модели задачи в программный код (с возможной кодогенерацией, хотя бы частично).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 07 Июнь, 2018 20:24 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 396
Владимир Ситников писал(а):
Прелесть и заключается в том, что одним концептом можно выразить и композицию автоматов, и "полный перебор" (по сути то же самое), и при этом не возникает callback hell'а.

Сам по себе механизм suspending functions, как алгоритмический концепт, выражает лишь точку приостановки потока, или же точку непосредственного "рандеву" между процессами и т.п. Т.е. какаю-то композицию автоматов концепт явно не выражает, как и саму суть организации "рандеву" и т.д. И возможные дальнейшие построения API поверх операции "ожидания" вполне могут привести к какому-то "hell"-у (аля "лямбда-hell"). Т.е. сам концепт suspending functions ещё не обеспечивает методологическую успешность построения взаимодействующих процессов, за "прелесть" ещё нужно бороться.

Владимир Ситников писал(а):
Пока получается, что текстовых вариантов -- вагон (и они нормальные!), а вот на Дракон-схему они не напяливаются

И вот те же аля suspending functions и требуют для схем указания точек блокировок, точек "рандеву". И в то же время в общем случае есть потребность для "ожидания" иметь "вольные" условия, как для процесса "atFloor" ранее в этой ветке:
https://forum.drakon.su/viewtopic.php?f=142&t=6246&sid=9001278b2fc553d08523a0a56a73fc2f#p101683

На сегодня, судя по всему, каждый сам себе "напяливает" точки ожидания, как хочет или может, с частными интерпретациями возникающей семантики.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 07 Июнь, 2018 22:02 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
И возможные дальнейшие построения API поверх операции "ожидания" вполне могут привести к какому-то "hell"-у (аля "лямбда-hell"). Т.е. сам концепт suspending functions ещё не обеспечивает методологическую успешность построения взаимодействующих процессов, за "прелесть" ещё нужно бороться..

Разговор зашёл в тупик.
Зубодробильный код можно написать на любом языке программирования.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 08 Июнь, 2018 00:14 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
Код:
process atFloor( : #idle  : #start) {
    open -> openDoor(), set t, opened;
    opened, closeButton() or t >= Tdoor -> closeDoor(), close;
    close, closedDoor() -> decisionClosed( : #idle  : #start);
    close, blockedDoor() -> open;
}


Выше "автоматные ветки" idle и start "передаются" наружу как результат работы процесса atFloor (в свою очередь, эти ветки "прилетают" от процесса decisionClosed). Кроме переплетения в силуэте "автоматных веток" ("интерфейсных", выражающих изменение поведения процесса в зависимости от предыстории действий) и "внутренних" вспомогательных возможны переходы или прыжки во "внешние" силуэты.


По-моему, это сомнительная конструкция.
Получается, atFloor удивительным образом зависит от "переданных свыше" #idle, #start, при этом для самой "гиперфункции" atFloor что #idle что #start всё равно.

Если говорить про a-la suspend вариацию, то никакого lambda hell'а тут не возникает.

Код:
// pre: стоим на этаже с открытыми дверями
// post: поймали добычу, закрыли дверь
suspend atFloor() {
    while(true) { // если поменять на for(i in 1..3), то будет 3 попытки закрыть дверь
        openDoor();
        set t;
        while (!(closeButton() or t)) {
            yield; /* ждёмс */
        }
        closeDoor();
        while(!blockedDoor()) {
            if (closedDoor()) {
                return; // дело сделано, можно принимать решение куда ехать
            }
            yield; /* ждёмс */
        }
    }
    throw new IllegalStateException("лифт сломался, идите пешком")
}


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 08 Июнь, 2018 15:04 

Зарегистрирован: Среда, 03 Май, 2017 09:55
Сообщения: 200
PSV100 писал(а):
Задачи верификации и решаются через "наукообразие", и в любом случае без "жести" не обойтись, даже если протоколы или интерфейсы заполучить в каком-то виде, слепить и оценить модели взаимодействия в каком-нибудь аля Spin/Promela, и переносить модели задачи в программный код (с возможной кодогенерацией, хотя бы частично).

Я вот к чему: использование науки в подходе очень часто сопряжено с накладными расходами.
Иначе говоря, от хорошей жизни не будут использовать наукообразные подходы.
Например, можно защищаться от проблемы "глобальных переменных" с помощью Haskell.
Можно доказывать правильность кода с помощью Coq/Idris.
Но всё это замедляет скорость разработки.

В бытовых же случаях стоимость ошибки может быть гораздо меньше, чем стоимость разработки с использованием "суперзащищённого наукообразного языка".

Я рассматривал Дракон исключительно в контексте "бытового" программирования.
Вы, конечно, набрасываете интересные ссылки, но они, к сожалению, слишком уж уходят далеко от практики.
Конечно, бывают случаи (напр. упомянутый USB стек), когда моделировать нужно именно в виде автомата, но для тех случаев, по-моему, Дракон вообще не годится. Под словами "в виде автомата" я понимаю явное указание событий, состояний в "программе".


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 188 ]  На страницу Пред.  1, 2, 3, 4, 5, 6 ... 10  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2008-2024, участники конференции «DRAKON.SU», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB