/* * Recover the maximizing variables going back through the maximizing * bucket_tree; the variables are returned as an array of markers * (non-explanation variables get INVALID_INDEX). */ private int[] backward_maximization() { int i, j; int bi = bucket_tree.length - 1; DiscreteFunction back_df; Bucket b = bucket_tree[bi]; // If there are no explanation variables in the BayesNet, return null if (b.backward_pointers == null) return (null); // Initialize the markers for backward pointers with INVALID_INDEX int backward_markers[] = new int[bn.number_variables()]; for (i = 0; i < backward_markers.length; i++) backward_markers[i] = BayesNet.INVALID_INDEX; // Initialize the marker for the last bucket backward_markers[b.variable.get_index()] = (int) (b.backward_pointers.get_value(0) + 0.5); // Go backwards through the bucket_tree for (i = (bi - 1); i >= 0; i--) { if (!bucket_tree[i].is_explanation()) break; back_df = bucket_tree[i].backward_pointers; // Skip null pointers (caused by evidence) if (back_df == null) continue; // Special treatment for bucket with only one value, // since it can be a bucket with only the bucket variable left if (back_df.number_values() == 1) { backward_markers[bucket_tree[i].variable.get_index()] = (int) (back_df.get_value(0) + 0.5); continue; } // Process the bucket j = back_df.get_position_from_indexes(bn.get_probability_variables(), backward_markers); backward_markers[bucket_tree[i].variable.get_index()] = (int) (back_df.get_value(j) + 0.5); } return (backward_markers); }
/** * Distribute evidence in the BucketTree. * * @return true if successful; false if not. */ public boolean distribute() { int i, j; boolean mark_non_conditioning[] = new boolean[bn.number_variables()]; // First make sure the BucketTree has been reduced. if (unnormalized_result == null) reduce(); // Second make sure there is more than one Bucket in the BucketTree. int last = bucket_tree.length - 1; if (last < 1) return (true); // Third, this method is used only if do_produce_clusters is true. if (do_produce_clusters == false) return (false); // Fourth, this method is use only if no explanatory variable was max'ed // out. if (backward_pointers != null) return (false); // Go through the Bucket objects, from bottom to top, // to compute the new separator and cluster for each bucket. for (i = (last - 1); i >= 0; i--) { // Start from (last-1); last does // not have child. // Check whether the Bucket has any valid content. if (bucket_tree[i].cluster == null) break; // Take the non-conditioning variables in a boolean array. for (j = 0; j < mark_non_conditioning.length; j++) mark_non_conditioning[j] = true; // OBS: The following piece of code will actually be less efficient // than // necessary. It will count as "conditioning" any variable in the // cluster // except the bucket variable. This will imply that some variables // in the // separator will be normalized over without need, and the separator // will // be larger than necessary. // OBS: this code was contributed by Wei Zhou ([email protected]), // who also detected the problem with the original code. // if (bucket_tree[i].cluster.number_variables() > // bucket_tree[i].non_conditioning_variables.size()) for (j = 1; j < bucket_tree[i].cluster.number_variables(); j++) { mark_non_conditioning[(bucket_tree[i].cluster.get_variables())[j].get_index()] = false; } // The following piece of code does the right thing (compared to the // piece of code above): it selects the // minimum number of non-conditioning variables. To use this piece // of code, it will be necessary to create a "normalize" method that // normalizes with respect to a number of variables at at time. /* * for (j=0; j<bucket_tree[i].cluster.number_variables(); j++) { * mark_non_conditioning[ * (bucket_tree[i].cluster.get_variables())[j].get_index() ] = * false; } for (Enumeration e = * bucket_tree[i].non_conditioning_variables.elements(); * e.hasMoreElements(); ) { ProbabilityVariable pv = * (ProbabilityVariable)(e.nextElement()); * mark_non_conditioning[pv.get_index() ] = true; } */ // Update the separator. bucket_tree[i].separator = bucket_tree[i].child.cluster.sum_out( bn.get_probability_variables(), mark_non_conditioning); // Compute cluster using new separator (note that if separator // is null, the cluster had all variables already processed). if (bucket_tree[i].separator != null) { // OBS: the method here should normalize with respect to more // than one variable, to allow this algorithm to be more // efficient! bucket_tree[i].cluster.normalize_first(); // Now combine the cluster and the separator. bucket_tree[i].cluster = bucket_tree[i].cluster.multiply( bn.get_probability_variables(), bucket_tree[i].separator); } // Mark the Bucket as DISTRIBUTED. bucket_tree[i].bucket_status = Bucket.DISTRIBUTED; } // Indicate success. return (true); }