public Cluster(JoinGraph.Node u) { // Constructor for cluster(u) this.node = u; // add to the cluster all CPTs of the given node for (CPF cpf : u.functions) cpts.add(cpf.getDomainProduct()[0]); // add all incoming messages of n for (JoinGraph.Node nb : u.getNeighbors()) { JoinGraph.Arc arc = u.arcs.get(nb); HashSet<MessageFunction> m = arc.getInMessage(u); if (!m.isEmpty()) functions.addAll(m); HashSet<BeliefNode> bn = arc.getCPTInMessage(u); if (!bn.isEmpty()) cpts.addAll(bn); } }
@Override public void _infer() throws Exception { // Create topological order if (verbose) out.println("determining order..."); jgNodes = jg.getTopologicalorder(); if (debug) { out.println("Topological Order: "); for (int i = 0; i < jgNodes.size(); i++) { out.println(jgNodes.get(i).getShortName()); } } // process observed variables if (verbose) out.println("processing observed variables..."); for (JoinGraph.Node n : jgNodes) { Vector<BeliefNode> nodes = new Vector<BeliefNode>(n.getNodes()); for (BeliefNode belNode : nodes) { int nodeIdx = bn.getNodeIndex(belNode); int domainIdx = evidenceDomainIndices[nodeIdx]; if (domainIdx > -1) n.nodes.remove(belNode); } } out.printf("running propagation (%d steps)...\n", this.numSamples); for (int step = 1; step <= this.numSamples; step++) { out.printf("step %d\n", step); // for every node in JG in topological order and back: int s = jgNodes.size(); boolean direction = true; for (int j = 0; j < 2 * s; j++) { int i; if (j < s) i = j; else { i = 2 * s - j - 1; direction = false; } JoinGraph.Node u = jgNodes.get(i); // out.printf("step %d, %d/%d: %-60s\r", step, j, 2*s, u.getShortName()); int topIndex = jgNodes.indexOf(u); for (JoinGraph.Node v : u.getNeighbors()) { if ((direction && jgNodes.indexOf(v) < topIndex) || (!direction && jgNodes.indexOf(v) > topIndex)) { continue; } Arc arc = u.getArcToNode(v); arc.clearOutMessages(u); // construct cluster_v(u) Cluster cluster_u = new Cluster(u, v); // Include in cluster_H each function in cluster_u which // scope does not contain variables in elim(u,v) HashSet<BeliefNode> elim = new HashSet<BeliefNode>(u.nodes); // out.println(" Node " + u.getShortName() + // " and node " +v.getShortName() + " have separator " + // StringTool.join(", ", arc.separator)); elim.removeAll(arc.separator); Cluster cluster_H = cluster_u.getReducedCluster(elim); // denote by cluster_A the remaining functions Cluster cluster_A = cluster_u.copy(); cluster_A.subtractCluster(cluster_H); // DEBUG OUTPUT if (debug) { out.println(" cluster_v(u): \n" + cluster_u); out.println(" A: \n" + cluster_A); out.println(" H_(u,v): \n" + cluster_H); } // convert eliminator into varsToSumOver int[] varsToSumOver = new int[elim.size()]; int k = 0; for (BeliefNode n : elim) varsToSumOver[k++] = bn.getNodeIndex(n); // create message function and send to v MessageFunction m = new MessageFunction(arc.separator, varsToSumOver, cluster_A); m.calcuSave(evidenceDomainIndices.clone()); arc.addOutMessage(u, m); for (MessageFunction mf : cluster_H.functions) { mf.calcuSave(evidenceDomainIndices.clone()); arc.addOutMessage(u, mf); } for (BeliefNode n : cluster_H.cpts) { arc.addCPTOutMessage(u, n); } } } } // compute probabilities and store results in distribution out.println("computing results..."); SampledDistribution dist = createDistribution(); dist.Z = 1.0; for (int i = 0; i < nodes.length; i++) { // out.println("Computing: " + nodes[i].getName() + "\n"); if (evidenceDomainIndices[i] >= 0) { dist.values[i][evidenceDomainIndices[i]] = 1.0; continue; } // For every node X let u be a vertex in the join graph such that X // is in u // out.println(nodes[i]); JoinGraph.Node u = null; for (JoinGraph.Node node : jgNodes) { if (node.nodes.contains(nodes[i])) { u = node; break; } } if (u == null) throw new Exception( "Could not find vertex in join graph containing variable " + nodes[i].getName()); // out.println("\nCalculating results for " + nodes[i]); // out.println(u); // compute sum for each domain value of i-th node int domSize = dist.values[i].length; double Z = 0.0; int[] nodeDomainIndices = evidenceDomainIndices.clone(); for (int j = 0; j < domSize; j++) { nodeDomainIndices[i] = j; MutableDouble sum = new MutableDouble(0.0); BeliefNode[] nodesToSumOver = u.nodes.toArray(new BeliefNode[u.nodes.size()]); computeSum(0, nodesToSumOver, nodes[i], new Cluster(u), nodeDomainIndices, sum); Z += (dist.values[i][j] = sum.value); } // normalize for (int j = 0; j < domSize; j++) dist.values[i][j] /= Z; } // dist.print(out); ((ImmediateDistributionBuilder) distributionBuilder).setDistribution(dist); }