Class: MiniPGM::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/mini_pgm/model.rb

Overview

Represents a Probabilistic Graphical Model (PGM)

Defined Under Namespace

Classes: ModelError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*edges) ⇒ Model

Returns a new instance of Model.



32
33
34
35
# File 'lib/mini_pgm/model.rb', line 32

def initialize(*edges)
  @edges = sort_edges(edges)
  @nodes = reduce_edges(edges)
end

Instance Attribute Details

#edgesObject (readonly)

Edges between individual nodes, sorted by label of the outgoing edge, e.g:

Pollution -> Cancer
Smoker -> Cancer


18
19
20
# File 'lib/mini_pgm/model.rb', line 18

def edges
  @edges
end

#errorObject (readonly)

most recent error after calling valid?



30
31
32
# File 'lib/mini_pgm/model.rb', line 30

def error
  @error
end

#nodesObject (readonly)

Lookup table of labelled nodes, each associated with a set of labels for all incoming edges, e.g:

{ Pollution, Smoker } -> Cancer -> { }
{ } -> Pollution -> { Cancer }
{ } -> Smoker -> { Cancer }


27
28
29
# File 'lib/mini_pgm/model.rb', line 27

def nodes
  @nodes
end

Instance Method Details

#add_cpd(cpd) ⇒ Object

Raises:



37
38
39
40
41
42
43
# File 'lib/mini_pgm/model.rb', line 37

def add_cpd(cpd)
  node = @nodes[cpd.variable.label]
  raise ArgumentError, "node does not exist for label #{node.label}" unless node

  check_cpd_evidence!(cpd.evidence.map(&:label), node.incoming_edges)
  node.cpd = cpd
end

#to_sObject



45
46
47
# File 'lib/mini_pgm/model.rb', line 45

def to_s
  ['Edges:', edges_to_s, '', 'Nodes:', nodes_to_s, '', 'Valid:', valid?, ''].join("\n")
end

#valid?Boolean

Returns:



60
61
62
63
64
65
66
67
# File 'lib/mini_pgm/model.rb', line 60

def valid?
  @error = nil
  validate!
  true
rescue ModelError => e
  @error = e
  false
end

#validate!Object



49
50
51
52
53
54
55
56
57
58
# File 'lib/mini_pgm/model.rb', line 49

def validate!
  @nodes.each_value do |node|
    raise ModelError, "node '#{node.label}' does not have a CPD" unless node.cpd
  end

  # validate cardinality between nodes for each edge
  @edges.each do |edge|
    validate_cardinality!(@nodes[edge.to], @nodes[edge.from])
  end
end