############################################################## # # 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