Убедительная просьба к тем, кто будет создавать следующий язык программирования, скажем, Java Pro или Scala ++. Пожалуйста, добавьте синтаксический сахар для монад, например, похожий на вычислительные выражения F#. Порою очень не хватает
суббота, 13 января 2018 г.
суббота, 11 ноября 2017 г.
Книга про моделирование и Haskell
Здесь тоже поделюсь. Написал книгу про имитационное моделирование с той точки зрения, как я это реализовал на языке Haskell в своем комплексе программных библиотек Айвика. Книгу назвал «Aivika: Computation-based Modeling and Simulation in Haskell».
Скачать можно по любой из двух следующих ссылок, которые обе ведут на один источник, но вторая ссылка точно должна работать:
http://aivikasoft.com/downloads/aivika/aivika.pdf
https://github.com/dsorokin/dsorokin.github.io/blob/master/downloads/aivika/aivika.pdf
Книга охватывает последовательное моделирование, параллельное и распределенное моделирование, а также вложенное моделирование. Фокус на дискретно-событийном моделировании, прежде всего, процесс-ориентированной парадигме, которая сводится на уровне реализации к событийно-ориентированной.
Начну представлять книгу с конца.
В самом конце книги описан мой эксперимент по вложенному моделированию, который можно применить, например, к финансовому моделированию. Так, в узлах решетки я запускаю вложенные имитации для эмуляции некоторого случайного процесса, который потом можно оценить. Мне кажется, что это может быть очень интересным расширением известной биномиальной модели, которая широко применяется для оценки опционов и контрактов. Я же позволяю случайные процессы описывать еще в терминах дискретных событий и дискретных процессов, да того же GPSS.
Середина книги посвящена моей реализации параллельного и распределенного моделирования на основе оптимистичного метода деформации времени. Описано, как создавать такие модели, как запускать, как мониторить, как работать с вводом-выводом в условиях распределенной имитации с откатами, какие есть нюансы, например, при определении пороговых значений очередей для эффективного задания горизонта моделирования.
Главная же часть книги описывает основные концепции дискретно-событийного моделирования применительно к последовательной имитации. Дискретные события, дискретные процессы, ресурсы, вытеснение ресурса, очереди и т.д. Но очень важно заметить, что практически все это работает и в случае распределенного моделирования, и вложенного моделирования, включая GPSS-подобный предметно-ориентированный язык, который тоже бегло описан.
Книга снабжена графиками и гистограммами, которые создала сама Айвика во время имитационных экспериментов. Вы их также можете запрограммировать. Готовые отчеты с результатами моделирования Айвика умеет создавать автоматически. Поддерживается метод Монте-Карло. Можно проводить анализ чувствительности относительно случайных внешних параметров. Легко запустить имитацию с тысячами параллельных прогонов.
При всем этом мы можем с помощью довольно высокоуровневых вычислений просто определять довольно сложные имитационные модели, где в иных условиях пришлось бы прибегнуть к помощи дорогущих и сложных систем визуального моделирования.
В общем, приглашаю к прочтению. Книга о том, как можно использовать мой комплекс библиотек Айвика для решения самых разных задач имитационного моделирования. Есть только один нюанс. Для охвата более широкой аудитории я решил написать книгу на английском языке.
И добавлю еще, что на мой взгляд скорость моделирования получилась очень хорошей. Постоянно делаю замеры.
Скачать можно по любой из двух следующих ссылок, которые обе ведут на один источник, но вторая ссылка точно должна работать:
http://aivikasoft.com/downloads/aivika/aivika.pdf
https://github.com/dsorokin/dsorokin.github.io/blob/master/downloads/aivika/aivika.pdf
Книга охватывает последовательное моделирование, параллельное и распределенное моделирование, а также вложенное моделирование. Фокус на дискретно-событийном моделировании, прежде всего, процесс-ориентированной парадигме, которая сводится на уровне реализации к событийно-ориентированной.
Начну представлять книгу с конца.
В самом конце книги описан мой эксперимент по вложенному моделированию, который можно применить, например, к финансовому моделированию. Так, в узлах решетки я запускаю вложенные имитации для эмуляции некоторого случайного процесса, который потом можно оценить. Мне кажется, что это может быть очень интересным расширением известной биномиальной модели, которая широко применяется для оценки опционов и контрактов. Я же позволяю случайные процессы описывать еще в терминах дискретных событий и дискретных процессов, да того же GPSS.
Середина книги посвящена моей реализации параллельного и распределенного моделирования на основе оптимистичного метода деформации времени. Описано, как создавать такие модели, как запускать, как мониторить, как работать с вводом-выводом в условиях распределенной имитации с откатами, какие есть нюансы, например, при определении пороговых значений очередей для эффективного задания горизонта моделирования.
Главная же часть книги описывает основные концепции дискретно-событийного моделирования применительно к последовательной имитации. Дискретные события, дискретные процессы, ресурсы, вытеснение ресурса, очереди и т.д. Но очень важно заметить, что практически все это работает и в случае распределенного моделирования, и вложенного моделирования, включая GPSS-подобный предметно-ориентированный язык, который тоже бегло описан.
Книга снабжена графиками и гистограммами, которые создала сама Айвика во время имитационных экспериментов. Вы их также можете запрограммировать. Готовые отчеты с результатами моделирования Айвика умеет создавать автоматически. Поддерживается метод Монте-Карло. Можно проводить анализ чувствительности относительно случайных внешних параметров. Легко запустить имитацию с тысячами параллельных прогонов.
При всем этом мы можем с помощью довольно высокоуровневых вычислений просто определять довольно сложные имитационные модели, где в иных условиях пришлось бы прибегнуть к помощи дорогущих и сложных систем визуального моделирования.
В общем, приглашаю к прочтению. Книга о том, как можно использовать мой комплекс библиотек Айвика для решения самых разных задач имитационного моделирования. Есть только один нюанс. Для охвата более широкой аудитории я решил написать книгу на английском языке.
И добавлю еще, что на мой взгляд скорость моделирования получилась очень хорошей. Постоянно делаю замеры.
среда, 16 августа 2017 г.
Трансляция модели из Python в Haskell
Вспомнив известные слова про гору и Магомета, решил сделать свои наработки более доступными. Создал для языка программирования Python пакет aivika-modeler, который позволяет создавать дискретно-событийные модели. а затем запускать основанные на них имитационные эксперименты по методу Монте-Карло с тысячами запусков в серии и более.
Пакет больше предназначен быть неким клеем, с помощью которого на языке Python можно соединять и объединять готовые компоненты в единую модель, причем сами компоненты предполагается создавать уже на языке Haskell. Однако, во многих случаях должно хватить существующего набора компонент, и поэтому часто можно ограничиться одним языком Python. В планах добавить поддержку GPSS-подобного DSL.
Есть довольно большая категория людей из целевой аудитории, которые не знают, не хотят и не любят программирование, но Python вполне могут знать на некотором простом уровне. Однако, они могут быть очень хорошими специалистами в своей предметной области. Мой пакет может показаться удобным для них.
Итак, модель описывается на языке Python. По ней автоматически создается соответствующий код на языке Haskell. Более того, создается готовый проект на основе системы сборки Stack. Собственно, это главное техническое требование - на системе пользователя должен быть установлен Stack. Здесь предвижу некоторые возможные трудности с пакетом old-time на некоторых системах Windows, но надеюсь, что со временем они благополучно разрешатся.
Так вот, автоматически созданный проект на Stack собирается, а потом запускается на исполнение. В случае успеха в самом конце открывается веб-браузер с результатами имитационного эксперимента. Там могут быть графики, гистограммы, ссылки на таблицы в формате CSV, сводная статистика и прочая информация. Вид и формат желаемых итоговых результатов задается также на языке Python.
Мне был довольно интересен такой эксперимент по использованию Haskell из Python. Может быть, кто-нибудь возьмет идею на вооружение
Пакет больше предназначен быть неким клеем, с помощью которого на языке Python можно соединять и объединять готовые компоненты в единую модель, причем сами компоненты предполагается создавать уже на языке Haskell. Однако, во многих случаях должно хватить существующего набора компонент, и поэтому часто можно ограничиться одним языком Python. В планах добавить поддержку GPSS-подобного DSL.
Есть довольно большая категория людей из целевой аудитории, которые не знают, не хотят и не любят программирование, но Python вполне могут знать на некотором простом уровне. Однако, они могут быть очень хорошими специалистами в своей предметной области. Мой пакет может показаться удобным для них.
Итак, модель описывается на языке Python. По ней автоматически создается соответствующий код на языке Haskell. Более того, создается готовый проект на основе системы сборки Stack. Собственно, это главное техническое требование - на системе пользователя должен быть установлен Stack. Здесь предвижу некоторые возможные трудности с пакетом old-time на некоторых системах Windows, но надеюсь, что со временем они благополучно разрешатся.
Так вот, автоматически созданный проект на Stack собирается, а потом запускается на исполнение. В случае успеха в самом конце открывается веб-браузер с результатами имитационного эксперимента. Там могут быть графики, гистограммы, ссылки на таблицы в формате CSV, сводная статистика и прочая информация. Вид и формат желаемых итоговых результатов задается также на языке Python.
Мне был довольно интересен такой эксперимент по использованию Haskell из Python. Может быть, кто-нибудь возьмет идею на вооружение
понедельник, 20 марта 2017 г.
GPSS на Haskell
Если кто еще не знает, GPSS - это один из самых известных специализированных языков дискретно-событийного моделирования. Так вот, я добавил в AivikaSim [http://www.aivikasoft.com/ru/products/aivikasim.html] поддержку GPSS-подобного предметного-ориентированного языка. Это пакет aivikasim-gpss [https://github.com/dsorokin/aivikasim-gpss]. Вот здесь находится работающий тестовый пример [https://github.com/dsorokin/aivikasim-gpss-test].
Постарался охватить основные моделирующие блоки, такие как SEIZE, PREEMPT, GATHER, ASSEMBLE, MATCH. Другие либо имеют явные аналоги у меня, либо требуют небольшого программирования как в случае блоков LINK и UNLINK. Не гарантируется точного совпадения результатов с GPSS World, так как логика работы с транзактами у меня совершенно иная, но в некоторых случаях результаты получаются очень близкими.
Вот, здесь примеры моделей [https://github.com/dsorokin/aivikasim-gpss/tree/master/examples] из красной книги Шрайбера по GPSS. Там в начале каждого примера приводится соответствующий код модели на языке GPSS World. Можно сличить результаты.
Example2A.hs означает, что это пример 2A из книги, а вот Example7-26.hs означает, что это соответствует модели на рисунке 7.26. Модели с окончанием Trans, такие как Example2BTrans.hs, означают, что там используется обобщенная версия AivikaSim. Фактически это означает, что приведенный код готов для использования в распределенной имитации.
Более того, пример Example7-26Distributed.hs непосредственно запускается через модуль распределенного моделирования. В данном случае это формально последовательная модель, но запускается она фактически в виде распределенной, т.е. она готова для кластера компьютеров. Используется оптимистичный алгоритм деформации времени.
Сразу напишу, что хотя для приведенных моделей удалось добиться очень хорошего соответствия с GPSS, то вот для примера 5D из книги Шрайбера такого близкого соответствия, скорее всего, не получится. Сейчас совпадение идет в 9 случаях против одного, где модель будет уже другой. Причем, совпадает даже на очень нетривиальных моделях, где важен порядок обработки транзактов.
Касательно скорости моделирования. Модуль GPSS-подобного языка последовательной версии AivikaSim моделирует примерно в 5-7 раз медленнее, чем GPSS World, но зато позволяет использовать разные методы в рамках одной модели, например, агенты и события. Для сравнения, распределенный модуль AivikaSim на последовательных задачах медленнее в раз 6-9, чем последовательная версия AivikaSim, но зато распределенную версию можно запустить много раз на разных узлах в рамках одной модели. Например, можно запустить 7 параллельно работающих локальных процессов на одной системе с 8-ядерным процессором.
Если кто захочет проверить результаты, то вот руководство по установке AivikaSim [https://github.com/dsorokin/aivikasim-installer].
Постарался охватить основные моделирующие блоки, такие как SEIZE, PREEMPT, GATHER, ASSEMBLE, MATCH. Другие либо имеют явные аналоги у меня, либо требуют небольшого программирования как в случае блоков LINK и UNLINK. Не гарантируется точного совпадения результатов с GPSS World, так как логика работы с транзактами у меня совершенно иная, но в некоторых случаях результаты получаются очень близкими.
Вот, здесь примеры моделей [https://github.com/dsorokin/aivikasim-gpss/tree/master/examples] из красной книги Шрайбера по GPSS. Там в начале каждого примера приводится соответствующий код модели на языке GPSS World. Можно сличить результаты.
Example2A.hs означает, что это пример 2A из книги, а вот Example7-26.hs означает, что это соответствует модели на рисунке 7.26. Модели с окончанием Trans, такие как Example2BTrans.hs, означают, что там используется обобщенная версия AivikaSim. Фактически это означает, что приведенный код готов для использования в распределенной имитации.
Более того, пример Example7-26Distributed.hs непосредственно запускается через модуль распределенного моделирования. В данном случае это формально последовательная модель, но запускается она фактически в виде распределенной, т.е. она готова для кластера компьютеров. Используется оптимистичный алгоритм деформации времени.
Сразу напишу, что хотя для приведенных моделей удалось добиться очень хорошего соответствия с GPSS, то вот для примера 5D из книги Шрайбера такого близкого соответствия, скорее всего, не получится. Сейчас совпадение идет в 9 случаях против одного, где модель будет уже другой. Причем, совпадает даже на очень нетривиальных моделях, где важен порядок обработки транзактов.
Касательно скорости моделирования. Модуль GPSS-подобного языка последовательной версии AivikaSim моделирует примерно в 5-7 раз медленнее, чем GPSS World, но зато позволяет использовать разные методы в рамках одной модели, например, агенты и события. Для сравнения, распределенный модуль AivikaSim на последовательных задачах медленнее в раз 6-9, чем последовательная версия AivikaSim, но зато распределенную версию можно запустить много раз на разных узлах в рамках одной модели. Например, можно запустить 7 параллельно работающих локальных процессов на одной системе с 8-ядерным процессором.
Если кто захочет проверить результаты, то вот руководство по установке AivikaSim [https://github.com/dsorokin/aivikasim-installer].
суббота, 18 февраля 2017 г.
Демо-тест распределенной имитации на монадах
Создал тестовый демонстрационный пример распределенной дискретно-событийной имитации на основе своего нового продукта AivikaSim. Тест легко воспроизвести по приведенной инструкции:
https://github.com/dsorokin/aivikasim-distributed-test
Код написан на языке Haskell, но для воспроизведения теста язык программирования знать не требуется.
Для реализации мне очень помогла платформа Cloud Haskell, разработчикам которого хочу выразить отдельную благодарность.
При воспроизведении теста можно обойтись одним локалхостом, а можно объединить до четырех машин в кластер. На самом деле, кластер мог бы состоять и из сотни машин, но для данной модели нужно всего четыре вычислительных узла.
Особая фишка в том, что узлы можно размещать, используя ненадежные соединения и обычные компьютеры. То есть, теоретически кластер может состоять из машин, расположенных в разных континентах, но вопрос тогда только в том, насколько быстро будет идти имитация, потому что для целей тестирования там сознательно создается очень много сообщений. Происходят постоянные откаты назад и попытки заново обработать дискретные события, потому как реализован оптимистичный алгоритм «деформации времени» (Time Warp).
Если возникнет кратковременная потеря связи на минуту или две, а я в своих тестах просто на время выдергивал Ethernet-кабель, то распределенная имитация должна сама себя излечить после восстановления связи. В принципе, время потери связи может быть и значительно дольше, но тогда надо подкрутить внешние параметры запуска.
Только стоит заметить, что восстановление имитации на Linux и macOS работает как часы, а вот на Windows немного похрамывает, но, видимо, это связано с тем, что у Haskell-сообщества Unix-системы приоритетнее, что скорее хорошо.
По приведенной ссылке лишь скромный небольшой демонстрационный пример, показывающий возможности системы AivikaSim.
https://github.com/dsorokin/aivikasim-distributed-test
Код написан на языке Haskell, но для воспроизведения теста язык программирования знать не требуется.
Для реализации мне очень помогла платформа Cloud Haskell, разработчикам которого хочу выразить отдельную благодарность.
При воспроизведении теста можно обойтись одним локалхостом, а можно объединить до четырех машин в кластер. На самом деле, кластер мог бы состоять и из сотни машин, но для данной модели нужно всего четыре вычислительных узла.
Особая фишка в том, что узлы можно размещать, используя ненадежные соединения и обычные компьютеры. То есть, теоретически кластер может состоять из машин, расположенных в разных континентах, но вопрос тогда только в том, насколько быстро будет идти имитация, потому что для целей тестирования там сознательно создается очень много сообщений. Происходят постоянные откаты назад и попытки заново обработать дискретные события, потому как реализован оптимистичный алгоритм «деформации времени» (Time Warp).
Если возникнет кратковременная потеря связи на минуту или две, а я в своих тестах просто на время выдергивал Ethernet-кабель, то распределенная имитация должна сама себя излечить после восстановления связи. В принципе, время потери связи может быть и значительно дольше, но тогда надо подкрутить внешние параметры запуска.
Только стоит заметить, что восстановление имитации на Linux и macOS работает как часы, а вот на Windows немного похрамывает, но, видимо, это связано с тем, что у Haskell-сообщества Unix-системы приоритетнее, что скорее хорошо.
По приведенной ссылке лишь скромный небольшой демонстрационный пример, показывающий возможности системы AivikaSim.
вторник, 29 ноября 2016 г.
Сетевое моделирование с Айвикой
Давно присматриваюсь к сетевому моделированию (англ. network simulation). Нахожу, что многое можно моделировать с помощью моей Айвики уже сейчас, в том числе, моделировать распределенно на кластере или параллельно на суперкомпьютере.
Основная идея такая. Обычно говорят о портах - источниках данных. В Айвике источники могут быть как активными, так и пассивными. Активный источник сам проталкивает данные дальше для обработки. Это у меня тип Signal a (или Signal m a в обобщенной версии). Тогда каналом будет просто преобразование одного сигнала в другой. Модуль будет функцией, отображающей входные сигналы на выходные.
Сигналы - это фактически приложение идеи шаблона IObservable из .NET к имитационному моделированию. Сигналы можно комбинировать, соединять друг с другом. Еще их можно задерживать по времени через очередь событий.
Похоже, что сигналы могут подойти для моделирования многих компьютерных сетей, но это пока предположение.
Пассивные источники данных у меня в Айвике представлены потоками Stream a (или Stream m a в обобщенной версии). Их нужно запрашивать, чтобы вытянуть из них данные. Их можно распараллеливать для обработки, а потом снова сливать в один поток.
Потоки являются обобщением собственно самой идеи потока из функционального программирования, но примененное к имитационному моделированию. Так, потоки можно задерживать по времени.
Такие потоки подходят для моделирования сетей массового обслуживания. Поэтому я часто называю их просто потоками транзактов, потому что это они самые и есть.
Любопытно, что активные сигналы и пассивные потоки могут быть преобразованы к друг другу тривиальным образом, используя очереди, если необходимо.
В общем, у меня есть достаточно общий аппарат, который может быть применен к широкому классу задач на мой взгляд. Более того, используя модуль aivika-distributed, такие задачи можно обсчитывать распределенно на кластере или параллельно в случае необходимости. Как раз на днях значительно улучшил этот модуль.
Распределенное моделирование c Айвикой
Обновил версию aivika-distributed, которую можно использовать для распределенного и параллельного моделирования. Реализована оптимистичная стратегия по методу Time Warp. В этой версии значительно улучшена синхронизация глобального времени. Используется алгоритм Самади. В общем, если соединения между узлами достаточно надежные, то распределенная имитация должна вполне хорошо работать.
Чтобы использовать эту версию, достаточно вооружиться документацией PDF по базовой версии Айвики. Здесь все то же самое, т.е. события, процессы, ресурсы, сигналы, потоки транзактов, все это применимо и к распределенной версии. Только типы будут выглядеть по другому. Там, где был Event a, станет Event DIO a и т.д. Последний Event - это фактически монадный трансформер, но я решил не добавлять к его названию букву T, как это обычно делают, а сохранить все названия из базовой версии. Тому были причины.
Итак, вооружившись документацией по базовой версии Айвики, можно создавать имитационные модели. Распределенность добавляется через посылку и прием сообщений вот из этого модуля Message.
Собственно, все! В следующем сообщении напишу, как это можно применить к сетевому моделированию (англ. network simulation)
вторник, 7 июня 2016 г.
Айвика как конструктор общецелевых библиотек имитационного моделирования
Пока в отпуске написал статью о том, как функциональное программирование может быть применено к задачам вложенного моделирования и задачам параллельного распределенного моделирования на примере моей Айвики. Раскрыты некоторые ключевые детали реализации для более полного понимания того, как работает Айвика.
пятница, 29 апреля 2016 г.
Айвика для кластера и суперкомпьютера
В прошлую субботу выпустил первую версию [5] своей Айвики, которая позволяет создавать и обсчитывать параллельные распределенные дискретно-событийные модели на кластере и/или суперкомпьютере.
В общем, идея такая.
У меня есть основная версия [2] обще-целевой библиотеки, о которой я много писал у себя в блоге. Она построена на основе стандартного вычисления IO. Самая быстрая версия. Можно автоматизировать вывод графиков и таблиц. Есть документация [1] в формате PDF. Много примеров.
Потом я обобщил эту версию для произвольных вычислений, которые должны удовлетворять небольшому числу ограничений, в числе которых возможность создавать изменяемые ссылки и возможность иметь очередь событий. Так родилась обобщенная версия [3] библиотеки. Это тоже обще-целевая библиотека с возможностью формулировать модели в терминах событий, дискретных процессов, очередей, ресурсов, потоков транзактов, процессоров и т.п., но в рамках задаваемого извне типа вычислений. Практически совпадает с основной версией на уровне реализации, в том числе, в названиях, но типы и сигнатуры функций другие.
Дальше идут приложения. Создаю частные случаи вычислений, удовлетворяющие требованиям обобщенной версии Айвики, но добавляющие те или иные желаемые свойства.
Так родилась версия [4] для вложенных имитаций. Это когда из «настоящего» мы можем относительно дешево и быстро заглядывать в «будущее» модели столько раз, сколько необходимо, а потом на основе полученной информации принимать решения уже в «настоящем». Конек в относительной дешевизне создания вложенных имитаций и в том, что это по-прежнему обще-целевая библиотека имитационного моделирования.
Теперь же воплотил в жизнь еще и версию [5] для параллельного распределенного имитационного моделирования. Тоже обще-целевая библиотека моделирования. Здесь независимые узлы могут обмениваться друг с другом асинхронными сообщениями, привязанными к временным меткам. Если на узле уже «будущее», а приходит сообщение в «прошлое», то происходит прозрачный откат до «прошлого» модели. Все сообщения, которые были посланы узлом и стали устаревшими, отменяются, и, соответственно, рассылаются так называемые «анти-сообщения». Короче, реализована оптимистичная стратегия с прозрачными, возможно, каскадными откатами на основе идей метода «деформации времени» (англ. «time warp»), датируемого началом 80-х.
В распределенной версии экспериментальная реализация механизма синхронизации времени. Есть разные параметры, которые можно настраивать. Правда, с документацией немного туговато, да и требуется хорошее знание Haskell, но там очень мало отличий от основной версии, для которой уже есть документация. Если есть желающие, то пробуйте в своих университетах! :)
воскресенье, 31 января 2016 г.
Айвика: ветвящееся дискретно-событийное моделирование на Haskell
На днях сделал анонс своих новых наработок на Haskell Cafe. Повторю и здесь.
Выпустил три новых релиза. Это входит в серию библиотек, которую я условно называю Айвикой [1, 2, 3]. Главная новинка - пакет aivika-branches [3], который позволяет делать то, что я для себя назвал «ветвящимся дискретно-событийным моделированием» (англ. «branching discrete event simulation») с возможностью запускать вложенные имитации внутри имитации для предсказания и оценки будущего поведения системы на этапе самой имитации. Сейчас попробую описать подробнее.
Допустим, что у нас есть достаточно общая библиотека, которая позволяет реализовывать дискретно-событийные модели. Там могут быть потоки случайных заданий (требований, они же, тразакты). Могут быть ограниченные ресурсы, за которые идет конкурентная борьба дискретных процессов. Есть глобальная очередь событий. Есть просто очереди сущностей. Есть активности, привязанные к обработке событий и т.п. В общем, все то, что реализовано в моем пакете aivika [1].
Мой метод заключается в том, что мы описываем поведение имитационной модели с помощью абстрактных вычислений. Во время своего запуска основное вычисление имеет состояние, которое сводится к состоянию очереди обработчиков будущих событий и к состоянию всех ссылок (они же, переменные), которые используются в модели.
Теперь главная новинка. Представим, что мы умеем достаточно эффективно клонировать состояние модели, порождая производную ветвь модели в текущий момент времени. То есть, мы клонируем и очередь всех обработчиков будущих событий, которые должны еще отработать в будущем. Мы также клонируем состояние всех изменяемых ссылок для новой ветки модели.
Тогда мы можем запросить из текущего времени будущее значение заданного под-вычисления, как если бы мы продолжили текущую имитацию, но без фактического изменения самой имитации!
Именно это умеет делать следующая функция из нового пакета aivika-branches [3]:
futureEvent :: Double -> Event BrIO a -> Event BrIO a
Здесь мы создаем новую ветку имитационной модели и запускаем заданное под-вычисление в желаемое время в будущем или настоящем, причем текущая имитационная модель остается нетронутой. В порожденной ветке отрабатывают все ожидающие выполнения обработчики событий вплоть до заданного времени.
Что касается типов, то здесь появляются монадные трансоформеры из другого пакета aivika-transformers [2], который является обобщение пакета aivika. На самом деле, пакет aivika-transformers я подготовил для реализации распределенного и параллельного дискретно-событийного моделирования, но он получился таким общим и гибким, что я смог его применить и к ветвящемуся дискретно-событийному моделированию.
Как я уже написал, фишка в том, что функция futureEvent относительно дешевая. Мы можем относительно быстро клонировать состояние целого мира имитационной модели! Это стало возможным во многом благодаря повсеместному использованию приемов функционального программирования (тут в скобках замечу, что очень забавно со стороны смотрятся те, кто наивно полагает по своему неразумению, что монада IO не относится к функциональному программированию. Просто не понимают, что функциональное и императивное программирование - это разные, но совсем не антагонистичные и не исключающие друг друга взгляды на то, как можно писать компьютерные программы. Эти оба взгляда вполне могут сосуществовать). Еще там используются такие вещи, как слабые ссылки для того, чтобы не было утечки пространства (англ. space leak) при разветвлении состояния ссылок, чтобы вовремя подчищалась память.
Фактически получаем дерево имитаций, которое нужно ограничивать или по уровню вложенности или с помощью метода ветвей и границ. Что-то похожее встречается в финансовом моделировании.
Вообще, мне кажется, что ветвящееся дискретно-событийное моделирование может быть полезно для описания систем, которые моделируют поведение человека, который способен предвидеть будущее, самообучаться и сообразно менять свое поведение на ходу. Мне кажется, что это очень интересная и перспективная область.
[1] http://hackage.haskell.org/package/aivika
[2] http://hackage.haskell.org/package/aivika-transformers
[3] http://hackage.haskell.org/package/aivika-branches
Выпустил три новых релиза. Это входит в серию библиотек, которую я условно называю Айвикой [1, 2, 3]. Главная новинка - пакет aivika-branches [3], который позволяет делать то, что я для себя назвал «ветвящимся дискретно-событийным моделированием» (англ. «branching discrete event simulation») с возможностью запускать вложенные имитации внутри имитации для предсказания и оценки будущего поведения системы на этапе самой имитации. Сейчас попробую описать подробнее.
Допустим, что у нас есть достаточно общая библиотека, которая позволяет реализовывать дискретно-событийные модели. Там могут быть потоки случайных заданий (требований, они же, тразакты). Могут быть ограниченные ресурсы, за которые идет конкурентная борьба дискретных процессов. Есть глобальная очередь событий. Есть просто очереди сущностей. Есть активности, привязанные к обработке событий и т.п. В общем, все то, что реализовано в моем пакете aivika [1].
Мой метод заключается в том, что мы описываем поведение имитационной модели с помощью абстрактных вычислений. Во время своего запуска основное вычисление имеет состояние, которое сводится к состоянию очереди обработчиков будущих событий и к состоянию всех ссылок (они же, переменные), которые используются в модели.
Теперь главная новинка. Представим, что мы умеем достаточно эффективно клонировать состояние модели, порождая производную ветвь модели в текущий момент времени. То есть, мы клонируем и очередь всех обработчиков будущих событий, которые должны еще отработать в будущем. Мы также клонируем состояние всех изменяемых ссылок для новой ветки модели.
Тогда мы можем запросить из текущего времени будущее значение заданного под-вычисления, как если бы мы продолжили текущую имитацию, но без фактического изменения самой имитации!
Именно это умеет делать следующая функция из нового пакета aivika-branches [3]:
futureEvent :: Double -> Event BrIO a -> Event BrIO a
Здесь мы создаем новую ветку имитационной модели и запускаем заданное под-вычисление в желаемое время в будущем или настоящем, причем текущая имитационная модель остается нетронутой. В порожденной ветке отрабатывают все ожидающие выполнения обработчики событий вплоть до заданного времени.
Что касается типов, то здесь появляются монадные трансоформеры из другого пакета aivika-transformers [2], который является обобщение пакета aivika. На самом деле, пакет aivika-transformers я подготовил для реализации распределенного и параллельного дискретно-событийного моделирования, но он получился таким общим и гибким, что я смог его применить и к ветвящемуся дискретно-событийному моделированию.
Как я уже написал, фишка в том, что функция futureEvent относительно дешевая. Мы можем относительно быстро клонировать состояние целого мира имитационной модели! Это стало возможным во многом благодаря повсеместному использованию приемов функционального программирования (тут в скобках замечу, что очень забавно со стороны смотрятся те, кто наивно полагает по своему неразумению, что монада IO не относится к функциональному программированию. Просто не понимают, что функциональное и императивное программирование - это разные, но совсем не антагонистичные и не исключающие друг друга взгляды на то, как можно писать компьютерные программы. Эти оба взгляда вполне могут сосуществовать). Еще там используются такие вещи, как слабые ссылки для того, чтобы не было утечки пространства (англ. space leak) при разветвлении состояния ссылок, чтобы вовремя подчищалась память.
Фактически получаем дерево имитаций, которое нужно ограничивать или по уровню вложенности или с помощью метода ветвей и границ. Что-то похожее встречается в финансовом моделировании.
Вообще, мне кажется, что ветвящееся дискретно-событийное моделирование может быть полезно для описания систем, которые моделируют поведение человека, который способен предвидеть будущее, самообучаться и сообразно менять свое поведение на ходу. Мне кажется, что это очень интересная и перспективная область.
[1] http://hackage.haskell.org/package/aivika
[2] http://hackage.haskell.org/package/aivika-transformers
[3] http://hackage.haskell.org/package/aivika-branches
пятница, 20 ноября 2015 г.
Релиз системы моделирования VisualAivika 5
Всем привет! Недавно выпустил версию своей визуальной системы моделирования для системной динамики VisualAivika.
Функциональное программирование здесь при том, что на конечном этапе исходная система диффуров преобразуется в модель в терминах моей библиотеки Айвика, которая написана на языке F#, который, как говорят его создатели, functional first.
Может быть интересна история создания Айвики. Первоначальная идея возникла при изучении Haskell, но я очень быстро переключился реализовывать идею на F#. Первая версия на F# была ужасна. Ее до сих пор можно найти на простора интернета, но я не хочу давать ссылку на нее - пусть останется для истории.
Мне всегда было очень интересно реализовать Айвику на Haskell. И попытка переписать с F# на Haskell была неудачной. Нарвался на то, что компилятор Haskell предполагает ссылочную прозрачность, и соответственно оптимизирует код. Это решается с помощью прагм, что некрасиво, но главная нехорошесть была в другом. У меня там возникал вложенный двухэтажный одноименный тип в сигнатурах, что было прямым указанием на какую-то логическую ошибку.
Прояснение пришло не сразу. Сначала я пытался все выразить в рамках одного вычисления, т.е. монады. Все кардинально упростилось, когда я понял, что мне нужно ввести несколько вычислений. В итоге полностью избавился от нехорошего unsafePerformIO, сигнатуры функций стали понятными с первого взгляда, код целиком стал ссылочно-прозрачным. Просто красота! Так родилась версия Айвики для Haskell.
Потом я уже переписал обратно c Haskell на F#. Пришлось пойти не некоторые упрощения и хитрости, но в целом, версия Айвики на F# примерно соответствует своей старшей сестрице, хотя и будет немного слабее. Именно переписанная версия теперь используется у меня в визуальной системе моделирования.
Возвращаясь к исходной теме. Даже если имитационное моделирование не входит в область ваших интересов, то может быть интересно то, что VisualAivika позволяет создавать так называемые Casual Loop Diagrams (CLD), область применения которых довольно широка. Это Systems Thinking или системное мышление.
Ниже показан пример такой диаграммы, которую я накидал в своей VisualAivika за минуту-две.
Здесь знак плюса указывает на положительную связь, знак минуса - на отрицательную. Видим, что приведенный цикл является устойчивым. Нет ни бурного роста, ни активного падения.
Функциональное программирование здесь при том, что на конечном этапе исходная система диффуров преобразуется в модель в терминах моей библиотеки Айвика, которая написана на языке F#, который, как говорят его создатели, functional first.
Может быть интересна история создания Айвики. Первоначальная идея возникла при изучении Haskell, но я очень быстро переключился реализовывать идею на F#. Первая версия на F# была ужасна. Ее до сих пор можно найти на простора интернета, но я не хочу давать ссылку на нее - пусть останется для истории.
Мне всегда было очень интересно реализовать Айвику на Haskell. И попытка переписать с F# на Haskell была неудачной. Нарвался на то, что компилятор Haskell предполагает ссылочную прозрачность, и соответственно оптимизирует код. Это решается с помощью прагм, что некрасиво, но главная нехорошесть была в другом. У меня там возникал вложенный двухэтажный одноименный тип в сигнатурах, что было прямым указанием на какую-то логическую ошибку.
Прояснение пришло не сразу. Сначала я пытался все выразить в рамках одного вычисления, т.е. монады. Все кардинально упростилось, когда я понял, что мне нужно ввести несколько вычислений. В итоге полностью избавился от нехорошего unsafePerformIO, сигнатуры функций стали понятными с первого взгляда, код целиком стал ссылочно-прозрачным. Просто красота! Так родилась версия Айвики для Haskell.
Потом я уже переписал обратно c Haskell на F#. Пришлось пойти не некоторые упрощения и хитрости, но в целом, версия Айвики на F# примерно соответствует своей старшей сестрице, хотя и будет немного слабее. Именно переписанная версия теперь используется у меня в визуальной системе моделирования.
Возвращаясь к исходной теме. Даже если имитационное моделирование не входит в область ваших интересов, то может быть интересно то, что VisualAivika позволяет создавать так называемые Casual Loop Diagrams (CLD), область применения которых довольно широка. Это Systems Thinking или системное мышление.
Ниже показан пример такой диаграммы, которую я накидал в своей VisualAivika за минуту-две.
Здесь знак плюса указывает на положительную связь, знак минуса - на отрицательную. Видим, что приведенный цикл является устойчивым. Нет ни бурного роста, ни активного падения.
пятница, 12 июня 2015 г.
Обновленная Aivika for .NET
Открыл по лицензии GNU дополнительные компоненты к версии своей библиотеки имитационного моделирования Айвика, написанной на языке F#. Теперь по открытой лицензии доступны не только разработка и запуск модели в Visual Studio или Xamarin Studio, но можно также сохранять результаты, строить графики и т.п. Все это удовольствие автоматизируется несколькими дополнительными строками кода.
В дополнение к существующей документации в формате PDF выложил исходники примеров, которые охватывают наиболее известные области имитационного моделирования: системная динамика, дискретно-событийное моделирование (управляемое временем, событиями и процессами), базовое агентное моделирование.
Здесь замечу, что версия на Haskell по-прежнему остается более функциональной, и она имеет более чистый дизайн. В случае с F# пришлось пойти на некоторые упрощения. Зато доступна Visual Studio с IntelliSense, хотя лично я предпочитаю Aquamacs и runghc / cabal в терминале :)
понедельник, 4 мая 2015 г.
Зарелизил Aivika for .NET
Выпустил движок имитационного моделирования Aivika for .NET по двойной лицензии: GPLv3 и коммерческая. Коммерческая версия имеет дополнительные плюшки в виде модулей для быстрого и удобного возвращения результатов, обработки и анализа. Но сам движок полностью самодостаточен, и он лежит теперь на гитхабе:
https://github.com/dsorokin/aivika-fsharp-ce
https://github.com/dsorokin/aivika-fsharp-ce
пятница, 1 мая 2015 г.
Айвика для .NET Framework и Mono
Айвика для .NET Framework и Mono
Портировал свою библиотеку имитационного моделирования Айвику на .NET Framework и Mono. Если кратко, это такая библиотека, которая поддерживает большинство известных парадигм имитационного моделирования. Звучит очень амбициозно, но это действительно так. Можете проверить, взяв открытую версию для Haskell. Код доступен. Есть примеры. Есть документация. Даже Google очень уважает мою библиотеку по поисковой фразе «simulation library», хотя замечу, что его выдача бывает нестабильной и зависит от многих факторов.
Теперь есть порт для .NET и Mono. Написано на F#. В отличие от открытой версии для Haskell, этот порт закрыт, но доступна документация в формате PDF по ссылке в конце приведенной выше страницы Wiki. Больше 100 страниц с описанием основного API, примерами, графиками и т.п.
Что может дать новая версия?
Как и в случае Haskell, можно составлять имитационные модели практически любой степени сложности и нетривиальности, используя очень простую концепцию, где основные моделируемые активности представлены как вычисления. По сути, это функциональное программирование в чистом виде: монады, потоки, стрелки и т.п., но этим можно особо не заморачиваться, поскольку F# создает иллюзию простоты, насколько возможно.
Все настолько топорно устроено, что не может не работать. Чем больше проверяю на разных примерах, тем больше убеждаюсь, что метод работает. Иногда вношу неточности в примеры моделей, но потом обычно исправляюсь. Получаю такие же результаты, как в других источниках литературы, хотя последние иногда грешат :)
Библиотека охватывает такие вещи, как обыкновенные диффуры, так и вытесняющую многопроцессность для систем массового обслуживания. Например, вытеснение ресурса позволяет с легкостью моделировать поломку станков. А потоки с мультиплексированием позволяют моделировать станки параллельно.
По модели можно запустить вычислительный эксперимент и получить итоговую страницу HTML с графиками, гистограммами, таблицами в формате CSV и прочим, что позволяет проводить быстрый анализ модели, если нужно, экспортируя результаты в R для более детального изучения.
Теперь это все доступно на платформах .NET Framework и Mono. Работает на Windows, OS X и Linux. Можно составлять модели в удобном редакторе Visual Studio или Xamarin Studio с подсветкой типов и автодополнением. Возможно создание интерактивных тренажеров. Можно интегрировать с существующими решениями, использующими .NET.
воскресенье, 29 июня 2014 г.
Версия 1.3 моей библиотеки имитационного моделирования Айвики на Haskell
Вчера обновил документацию, а также новую версию моей библиотеки имитационного моделирования Айвики, написанную целиком на языке функционального программирования Haskell.
Айвика уже много лет умеет:
- системную динамику (обыкновенные диффуры и разностные уравнения);
- дискретно-событийное моделирование (управляемое временем, событиями и процессами);
- самые базовые вещи из агентного моделирования.
Примерно год назад добавил потоки данных и процессоры, которые позволяют на достаточно высоком уровне и декларативно описывать сети массового ожидания с очередями, серверами и прочими сущностями. Код выглядит близко к тому, как если бы мы описывали такую сеть с помощью диаграмм.
Совсем недавно добавил конечные автоматы, которые позволяют моделировать с некоторым упрощением цифровые схемы. Для интеграции со всем остальным эти автоматы синхронизируются с очередью событий. Схемы могут быть рекурсивными, могут иметь задержки на такт.
Все работает на единой схеме. Формализм и базовое API описаны в документе PDF на странице Wiki проекта Aivika (пока к сожалению, только на английском):
Сам код библиотеки полностью документирован с помощью комментариев haddock. Это стандартный для Haskell способ документирования API.
Для реализации я использовал очень много разных вещей из мира функционального программирования - ввел несколько монад и две стрелки. Многое взял из учебников по Haskell и F#. Библиотека по всей своей природе целиком принадлежит миру ФП, хотя и ориентирована на императивные вычисления: стохастику и прочее IO. Просто некоторые слишком узком понимают ФП, ограничивая себя рамками детерминированности, но забывая при этом, что IO вполне поддается ссылочной прозрачности. У меня нигде там нет unsafePerformIO, и это особый предмет гордости :)
Библиотека ориентирована на практику. Мало составить модель, нужно еще вывести результаты, как-то их обработать и представить в удобном виде при минимуме рутины. Для этого существуют дополнительные пакеты, которые позволяют автоматизировать имитационные эксперименты, где мы можем достаточно декларативно описать, какие данные мы хотим вывести и в каком виде.
Можем сохранить таблицы в файлы CSV, нарисовать графики, гистограммы, подсчитать сводную статистику по переменным, показать на специальном графике тренд и вероятные границы отклонения по правилу 3-х сигм.
В результате эксперимента создается файл HTML с результатами, который может быть просмотрен в любом современном браузере интернета.
Модель может иметь внешние параметры, которые могут быть случайными или быть прочитанными из файла в случае необходимости.
Например, это позволяет проводить анализ чувствительности тех или иных переменных по отношению к внешним параметрам посредством множественных запусков по методу Монте-Карло. Можем планировать эксперимент.
Вообще, моя библиотека предоставляет eDSL, который органично вписывается в язык Haskell. При определении модели мы можем использовать практически весь арсенал средств этого языка программирования общего назначения, что открывает просто фантастические возможности для описания очень сложных процессов, конечно, при соответствующем знании языка. Дополняет эти возможности то, что заявленные выше парадигмы имитационного моделирования реализованы на основе единой схемы - они все интегрированы между собой, и фактически сводятся друг к другу.
Библиотека со всеми пакетами размещена на официальном репозитории Hackage DB, который интегрирован с Haskell Platform. Используемая лицензия очень либеральна - BSD3. Код распространяется полностью в открытых исходниках.
На винде устанавливается так:
> cabal update
> cabal install aivika
> cabal install aivika-experiment
> cabal install aivika-experiment-chart
> cabal install aivika-experiment-diagrams
Первые три пакета помимо самого кода содержат еще и примеры. Особенно интересными могут быть примеры из третьего пакета, где выводятся графики, но для этого как раз нужен четвертый, который уже непосредственно рендерит графики.
На маке (OS X) и особенно линуксе лучше установить еще другой рендерер графиков:
$ cabal install aivika-experiment-cairo
Он использует библиотеку Cairo, и графики на мой взгляд получаются красивее.
Будет интересно получить комментарии и пожелания. Так же интересует, насколько вероятна возможность консалтинга. Готов рассмотреть взаимовыгодные и заманчивые предложения.
воскресенье, 25 августа 2013 г.
F# на юниксе
Оказывается, можно замечательно использовать F# на маке с помощью Mono и Xamarin Studio. Очень удобно, и мой проект от Visual Studio работает прекрасно. Попробовал редактировать и создавать файлы в Xamarin Studio. Мне понравилось. Даже лень было сегодня загружаться в винду, где у меня установлена Visual Studio.
Надо сказать, что ребята из Xamarin достигли заметного прогресса. Что меня больше всего потрясло, так это то, что в некоторых моих тестах Mono заметно обгоняет .NET, делая поправку на то, что гонял я тесты на одной машине, но под разными операционками, да и тесты, вероятно были несколько специфическими. Ни за что бы не поверил в возможность такого еще пару лет назад!
суббота, 10 августа 2013 г.
А вдруг есть такой чудесный плагин для Scala?
Пока самые лучшие и знаменитые наши умы заняты очень серьезным мероприятием, хочу поделиться со всеми остальными о наболевшем.
Есть у меня одна уже работающая задумка, но мне нужен для Scala хороший и удобный синтаксический сахар для монад (эх, еще бы для стрелок…). Мечтаю о чем-то подобном computation expressions из F# - это такой аналог нотации do для языка, в котором нет классов типов. Как понимаю, нужен плагин к компилятору в случае Scala.
Ни встроенный for-comprehension, ни плагин продолжений не впечатляют нисколько. Отчасти они дублируют друг друга, но ни одно из них не решает свою задачу хорошо в моем понимании, давно извращенным другими языками. В общем, тот случай, где количество не переходит в качество, и даже не помышляет о том.
Очень хотел использовать Scala, но сейчас пребываю в полной печали. Для моей задачи технически идеально подходит Haskell, но я хочу продвинуть библиотеку в широкие массы, а потому Haskell пока хорош только как полигон для выработки, обкатки и кристаллизации моих безумных идей, и здесь он свою миссию уже выполнил на все 350% с блеском и шиком. Но сейчас хочется получить уже широкую аудиторию из исключительно меркантильных соображений, а потому интересует Scala.
пятница, 22 марта 2013 г.
Комментарий о хвостовой рекурсии
Как известно, дьявол скрывается в деталях. Порою, небольшая деталь может сильно изменить смысл. Получается эффект бабочки. Что-то такое иногда происходит с пониманием хвостовой рекурсии. Мне всегда эта тема казалось сложной.
В прошлом году вышел замечательный перевод книги Пола Грэма "ANSI Common Lisp". В оригинале этой книги на странице 216 есть такое предложение: "A good compiler can compile a tail call into a goto, and so can compile a tail-recursive function into a loop". Дальше идет довольно общее описание того, как это может быть сделано.
Проблема в том, что без знания контекста тот текст можно неправильно истолковать. Все встает на свои места, если обратиться к книге PAIP Питера Норвига, которую Пол Грэм безусловно читал. В той книге приведена некая абстрактная машина. Там действительно хвостовая рекурсия компилируется в циклы, но в циклы не языка высокого уровня, а в циклы ассемблера той абстрактной машины (фактически через goto). Вот, в чем загвоздка.
Многие почему-то считают, что хвостовую рекурсию можно всегда преобразовать в циклы Scala, F# или Common Lisp. Мне кажется это неправильным. Можно придумать контр-пример. Достаточно обернуть рекурсивный вызов в лямбду и дальше передать эту лямбду другой функции. Например, компилятор Scala не сможет это превратить в цикл на уровне явовского байт-кода, а на уровне абстрактной машины из PAIP цикл получился бы сам собою.
вторник, 19 марта 2013 г.
Функциональная чистота и ссылочная прозрачность
Есть мнение, что термин "ссылочная прозрачность" является ненадежным, поскольку люди до сих пор не могут договориться об его точном определении, точно также как не могут договориться о том, какие языки программирования считать функциональными, а какие - нет. Тем не менее, термин широко встречается в литературе.
Что касается "функциональной чистоты", то с нею более-менее понятно: результат зависит только от входных параметров, и функция не производит внешних побочных эффектов в том смысле, что не изменяет состояние окружающего мира. Для статически типизированных языков это обычно означает, что все, что функция делает и производит, описано в ее сигнатуре. Тут я изучал самые разные источники, включая учебники по Common Lisp, Haskell, F# и Scala. Трактовка везде примерно такая, почему-то за исключением одного русскоязычного учебника (не буду называть).
Для определенности возьмем такую вариацию этих терминов из еще невышедшей книги "Functional Programming in Scala":
"An expression e is referentially transparent if for all programs p, all occurrences of e in p can be replaced by the result of evaluating e, without affecting the observable behavior of p. A function f is pure if the expression f(x) is referentially transparent for all referentially transparent x."
Здесь содержатся одно из возможных определений для ссылочной прозрачности и вывод о том, что если выражение f(x) ccылочно-прозрачно для всех ссылочно-прозрачных x, то функция f является чистой. Определение чистоты в книге дается обычное в другом месте. Меня смущает то, что хотя используется слово "if" в последнем предложении, трактуется оно почему-то как "if and only if".
Вопрос номер один. Правильно ли я понимаю, что в такой постановке ссылочная прозрачность является достаточным условием для функциональной чистоты, и оба эти понятия, вообще говоря, не эквивалентны в математическом смысле, т.е. ссылочная прозрачность уже не является необходимым условием чистоты?
Второе. У меня складывается ощущение, что ссылочная прозрачность жестко привязана к конкретному языку программирования, тогда как свойство функции быть чистой является в большой степени над-языковым. Припоминая ассемблер PDP-11, сдается мне, что даже на уровне ассемблера можно оперировать чистотой, если ввести определенные допущения для стека (или стеков). Это так? Если да, то тогда оба понятия действительно не могут быть эквивалентными уже по этому.
В общем, прошу вразумить и поставить на путь истинный.
понедельник, 10 декабря 2012 г.
Ряд Фибоначчи
Давеча рекламировал свои обобщенные последовательности (Generic Sequences), а какие могут быть последовательности без ряда Фибоначчи? Это что-то вроде обязательного ритуала. Опустим здесь тот факт, что я создал эту библиотеку для вполне практической задачи, когда мне понадобилось быстро и эффективно сравнивать деревья, а там ленивые последовательности дюже полезны.
Итак, ниже приведена рабоче-крестьянская версия, которая выдает ленивую бесконечную последовательности ряда Фибоначчи через то, что я назвал Sequence Comprehension:
(defparameter *fibs-1*
(with-seq/cc
(do ((a 1 b)
(b 1 (+ a b)))
(nil)
(yield/cc a))))
Очень просто, не правда ли?
Теперь каноническая версия через поток:
(defparameter *fibs-2*
(reclet
((fibs (seq->stream
(seq-cons
1 (seq-cons
1 (seq-map
(lambda (x)
(+ (first x) (second x)))
(seq-zip
(delay-seq fibs)
(delay-seq (seq-cdr fibs)))))))))
fibs))
Проверка:
? (seq->list (seq-take 20 *fibs-1*)) (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765) ? (seq->list (seq-take 20 *fibs-2*)) (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
Дополнение.
Чтобы не сложилось неправильного впечатления, сейчас покажу наиболее эффективную реализацию, которая только возможна в рамках моей библиотеки.
(defparameter *fibs-3*
(make-seq
(labels ((traverse (a b)
(enum-cons a (traverse b (+ a b)))))
(traverse 1 1))))
Основная идея заключается в том, что мы работаем как с обычным списком, что очень удобно при обходе индуктивных/рекурсивных структур данных. Собственно, все комбинаторы написаны у меня в таком стиле.
И если вам по какой-то причине не нравятся комбинаторы, то результат можно получить с помощью известного макроса iter, для которого я добавил конструкцию in-seq:
? (iter (for i from 1 to 20)
(for x in-seq *fibs-3*)
(collect x))
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
Подписаться на:
Сообщения (Atom)


