/** * SPINdle (version 2.2.2) * Copyright (C) 2009-2012 NICTA Ltd. * * This file is part of SPINdle project. * * SPINdle is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SPINdle 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPINdle. If not, see <http://www.gnu.org/licenses/>. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory */ package spindle.tools.analyser.impl; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.TreeSet; import java.util.Vector; import java.util.logging.Level; import spindle.core.dom.Literal; import spindle.core.dom.Rule; import spindle.tools.analyser.TheoryAnalyserException; import spindle.tools.analyser.dom.CLiteral; /** * Search strongly connected literals in a theory using Gabow's algorithm. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory * @since version 1.0.5 */ public class StronglyConnectedComponentsImpl_gabow extends StronglyConnectedComponentsBase implements StronglyConnectedComponents { private List<CLiteral> literalsInTheory = null; private List<CLiteral> literalsPending = null; private int cnt = 0; private int scnt = 0; private Stack<CLiteral> path = null; private Stack<CLiteral> S = null; private List<Set<Literal>> sccLiteralsGroups = null; public StronglyConnectedComponentsImpl_gabow() { super(); } private void setUp() { literalsPending = new Vector<CLiteral>(); literalsInTheory = new Vector<CLiteral>(); for (Literal literal : getTheory().getAllLiteralsInRules()) { CLiteral cl = new CLiteral(literal); literalsPending.add(cl); literalsInTheory.add(cl); } path = new Stack<CLiteral>(); S = new Stack<CLiteral>(); cnt = 0; scnt = 0; sccLiteralsGroups = new ArrayList<Set<Literal>>(); } @Override protected List<Set<Literal>> searchStronglyConnectedLiterals() throws TheoryAnalyserException { setUp(); // this.logMessage(0,"scc_gabow\n"+getTheory().toString()); try { CLiteral literal = null; while ((literal = getNextLiteral()) != null) { scR(literal); } return sccLiteralsGroups; } catch (Exception e) { throw new TheoryAnalyserException(e); } } private int findMinimumPre(CLiteral literal) { Literal conflictLiteral = literal.getComplementClone(); CLiteral cl = getCLiteral(conflictLiteral); int minPre = literal.getPre(); if (null != cl && S.contains(cl) && cl.getPre() != Integer.MIN_VALUE && cl.getPre() < minPre) { minPre = cl.getPre(); } // logMessage(1, "findMin, literal=" + literal + ", min=" + minPre); return minPre; } private void scR(CLiteral literal) { literal.setPre(cnt++); S.push(literal); path.push(literal); // logMessage(1,literal.toString()); Map<String, Rule> rules = getTheory().getRules(literal); for (Rule rule : rules.values()) { // logMessage(2,"scR:"+rule.toString()); if (rule.isHeadLiteral(literal)) { if (rule.isBodyLiteral(literal)) { } // logMessage(3,"is head literal: "+literal); } else { for (Literal l : rule.getHeadLiterals()) { CLiteral cl = getCLiteral(l); if (cl.getPre() == Integer.MIN_VALUE) { literalsPending.remove(cl); scR(cl); } else { if (cl.getGroupId() == Integer.MIN_VALUE) { while (path.size() > 0 && path.peek().getPre() > cl.getPre()) { path.pop(); } } } } } } int minPre = findMinimumPre(literal); while (path.size() > 0 && path.peek().getPre() > minPre) { path.pop(); } if (path.size() > 0 && path.peek().getPre() == literal.getPre()) { path.pop(); } else { logMessage(Level.FINER, 2, "==> return"); return; } CLiteral tLiteral = null; Set<Literal> sscLiterals = new TreeSet<Literal>(); do { tLiteral = S.pop(); tLiteral.setGroupId(scnt); sscLiterals.add(tLiteral); } while (S.size() >= 0 && !tLiteral.equals(literal)); sccLiteralsGroups.add(sscLiterals); logMessage(Level.FINER, 1, "scc group found:[" + sscLiterals.size() + "]-", sscLiterals); scnt++; } private CLiteral getCLiteral(final Literal literal) { int l = literalsInTheory.indexOf(literal); return l < 0 ? null : literalsInTheory.get(l); } private CLiteral getNextLiteral() { if (literalsPending.size() == 0) return null; return literalsPending.remove(0); } protected Set<Literal> getConflictLiterals(final Literal literal) { Set<Literal> literalList = new TreeSet<Literal>(); literalList.add(literal.getComplementClone()); return literalList; } }