/*******************************************************************************
* Copyright (c) 2013 Michael Kutschke.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Kutschke - initial API and implementation
******************************************************************************/
package bayesnet.jayes.inference.jtree;
import static bayesnet.jayes.util.Pair.newPair;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import bayesnet.internal.jayes.util.UnionFind;
import bayesnet.jayes.BayesNet;
import bayesnet.jayes.util.Graph;
import bayesnet.jayes.util.OrderIgnoringPair;
import bayesnet.jayes.util.Pair;
public class SepsetComputer {
public List, List>> computeSepsets(JunctionTree junctionTree, BayesNet net) {
final List, List>> candidates = enumerateCandidateSepSets(junctionTree
.getClusters());
Collections.sort(candidates, new SepsetComparator(net));
return computeMaxSpanningTree(junctionTree.getGraph(), candidates);
}
private List, List>> enumerateCandidateSepSets(List> clusters) {
final List, List>> sepSets = new ArrayList, List>>();
final ListIterator> it = clusters.listIterator();
while (it.hasNext()) {
final List clique1 = it.next();
final ListIterator> remainingIt = clusters.listIterator(it.nextIndex());
while (remainingIt.hasNext()) { // generate sepSets
final List clique2 = new ArrayList(remainingIt.next());
clique2.retainAll(clique1);
sepSets.add(newPair(new OrderIgnoringPair(it.nextIndex() - 1, remainingIt.nextIndex() - 1),
clique2));
}
}
return sepSets;
}
private List, List>> computeMaxSpanningTree(Graph graph,
final List, List>> sortedCandidateSepSets) {
final ArrayDeque, List>> pq = new ArrayDeque, List>>(
sortedCandidateSepSets);
final int vertexCount = graph.numberOfVertices();
final UnionFind[] sets = UnionFind.createArray(vertexCount);
final List, List>> leftSepSets = new ArrayList, List>>();
while (leftSepSets.size() < vertexCount - 1) {
final Pair, List> sep = pq.poll();
final boolean bothEndsInSameTree = sets[sep.getFirst().getFirst()].find() == sets[sep.getFirst()
.getSecond()].find();
if (!bothEndsInSameTree) {
sets[sep.getFirst().getFirst()].merge(sets[sep.getFirst().getSecond()]);
leftSepSets.add(sep);
graph.addEdge(sep.getFirst().getFirst(), sep.getFirst().getSecond());
}
}
return leftSepSets;
}
private static final class SepsetComparator implements Comparator, List>> {
private final BayesNet net;
public SepsetComparator(BayesNet net) {
this.net = net;
}
// heuristic: choose sepSet with most variables first,
// if equal, choose the on with least table size
@Override
public int compare(final Pair, List> sepSet1,
final Pair, List> sepSet2) {
final int compareNumberOfVariables = compare(sepSet2.getSecond().size(), sepSet1.getSecond().size());
if (compareNumberOfVariables != 0) {
return compareNumberOfVariables;
}
final int tableSize1 = getTableSize(sepSet1.getSecond());
final int tableSize2 = getTableSize(sepSet2.getSecond());
return compare(tableSize1, tableSize2);
}
private int getTableSize(final List cluster) {
int tableSize = 1;
for (final int id : cluster) {
tableSize *= net.getNode(id).getOutcomeCount();
}
return tableSize;
}
private int compare(final int i1, final int i2) {
return i1 - i2;
}
}
}
Ads help maintain this website.