/** * DSeparation.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 BayesianInferences; import BayesianNetworks.*; import java.util.*; /**************************************************************************/ class DSeparation { BayesNet bn; boolean above[], below[]; private final static int CONNECTED_VARIABLES = 0; private final static int AFFECTING_VARIABLES = 1; /** * Constructor for DSeparation object. */ DSeparation(BayesNet b_n) { bn = b_n; } /** * Return a list of all variables that are d-connected to * a given variable. */ public Vector all_connected(int x) { return(separation(x, CONNECTED_VARIABLES)); } /** * Returns a list of all variables whose distributions can * affect the marginal posterior of a given variable. */ public Vector all_affecting(int x) { return(separation(x, AFFECTING_VARIABLES)); } /* * Find all d-separation relations. */ private void separation_relations(int x, int flag) { int nvertices = bn.number_probability_functions(); if (flag == AFFECTING_VARIABLES) nvertices += nvertices; boolean ans = false; above = new boolean[nvertices]; below = new boolean[nvertices]; int current[] = new int[2]; int i, j, v, subscript; for (i=0; i < nvertices; i++) { above[i] = false; below[i] = false; } Stack stack = new Stack( ); int Xabove[] = { x, 1 }; int Xbelow[] = { x, -1 }; stack.push(Xabove); stack.push(Xbelow); below[x] = true; above[x] = true; while( !stack.empty( ) ) { current = (int[]) stack.pop( ); v = current[0]; subscript = current[1]; if(subscript < 0) { for ( i = 0; i < nvertices; i++ ) //parents if ( adj(i, v, flag) ) if( (!below[i]) && ( !is_separator(i, flag) )) { below[i] = true; int Vbelow[] = { i, -1 }; stack.push(Vbelow); } for ( j = 0; j < nvertices; j++) //children if ( adj(v, j, flag) ) if(!above[j]) { above[j] = true; int Tabove[] = { j, 1 }; stack.push(Tabove); } above[v] = true; } // subscript < 0 else { if ( is_separator(v, flag) ) { // v known for ( i = 0; i < nvertices; i++ ) //parents if ( adj(i, v, flag) ) if ( ( !is_separator(i, flag) ) && !below[i] ) { below[i] = true; int Tbelow[] = { i, -1 }; stack.push(Tbelow); } } else // v not known for ( j = 0; j < nvertices; j++ ) //children if ( adj(v, j, flag) ) if(!above[j]) { above[j] = true; int Sabove[] = { j, 1 }; stack.push(Sabove); } } // subscript >= 0 } // while } /* * Run the separation algorithm and process its results. */ private Vector separation(int x, int flag) { int i; int nvertices = bn.number_probability_functions(); Vector d_separated_variables = new Vector(); // Run algorithm separation_relations(x, flag); // Process results if (flag == CONNECTED_VARIABLES) { for (i=0; i<nvertices; i++) { if (below[i] || above[i]) d_separated_variables.addElement(bn.get_probability_variable(i)); } } else { for (i=nvertices; i<(nvertices+nvertices); i++) { if (below[i] || above[i]) d_separated_variables.addElement(bn.get_probability_variable(i - nvertices)); } } return(d_separated_variables); } /* * Check whether the variable given by the index is in the * list of separators (i.e., it is observed). */ private boolean is_separator(int i, int flag) { if ((flag == CONNECTED_VARIABLES) || ((flag == AFFECTING_VARIABLES) && (i < bn.number_probability_functions()))) return(bn.get_probability_variable(i).is_observed()); else return(false); } /* * Check whether there is a link from variable index_from to * variable index_to. */ private boolean adj(int index_from, int index_to, int flag) { ProbabilityFunction pf = null; if ((flag == CONNECTED_VARIABLES) || ((flag == AFFECTING_VARIABLES) && (index_to < bn.number_probability_functions()) && (index_from < bn.number_probability_functions()))) { for (int i=0; i<bn.number_probability_functions(); i++) { if (bn.get_probability_function(i).get_index(0) == index_to) { pf = bn.get_probability_function(i); break; } } if (pf == null) return(false); for (int i=1; i<pf.number_variables(); i++) { if (pf.get_index(i) == index_from) return(true); } return(false); } else { if ( ( index_from - index_to ) == bn.number_probability_functions() ) return(true); else return(false); } } }