/** * QBInference.java * @author Fabio G. Cozman * Copyright 1996 - 1999, Fabio G. Cozman, * Carnergie Mellon University, Universidade de Sao Paulo * fgcozman@usp.br, http://www.cs.cmu.edu/~fgcozman/home.html * * The JavaBayes distribution is free software; you can * redistribute it and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation (either * version 2 of the License or, at your option, any later version), * provided that this notice and the name of the author appear in all * copies. Upon request to the author, some of the packages in the * JavaBayes distribution can be licensed under the GNU Lesser General * Public License as published by the Free Software Foundation (either * version 2 of the License, or (at your option) any later version). * If you're using the software, please notify fgcozman@usp.br so * that you can receive updates and patches. JavaBayes is distributed * "as is", in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with the JavaBayes distribution. If not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package QuasiBayesianInferences; import BayesianNetworks.*; import BayesianInferences.*; import QuasiBayesianNetworks.*; import CredalSets.*; import java.io.*; import java.util.Vector; import java.util.Enumeration; /* * There are three cases to be considered: * Either the models are single distributions, local credal sets * or global credal sets: NONE, LOCAL and GLOBAL. * Note that when explanations are requested and there are no * explanatory variables, the final result is the posterior * marginal but the possibly present local credal sets are ignored. * This is a method to turn local credal sets off without * necessarily deleting them. * * Rule: LOCAL dominates NONE; GLOBAL dominates LOCAL. * -> When there is a local credal set, compute with the * local credal set. * -> When there is a global credal set specification, * compute with that (ignore local credal sets). */ public class QBInference extends Inference { BayesNet original_bn; ProbabilityFunction list_of_local_neighborhood_results; boolean is_inference_without_local_neighborhoods; /** * Constructor for a QBInference. */ public QBInference(BayesNet b_n, boolean dpc) { super(b_n, dpc); original_bn = b_n; transform_network(); } /* * Code for basic transformation. */ /* * Create all the values and transparent variables for the * credal sets, but do not include the transparent variables in * the probability_variables array. * Local neighborhoods are only used if there are * local credal sets and no global credal set. */ private void transform_network() { // Decide whether transformation is necessary if (bn instanceof QuasiBayesNet) is_inference_without_local_neighborhoods = ( ((QuasiBayesNet)bn).get_global_neighborhood_type() != QuasiBayesNet.NO_CREDAL_SET ) || (! (((QuasiBayesNet)bn).are_local_credal_sets_present()) ); else is_inference_without_local_neighborhoods = true; // Generate the transformed_bn. bn = new QuasiBayesNet(bn); // If no transformation, then return. if (is_inference_without_local_neighborhoods) return; // Else, copy all relevant content from bn to transformed_bn bn.set_name("Transformed-Network"); Vector auxiliary_variables = transform_probability_functions_array(); transform_probability_variables_array(auxiliary_variables); } /* * Create all the values and transparent variables for the * credal sets. */ private Vector transform_probability_functions_array() { VertexSet qbpf, new_qbpf; ProbabilityFunction pf, new_probability_function; Vector auxiliary_variables = new Vector(); // Process every ProbabilityFunction for (int i=0; i<bn.number_probability_functions(); i++) { pf = bn.get_probability_function(i); if (pf instanceof VertexSet) { qbpf = (VertexSet)pf; new_qbpf = qbpf.prepare_auxiliary_variable(bn); auxiliary_variables.addElement(new_qbpf.get_auxiliary_variable()); bn.set_probability_function(i, new_qbpf); } else { new_probability_function = new ProbabilityFunction(bn, pf.get_variables(), pf.get_values(), (Vector)null); bn.set_probability_function(i, new_probability_function); } } return(auxiliary_variables); } /* * Copy all the regular and auxiliary variables into a new * probability_variables array, making the auxiliary variables * available for calculation of marginals */ private void transform_probability_variables_array(Vector auxs) { ProbabilityVariable new_probability_variable; ProbabilityVariable new_probability_variables[]; Enumeration e; int i, j, new_array_size; // Create the new probability_variables array new_array_size = bn.number_variables() + auxs.size(); new_probability_variables = new ProbabilityVariable[new_array_size]; // Insert regular variables into new array for (i=0; i<bn.number_variables(); i++) { new_probability_variable = new ProbabilityVariable(bn, bn.get_probability_variable(i)); new_probability_variables[i] = new_probability_variable; } // Insert auxiliary variables into new array for (e = auxs.elements(), j=i; j<new_probability_variables.length; j++) { // Insert auxiliary variable new_probability_variables[j] = (ProbabilityVariable)(e.nextElement()); // Update the index of auxiliary variable new_probability_variables[j].set_index(j); } // Replace probability_variables bn.set_probability_variables(new_probability_variables); } /* * Calculation of Inference. */ public void inference(String queried_variable_name) { super.inference(queried_variable_name); do_quasi_bayesian_inference(); } /** * Calculation of marginal posterior envelope using a given ordering. */ public void inference(String order[]) { inference(order); do_quasi_bayesian_inference(); } /* * Do the Inference. */ protected void do_quasi_bayesian_inference() { // Process result if (is_inference_without_local_neighborhoods) inference_without_local_neighborhoods(); else inference_with_local_neighborhoods(); } /* * Perform calculation of marginal posterior distributions * when local neighborhoods are present. * Note that the distributions for the queried variable, for * all transparent variables, is stored at results. */ private void inference_with_local_neighborhoods() { int i, j, jump = 1; double v, min[], max[]; DiscreteFunction unnormalized_results; ProbabilityFunction normalized_results; // Normalize with respect to transparent variables unnormalized_results = bucket_tree.get_unnormalized_result(); normalized_results = new ProbabilityFunction(bn, unnormalized_results.get_variables(), unnormalized_results.get_values(), (Vector)null); normalized_results.normalize_first(); // Get the bounds on probability for (i=1; i<normalized_results.number_variables(); i++) jump *= normalized_results.get_variable(i).number_values(); min = new double[normalized_results.get_variable(0).number_values()]; max = new double[normalized_results.get_variable(0).number_values()]; for (i=0; i<normalized_results.get_variable(0).number_values(); i++) { min[i] = 1.0; max[i] = 0.0; for (j=0; j<jump; j++) { v = normalized_results.get_value( j + i*jump ); if (v < min[i]) min[i] = v; if (v > max[i]) max[i] = v; } } // Construct results result = new QBProbabilityFunction(normalized_results, (double[])null, min, max); list_of_local_neighborhood_results = normalized_results; } /* * Perform calculation of marginal posterior distributions * when local neighborhoods are absent; handles global * neighborhoods if necessary. */ private void inference_without_local_neighborhoods() { DiscreteFunction unnormalized = bucket_tree.get_unnormalized_result(); switch (((QuasiBayesNet)bn).get_global_neighborhood_type()) { case QuasiBayesNet.NO_CREDAL_SET: result = new ProbabilityFunction(unnormalized, bn); result.normalize(); break; case QuasiBayesNet.CONSTANT_DENSITY_RATIO: ProbabilityFunction cdr_res = new ProbabilityFunction(unnormalized, bn); ConstantDensityRatioSet cdr = new ConstantDensityRatioSet(cdr_res, ((QuasiBayesNet)bn).get_global_neighborhood_parameter()); result = cdr.posterior_marginal(); break; case QuasiBayesNet.EPSILON_CONTAMINATED: ProbabilityFunction eps_res = new ProbabilityFunction(unnormalized, bn); EpsilonContaminatedSet eps = new EpsilonContaminatedSet(eps_res, ((QuasiBayesNet)bn).get_global_neighborhood_parameter()); result = eps.posterior_marginal(); break; case QuasiBayesNet.CONSTANT_DENSITY_BOUNDED: ProbabilityFunction cdb_res = new ProbabilityFunction(unnormalized, bn); ConstantDensityBoundedSet cdb = new ConstantDensityBoundedSet(cdb_res, ((QuasiBayesNet)bn).get_global_neighborhood_parameter()); result = cdb.posterior_marginal(); break; case QuasiBayesNet.TOTAL_VARIATION: ProbabilityFunction tv_res = new ProbabilityFunction(unnormalized, bn); TotalVariationSet tv = new TotalVariationSet(tv_res, ((QuasiBayesNet)bn).get_global_neighborhood_parameter()); result = tv.posterior_marginal(); break; } } }