##############################################################
#
# Export fuctions of Bayesian Network Library for Ruby
#
# Author: Sergio Espeja ( http://www.upf.edu/pdi/iula/sergio.espeja, sergio.espeja at gmail.com )
#
# Developed in: IULA ( http://www.iula.upf.es ) and
# in bee.com.es ( http://bee.com.es )
#
# == Export formats implemented
# * dot (Graphviz .dot files)
# * xbn (Microsoft Belief Networks)
#
##############################################################
#
class BayesNet < DirectedAdjacencyGraph
def to_dot(bn = self)
#TODO: label relations between nodes
#TODO: print information about probabilities tables?
bn.to_dot_graph.to_s
end
def to_xbn(bn = self)
#TODO beautify code using REXML
xbn_str = "\n"
xbn_str += "\n"
xbn_str += "MSR DTAS XML\n"
xbn_str += " 1.0\n"
xbn_str += " Microsoft Research DTAS\n"
xbn_str += " \n"
xbn_str += " Notes on the diagram\n"
xbn_str += " \n"
xbn_str += " \n"
xbn_str += " \n"
xbn_str += xbn_variables(bn)
xbn_str += xbn_structure(bn)
xbn_str += xbn_distributions(bn)
xbn_str += " \n"
xbn_str += "\n"
end
private
def xbn_variables(bn = self)
xbn_str = "\n"
#
# n_intr_le
# Yes
# No
#
x_pos_index = Array.new(bn.deep, 0); x0_pos = Array.new(bn.deep, 0)
num_nodes_in_deep = Array.new(bn.deep, 0)
# get how many nodes are in each deep level to calcule the offset
bn.vertices.each { |node| num_nodes_in_deep[node.deep-1] += 1 }
x0_pos = num_nodes_in_deep.collect { |num_nodes|
a = num_nodes * 6500
b = num_nodes_in_deep.max * 6500
(b-a)/2
}
bn.nodes_ordered_by_breath_first_search.each { |node|
x_pos = x0_pos[node.deep-1] + (6500*x_pos_index[node.deep-1])
y_pos = 2500 + (5000*(node.deep-1))
x_pos_index[node.deep-1] += 1;
xbn_str += "\n"
xbn_str += "#{node.name}\n"
if (node.outcomes - [true,false]).empty?
xbn_str += "Yes\n"
xbn_str += "No\n"
else
node.outcomes.each {|o| xbn_str += "#{o}\n"}
end
xbn_str += "\n"
}
xbn_str += "\n"
end
def xbn_structure(bn = self)
xbn_str = "\n"
bn.nodes_ordered_by_dependencies.each { |node|
next if node.root? #node.num_parents > 0
node.parents.each { |parent|
xbn_str += "\n"
}
}
#
#
#
#
#
#
xbn_str += "\n"
end
def xbn_distributions(bn = self)
xbn_str = "\n"
# With parents
#
#
#
#
#
#
#
#
# 0.7 0.3
# 0.3 0.7
# 0.3 0.7
# 0 1
# 1 0
# 0.7 0.3
# 0.7 0.3
# 0.3 0.7
#
#
bn.nodes_ordered_by_dependencies.each { |node|
next if node.root?
xbn_str += "\n"
xbn_str += " \n"
xbn_str += " \n"
node.parents.each { |parent| xbn_str += " " }
xbn_str += " \n"
xbn_str += " \n"
boolean_combinations = generate_combinations(node.parents)
boolean_combinations.each { |boolean_combination|
probs = node.outcomes.collect { |n_assignment|
p "n_assignment: " + n_assignment.to_s
node.get_probability(n_assignment, boolean_combination) }
bc_str = boolean_combination.collect {|b| (b)?"0":"1"}.join(" ")
xbn_str += " " + probs.join(" ") + " \n"
#0.7 0.3
}
xbn_str += " \n"
xbn_str += "\n"
}
# Without parents
#
#
#
# 0.3 0.7
#
#
bn.nodes_ordered_by_dependencies.each { |node|
next unless node.root?
xbn_str += "\n"
xbn_str += " \n"
xbn_str += " \n"
probs = [true, false].collect { |n_assignment| node.get_probability(n_assignment) }
xbn_str += " " + probs.join(" ") + " \n"
xbn_str += " \n"
xbn_str += "\n"
}
xbn_str += "\n"
end
end