Карта последних в clojure с использованием ньютоновского охлаждения - PullRequest
14 голосов
/ 04 октября 2011

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

Другими словами, когда приходит событие, я хочу иметь возможность присвоить ему оценку от 1,0 (никогда раньше не было или «температура окружающей среды» в уравнении Ньютона) до 10,0 (горячее горячее горячее, произошлонесколько раз за последнюю минуту).

У меня есть смутное представление о том, как выглядит эта структура данных - каждый «тип события» является ключом карты, и каждое значение карты должно содержать некоторый набор временных меток для предыдущих событий.и, возможно, скользящее среднее значение текущей «высокой температуры» для этого типа события, но я не могу понять, как начать реализовывать дальше.В частности, мне трудно понять, как перейти от фактического уравнения Ньютона, которое является очень общим, и применить его к этому конкретному сценарию.

Есть ли у кого-нибудь указатели?Может ли кто-нибудь предложить более простой «алгоритм оценки недавности», чтобы начать меня, который можно было бы заменить ньютоновским охлаждением на дороге?

РЕДАКТИРОВАТЬ : Вот некоторый код clojure!Он ссылается на события как на буквы, но, очевидно, может быть перенаправлен на любой другой объект.

(ns heater.core
    (:require [clojure.contrib.generic.math-functions :as math]))

(def letter-recency-map (ref {}))

(def MIN-TEMP 1.0)
(def MAX-TEMP 10.0)
;; Cooling time is 15 seconds
(def COOLING-TIME 15000)
;; Events required to reach max heat
(def EVENTS-TO-HEAT 5.0)

(defn temp-since [t since now]
    (+
        MIN-TEMP
        (*
            (math/exp (/
                (- (- now since))
                COOLING-TIME))
            (- t MIN-TEMP))))

(defn temp-post-event [temp-pre-event]
    (+ temp-pre-event
        (/
            (- MAX-TEMP temp-pre-event)
            EVENTS-TO-HEAT)))

(defn get-letter-heat [letter]
        (dosync
            (let [heat-record (get (ensure letter-recency-map) letter)]
            (if (= heat-record nil)
                (do
                (alter letter-recency-map conj {letter {:time (System/currentTimeMillis) :heat 1.0}})
                MIN-TEMP)
                (let [now (System/currentTimeMillis)
                     new-temp-cooled (temp-since (:heat heat-record) (:time heat-record) now)
                     new-temp-event (temp-post-event new-temp-cooled)]
                     (alter letter-recency-map conj {letter {:time now :heat new-temp-event}})
                    new-temp-event)))))

1 Ответ

5 голосов
/ 04 октября 2011

В отсутствие каких-либо событий решение уравнения охлаждения является экспоненциальным затуханием.Скажите T_0 - это температура в начале периода охлаждения, а dt - это временной шаг (рассчитанный по системному времени или как-то еще), поскольку вы оценили температуру как T_0:

T_no_events(dt) = T_min + (T_0 - T_min)*exp(- dt / t_cooling)

Поскольку ваши события представляют собой дискретные импульсы, и у вас есть максимальная температура, вам нужно заданное соотношение для каждого события:

T_post_event = T_pre_event + (T_max - T_pre_event) / num_events_to_heat

Некоторые примечания:

  • t_coolingвремя остывания вещей с коэффициентом 1/e = 1/(2.718...).

  • num_events_to_heat - это число событий, необходимое для получения эффекта, сравнимого с T_max.Вероятно, это должно быть умеренно большое положительное значение (скажем, 5.0 или больше?).Обратите внимание, что если num_events_to_heat==1.0, то каждое событие будет сбрасывать температуру до T_max, что не очень интересно, поэтому значение должно как минимум быть больше единицы.

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

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

  • Обратите внимание, что запросы только для чтения не требуют обновления:Вы можете просто вычислить охлаждение с момента последнего обновления.

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