/** * Author: Georg Hofferek <georg.hofferek@iaik.tugraz.at> */ package at.iaik.suraq.util; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import at.iaik.suraq.proof.VeritProofNode; import at.iaik.suraq.smtlib.formula.DomainEq; import at.iaik.suraq.smtlib.formula.Formula; import at.iaik.suraq.smtlib.formula.UninterpretedPredicateInstance; import at.iaik.suraq.util.chain.TransitivityCongruenceChain; /** * For parallel splitting of uncolorable leaves. * * @author Georg Hofferek <georg.hofferek@iaik.tugraz.at> * */ public class UncolorableLeafSplitter implements Runnable { /** * An identifying integer among all leaf-splitters. */ private final int id; /** * The leaves to be split by this splitter. */ private final List<VeritProofNode> leavesToSplit; /** * The map from original nodes to replaced nodes. */ private final Map<VeritProofNode, VeritProofNode> replacements; /** * Counts how many literals were saved by this splitter */ private int totalLiteralsFewer = 0; /** * Counts how many clauses were being made stronger by this splitter. */ private int numStrongerClauses = 0; /** * The total wait time of this thread after completion. */ private long totalWaitTime = -1; /** * The total CPU time of this thread after completion. */ private long totalCpuTime = -1; /** * Stores whether everything went right */ private boolean allOk = false; /** * The parent thread */ private final Thread parentThread; private int doneCount = 0; /** * * Constructs a new <code>UncolorableLeafSplitter</code>. * * @param id * @param leavesToSplit */ public UncolorableLeafSplitter(int id, List<VeritProofNode> leavesToSplit, Thread parent) { this.id = id; this.leavesToSplit = new ArrayList<VeritProofNode>(leavesToSplit); this.replacements = new HashMap<VeritProofNode, VeritProofNode>( leavesToSplit.size()); this.parentThread = parent; } /** * @see java.lang.Runnable#run() */ @Override public void run() { try { split(); allOk = true; ThreadMXBean tmxb = ManagementFactory.getThreadMXBean(); if (tmxb.isCurrentThreadCpuTimeSupported()) { totalCpuTime = tmxb.getCurrentThreadCpuTime(); } if (tmxb.isThreadContentionMonitoringSupported()) { totalWaitTime = tmxb.getThreadInfo( Thread.currentThread().getId()).getBlockedTime(); } } catch (Throwable exc) { Util.printToSystemOutWithWallClockTimePrefix("Exception in Splitter " + id + ". Stacktrace follows."); exc.printStackTrace(); allOk = false; parentThread.interrupt(); } } /** * Performs the actual work */ private void split() { while (!leavesToSplit.isEmpty()) { VeritProofNode leafToSplit = null; synchronized (this) { leafToSplit = leavesToSplit.remove(leavesToSplit.size() - 1); } assert (CongruenceClosure.checkVeritProofNode(leafToSplit)); assert (Util.countPositiveLiterals(leafToSplit .getLiteralConclusions()) == 1); assert (Util.countPositiveLiterals(leafToSplit .getLiteralConclusions()) + Util.countNegativeLiterals(leafToSplit .getLiteralConclusions()) == leafToSplit .getLiteralConclusions().size()); Formula positiveLiteral = Util.findPositiveLiteral(leafToSplit .getLiteralConclusions()); assert (positiveLiteral != null); assert (positiveLiteral instanceof DomainEq || positiveLiteral instanceof UninterpretedPredicateInstance); VeritProofNode replacement = null; // if (leafToClean.getType().equals(VeriTToken.EQ_CONGRUENT) // || leafToClean.getType().equals(VeriTToken.EQ_TRANSITIVE)) { if (positiveLiteral instanceof DomainEq) { Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Splitting leaf " + leafToSplit.getName()); TransitivityCongruenceChain chain = TransitivityCongruenceChain .create(leafToSplit); replacement = chain.toColorableProofNew(); // } else if (leafToClean.getType().equals( // VeriTToken.EQ_CONGRUENT_PRED)) { } else if (positiveLiteral instanceof UninterpretedPredicateInstance) { Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Splitting (predicate) leaf " + leafToSplit.getName()); replacement = leafToSplit.splitPredicateLeafNew(); } else { Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Unexpected implied literal:"); System.out.println(positiveLiteral.toString()); System.out.println("Containing leaf:"); System.out.println(leafToSplit.toString()); assert (false); } assert (replacement != null); assert (leafToSplit.getLiteralConclusions().containsAll(replacement .getLiteralConclusions())); int difference = leafToSplit.getLiteralConclusions().size() - replacement.getLiteralConclusions().size(); assert (difference >= 0); synchronized (Util.class) { if (difference > 0) { totalLiteralsFewer += difference; numStrongerClauses++; Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Replacement has " + replacement.getLiteralConclusions().size() + " literals (" + difference + " literals fewer than original leaf.)"); } else Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Replacement has the same number of literals. (" + replacement.getLiteralConclusions().size() + ")"); Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + totalLiteralsFewer + " literals saved so far in " + numStrongerClauses + " clauses."); replacements.put(leafToSplit, replacement); Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "Done " + ++doneCount + ". (" + leavesToSplit.size() + " remaining.)"); } } synchronized (Util.class) { Util.printToSystemOutWithWallClockTimePrefix(" " + "Splitter " + id + ": " + "All done."); Util.printToSystemOutWithWallClockTimePrefix("Splitter " + id + ": " + totalLiteralsFewer + " literals saved in " + numStrongerClauses + " clauses."); } } /** * * @return <code>true</code> iff splitting was performed successfully. */ public synchronized boolean isAllOk() { return allOk; } /** * * @return the number of literals saved by this splitter. */ public synchronized int getTotalLiteralsFewer() { return totalLiteralsFewer; } /** * * @return the number of clauses made stronger by this splitter. */ public synchronized int getNumStrongerClauses() { return numStrongerClauses; } /** * * @return the replacements for the leaves split by this splitter (copy). */ public synchronized Map<VeritProofNode, VeritProofNode> getReplacements() { Map<VeritProofNode, VeritProofNode> result = new HashMap<VeritProofNode, VeritProofNode>( replacements); return result; } /** * * @return number of splits already done */ public synchronized int getDone() { return doneCount; } /** * * @return number of splits remaining */ public synchronized int getRemaining() { return leavesToSplit.size(); } /** * @return the total wait time of this thread after completion, or -1 if it * has not completed yet, or measurement is not supported. */ public synchronized long getTotalWaitTime() { return totalWaitTime; } /** * @return the total CPU time of this thread after completion, or -1 if it * has not completed yet, or measurement is not supported. */ public synchronized long getTotalCpuTime() { return totalCpuTime; } }