/******************************************************************************* * Copyright (C) 2008-2012 Dominik Jain. * * This file is part of ProbCog. * * ProbCog 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 3 of the License, or * (at your option) any later version. * * ProbCog is distributed 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 ProbCog. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package probcog.bayesnets.util; import java.util.HashMap; import java.util.Vector; import edu.ksu.cis.bnj.ver3.core.BeliefNetwork; import edu.ksu.cis.bnj.ver3.core.BeliefNode; import edu.ksu.cis.util.graph.core.Graph; import edu.ksu.cis.util.graph.core.Vertex; /** * * @author Dominik Jain */ public class TopologicalSort { protected BeliefNetwork bn; public TopologicalSort(BeliefNetwork bn) { this.bn = bn; } public TopologicalOrdering run() throws Exception { return run(false); } public TopologicalOrdering run(boolean createTierMap) throws Exception { Graph g = bn.getGraph(); BeliefNode[] nodes = bn.getNodes(); HashMap<BeliefNode, Integer> tierMap = null; if(createTierMap) tierMap = new HashMap<BeliefNode,Integer>(nodes.length); // obtain in-degree of each node/vertex Vertex[] vertices = g.getVertices(); int[] indeg = new int[vertices.length]; for(Vertex v : vertices) { for(Vertex child : g.getChildren(v)) { assert vertices[child.loc()] == child; indeg[child.loc()]++; } } // successively extract nodes with in-degree 0, decrementing the degree of nodes reached via them Vector<Vector<Integer>> ret = new Vector<Vector<Integer>>(); int numExtracted = 0; Integer numLevel = 0; int prevExtracted = -1; boolean debug = false; while(numExtracted < vertices.length) { if(prevExtracted == numExtracted) throw new Exception(String.format("Topological ordering could not be obtained because of cycles in the network (%d nodes remain).", vertices.length-numExtracted)); prevExtracted = numExtracted; if(debug) System.out.println(numExtracted + " of " + vertices.length); Vector<Integer> level = new Vector<Integer>(); int[] indeg2 = new int[indeg.length]; for(int i = 0; i < indeg.length; i++) { indeg2[i] += indeg[i]; if(indeg[i] == 0) { numExtracted++; indeg2[i] = -1; level.add(i); if(createTierMap) tierMap.put(nodes[i], numLevel); for(Vertex child : g.getChildren(vertices[i])) indeg2[child.loc()]--; } else if(debug) System.out.println(String.format(" %d %s", indeg[i], nodes[i].getName())); } indeg = indeg2; ret.add(level); numLevel++; } return new TopologicalOrdering(ret, tierMap); } }