2011-10-04 16 views
14

Estoy construyendo un sistema en Clojure que consume eventos en tiempo real y actúa según la cantidad de mensajes similares recibidos recientemente. Me gustaría implementar esto usando un puntaje de experiencia reciente basado en el enfriamiento newtoniano.Mapa reciente en clojure usando enfriamiento newtoniano

En otras palabras, cuando llega un evento, quiero poder asignarle una puntuación entre 1.0 (nunca antes, o "temperatura ambiente" en la ecuación de Newton) y 10.0 (caliente y caluroso, ha ocurrido varias veces) en el último minuto). Tengo una vaga idea de cómo es esta estructura de datos: cada "tipo de evento" es una clave de mapa, y cada valor de mapa debe contener un conjunto de marcas de tiempo para eventos previos y quizás un promedio continuo de la corriente " calentar "para ese tipo de evento, pero no puedo entender cómo comenzar a implementarlo más allá de eso. Específicamente, tengo problemas para averiguar cómo pasar de la ecuación real de Newton, que es muy genérica, y aplicarla a este escenario específico.

¿Alguien tiene punteros? ¿Podría alguien sugerir un "algoritmo de puntuación de lo reciente" más simple para comenzar, que podría ser reemplazado por un enfriamiento newtoniano en el futuro?

EDIT: ¡Aquí hay algunos códigos de clojure! Se refiere a los eventos como letras, pero podría reutilizarse para tomar cualquier otro tipo de objeto.

(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))))) 
+0

+1 para una gran pregunta. Estaré interesado en ver las respuestas que obtienes. –

+0

+1 también. Y acaba de agregar la etiqueta 'algorithm'. – 4e6

Respuesta

5

En ausencia de cualquier evento, la solución a la ecuación de enfriamiento es la disminución exponencial. Decir T_0 es la temperatura al comienzo de un período de enfriamiento, y dt es el paso de tiempo (calculado a partir de la hora del sistema o lo que sea), ya que usted evaluó que la temperatura sea T_0:

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

Desde sus eventos son impulsos discretos, y que haya una temperatura máxima, que desea una relación dada por evento:

T_post_event = T_pre_event + (T_max - T_pre_event)/num_events_to_heat 

Algunas notas:

  • t_cooling es el momento para que las cosas se enfríen por un factor de 1/e = 1/(2.718...).

  • num_events_to_heat es la cantidad de eventos requeridos para tener un efecto comparable al T_max. Probablemente debería ser un valor positivo moderadamente grande (por ejemplo, 5.0 o más). Tenga en cuenta que si num_events_to_heat==1.0, cada evento reiniciará la temperatura a T_max, lo que no es muy interesante, por lo que el valor debería ser al menos superior a uno.

  • Teóricamente, tanto la calefacción como la refrigeración nunca deberían alcanzar las temperaturas máxima y mínima, respectivamente (suponiendo que los parámetros se establezcan como se indicó anteriormente, y que se inicie en algún punto intermedio). En la práctica, sin embargo, la naturaleza exponencial del proceso debe acercarse lo suficiente como para no hacer ninguna diferencia ...

  • Para implementar esto, solo necesita almacenar la marca de tiempo y la temperatura de la última actualización. Cuando reciba un evento, realice un paso de enfriamiento, luego un evento de calentamiento y actualícelo con la nueva temperatura y fecha y hora.

  • Tenga en cuenta que las consultas de solo lectura no requieren una actualización: puede calcular el enfriamiento desde la última actualización.

+0

t_cooling es una "constante de tiempo": tiempo para enfriar hasta el 36.8% del delta original. Esta es una respuesta genial. Muestra una buena comprensión de la física del enfriamiento de una masa puntual y la aplica de forma novedosa. – duffymo

Cuestiones relacionadas