Лучший способ запрограммировать "Ruby-подобную" сеть влияния в Ruby?

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

Мне интересно, какой самый чистый способ реализовать это в Ruby?

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

Спасибо за вашу помощь!

Обновление: Похоже, что EventMachine может сделать эту работу... но он кажется более приспособленным к небольшому количеству "узлов"

3 ответа

Это звучит как хорошая ситуация для наблюдателя. Вот пример этого в ruby:

require 'observer'

class Node
  attr_accessor :id
  @@current_node_id = 0
  def initialize
    @@current_node_id += 1
    id = @@current_node_id
  end
  include Observable

  attr_reader :value


  protected
  def value=(new_value)
    return if @value == new_value
    old_value = @value
    @value = new_value
    changed
    notify_observers(id, old_value, @value)
  end
end


class ValueNode < Node
  def initialize(initial_value)
    super()
    @value = initial_value
  end

  def value=(new_value)
    super(new_value)
  end
end


class SumNode < Node
  def initialize(*nodes)
    super()
    @value = nodes.map(&:value).inject(0, &:+)
    nodes.each do |node|
      node.add_observer(self)
    end
  end


  def update(id, old_value, new_value)
    self.value = self.value - old_value + new_value
  end
end


def test
  v1 = ValueNode.new 4
  v2 = ValueNode.new 8
  sum = SumNode.new(v1, v2)
  sum2 = SumNode.new(v1, sum)
  v2.value = 10
  p sum.value
  p sum2.value
end


test()

Обратите внимание, как значение SumNode не пересчитывается при каждом запросе - вместо этого он обновляется при обновлении одного из его узлов значений. Это работает рекурсивно, так что внутренний SumNodes также запускать обновления. Поскольку уведомление включает в себя уникальный id узла, можно написать более сложный Node типы, такие как те, которые содержат формулы.

См. http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html для получения дополнительной информации о Observable.

Это похоже на часто используемую парадигму Twitter, где обновления одного пользователя рассылаются всем его последователям. Чтобы сделать это эффективно, вы должны хранить два списка для данного человека: один с людьми, за которыми он следует, а другой с людьми, которые следуют за ним. Вы можете сделать то же самое для списка узлов. Когда узел изменяется, вы можете быстро найти узлы, на которые влияет этот узел. Когда связь исчезнет, ​​вам понадобится "прямой" список, чтобы узнать, из каких списков "удалить" обратную связь.

Вы можете хранить эти списки в двухмерных массивах или в чем-то вроде Redis. Я не очень понимаю, как вписывается EventMachine.

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

Существует несколько способов взаимодействия с Neo4J из Ruby:

  • Вы можете использовать JRuby и его интерфейс Java.
  • Используйте его REST API
  • Используйте neo4j.rb или одну из других библиотек интерфейса Ruby.
Другие вопросы по тегам