Class: Fathom::CPMNode

Inherits:
Node
  • Object
show all
Defined in:
lib/fathom/node/cpm_node.rb

Overview

Conditional Probability Matrix to join two nodes

Instance Attribute Summary

Attributes inherited from Node

#description, #distribution, #name, #values

Instance Method Summary collapse

Methods inherited from Node

#add_child, #add_parent, #children, #inspect, #name_sym, #parents, #register_child, #register_parent, #simple_inspect

Constructor Details

#initialize(opts = {}) ⇒ CPMNode

Returns a new instance of CPMNode.



6
7
8
9
10
11
12
# File 'lib/fathom/node/cpm_node.rb', line 6

def initialize(opts={})
  ensure_belief_nodes(opts)
  super(opts)
  assert_name
  assert_description
  assert_cpm
end

Instance Method Details

#childObject



18
19
20
# File 'lib/fathom/node/cpm_node.rb', line 18

def child
  children.first
end

#likelihood(value) ⇒ Object Also known as: l

Returns a vector of likelihoods for each parent value, given the child value



76
77
78
79
80
# File 'lib/fathom/node/cpm_node.rb', line 76

def likelihood(value)
  GSL::Vector.alloc(
    *parent.labels.map {|parent_label| probability(parent.name_sym => parent_label, child.name_sym => value)}
  )
end

#odds(opts = {}) ⇒ Object Also known as: o



69
70
71
72
# File 'lib/fathom/node/cpm_node.rb', line 69

def odds(opts={})
  p = probability(opts)
  return p / (1 - p)
end

#parentObject



14
15
16
# File 'lib/fathom/node/cpm_node.rb', line 14

def parent
  parents.first
end

#probability(opts = {}) ⇒ Object Also known as: p

Filter values from the matrix. Allows us to grab multiple rows and columns if desired. If the rows or columns aren’t filtered, all values are assumed to be desired.

This filters both the child columns and the parent rows

This only filters the child columns

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fathom/node/cpm_node.rb', line 32

def probability(opts={})
  # Are we using long descriptions for the return value?
  # If so, we'll use a hash to describe it without having to parse the value out of a string later.
  describe = opts.delete(:describe) || false
  
  # Is something unknown being asked for?
  allowed = [parent.name_sym, child.name_sym]
  unknown_keys = opts.reject {|k, v| allowed.include?(k)}
  raise ArgumentError, "Unknown node: #{unknown_keys.inspect}" unless unknown_keys.empty?

  # Values for the desired child and parent values
  child_values = Array(opts[self.child.name_sym] || self.child.labels)
  parent_values = Array(opts[self.parent.name_sym] || self.parent.labels)
  
  # Indices in the matrix for the desired values
  child_indices = child_values.map {|c| self.child.labels.index(c)}
  parent_indices = parent_values.map {|c| self.parent.labels.index(c)}

  # Collect the filtered values from the matrix
  value = parent_indices.inject(0.0) do |sum, row|
    sum += child_indices.inject(0.0) do |s, col|
      s += matrix.get(row, col)
    end
  end
  
  return value unless describe

  label = "P(" + 
    child_values.map(&:to_s).join(" or ") + 
    " | " + 
    parent_values.map(&:to_s).join(" or ") + 
    ")"
  { label => value }

end