nflow v0.2.0

топ 100 блогов love5an30.01.2011 Полностью переработал модель распространения данных в neural-flow 
Не без помощи nflow v0.2.0 [info]dmitry_vk  в [email protected], надо сказать.

Библиотека стала больше походить на cells. Но, её интерфейс и dataflow-модель - намного проще и удобнее в использовании.

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

Что значит "автоматически"? Это значит, что, в отличие от предыдущей версии, теперь не нужно руками делать add-connection и remove-connection. Нейрон сам вычислит, с кем он связан и соответствующим образом распространяет поток данных.

Что значит "динамически"? Это значит, что связи между нейронами создаются и изменяются во время выполнения программы, на основе взаимодействия нейронов, а не на основе каких-либо статически заданных формул. Короче, как и у настоящих нейронов.
А связи между настоящими нейронами зависят от множества факторов - от расположения нейрона, от количества алкоголя в крови, да и даже от фазы луны.

Кстати, о фазе луны. Вот сразу  пример :)

(defparameter *input* (neuron ()
nil))

(defparameter *first* (neuron ()
(neuron-value *input*)
:first))

(defparameter *second* (neuron ()
(neuron-value *input*)
:second))

(defparameter *output* (neuron ()
(if (evenp (floor (get-universal-time) ;;количество секунд с 1 января 1900 года
(* 60 60 24 29.5 1/2))) ;;количество секунд в лунном полуцикле
(neuron-value *second*)
(neuron-value *first*))))

(defun query-lunar-phase ()
(update-neuron *input*)
(neuron-value *output*))

В первую половину лунного цикла нейрон *output* будет узнавать значение лунной фазы из нейрона *first*, а во вторую половину - из *second*. Ну, довольно очевидно, что на сегодняшний день он будет хранить значение :second :)

Макрос neuron это просто удобная форма записи (make-instance 'neuron ...)
Выглядит он так:

(defmacro neuron ((&optional (neuron-class 'neuron) (value-var (gensym)) &rest args)
&body body)
(check-type value-var symbol)
`(make-instance ',neuron-class
:function (lambda (,value-var) (declare (ignorable ,value-var)) ,@body)
,@args))
Таким образом, что каждый нейрон представляет собой функтор, являющийся звеном в некоторой цепочке вычислений.

Как видно, в функции query-lunar-phase мы не указываем явно, что нам нужно обновить именно нейрон *output*, который собственно и вычисляет фазу луны. Напротив, мы обновляем только нейрон *input*. И тем не менее, поток данных проходит весь путь от *input* к *output*.

Как это достигается? Очень просто - вызов функции neuron-value записывает нейрон, из которого мы эту функцию вызываем, в список зависимостей нейрона, к которому мы обращаемся.

(defun neuron-value (neuron)
(declare (type neuron neuron))
(when *current-neuron*
(pushnew *current-neuron* (slot-value neuron '%dependents) :test #'eq))
(slot-value neuron '%value))
Сама же функция-обработчик-данных нейрона, вызывается, среди прочего, при его создании.

Таким образом, связи между нейронами зависят исключительно от того, куда нейрон дотягивается "дендритами" во время выполнения программы. Для вышеописанного примера, на сегодняшнее число, связи будут выглядеть так:
нейроны
Прослеживается аналогия с монадами - нейрон, как и монада, это некое звено в цепочке вычислений. Отличие в том, что функция нейрона выполняет роли как bind, так и return; впрочем, я думаю позже ввести "синапсы"  - обобщенные функции, которые бы обрабатывали значение, полученное из нейрона, и значение, возвращаемое самим функтором. 

Важное отличие от традиционного FRP(functional reactive programming) состоит в том, что в моей библиотеке используется data-driven(push-based, eager) модель, в противоположность demand-driven(pull-based, lazy) моделям, которые обычно используются в FRP-фреймворках.

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

Напоследок, еще один пример:

;;В объектах классов, являющихся экземплярами метакласса dataflow-class
;; все слоты являются нейронами
;; При этом, мы можем продолжать с ними работать как с обычными слотами.
(defclass textbox (dataflow-object)
((text :initform "" :accessor textbox-text))
(:metaclass dataflow-class))

(defclass checkbox (dataflow-object)
((checked :initform nil :accessor checkbox-checked))
(:metaclass dataflow-class))

(defun event-example ()
(let* ((textbox (make-instance 'textbox))
(checkbox (make-instance 'checkbox)))
;;bindf это обобщенная функция, устанавливающая нейрону или слоту(как здесь)
;; новую функцию-обработчик, или же устанавливающая слоту новый нейрон.
(bindf (lambda (old-value)
(declare (ignore old-value))
(if (checkbox-checked checkbox)
"Checked"
"Unchecked"))
textbox
:slot 'text)
;;просто некий нейрон, который будет нас оповещать об изменениях
;; слота text у textbox'а
(let ((observer (neuron ()
(format t "Text changed. New value: ~s"
(textbox-text textbox)))))
(declare (ignorable observer))
checkbox)))


;;При изменении слота checked, слот textbox'a также будет изменяться -
;; устанавливаться в "Checked" или "Unchecked" соответственно.
;; А при изменении самого слота text, этим, или
;; другим способом(например через (setf slot-value)),
;; об изменении нас будет оповещать нейрон observer

Оставить комментарий

Архив записей в блогах:
Обычные люди, которые далеки от военной истории, могут спорить, что доспехи остались в рыцарской эпохе. Как раз тогда, когда появилось огнестрельное оружие, которое "пробивало рыцарские латы как картон". Это не так. Доспехи, а тем более необычные доспехи, существовали не только в ...
Потеплело, больше не ношу шапку или берет. Из-за ветра для презентабельности укладываю волосы кремом, а затем закрепляю лаком. Съездила туда-обратно, как видите, ничего не нарушилось, волосы лежат аккуратно. Как вам кажется, на собеседование так нормально ходить, или лучше подбирать с ...
Тут ЖЖ разродилось вопросом: Вы считаете себя патриотом? Если да, то как это выражается? Смотреть ответы (938) Ну, что сказать. А нужно как-то каждый день выражать свой патриотизм? Вот я люблю своих родителей, свою жену, своих детей, но разве ...
Ещё некоторые цифры налоговой.   По состоянию на 01.01.2010 р. предприятия торговли имели такую налоговую нагрузку по налогу на прибыль: Фуршет - 0,24; ЭКО - 0,01; Край -- 0,75; АТБ - 0,12; Эльдорадо - 0,7; Фокстрот - 0,3; Новая линия - 0,7; Эпицентр - 1,66; Караван - 0,3; ...
МОСКВА, 12 апр - РИА Новости. Минпросвещения России исключит обществознание из программы 6-8 классов с 1 сентября 2025 года, изучение этого предмета будет начинаться в 9 классе, общее число часов составит 34, по одному часу в неделю, соответствующий документ опубликован на ...