/** * Returns an array R of longs such that for each i, j in [0..R.length) i < j implies that the * formula identified by (int)R[i] in this.hits contributes fewer clauses to the core of the given * trace than the formula identified by (int)R[j]. * * @return an array as described above */ private long[] sortByRelevance(ResolutionTrace trace, IntSet relevantVars) { hits.indices().retainAll(relevantVars); if (hits.get(hits.indices().min()) == null) { // first call, initialize the hits for (IntIterator varItr = relevantVars.iterator(); varItr.hasNext(); ) { final int var = varItr.next(); final IntSet varReachable = new IntBitSet(var + 1); varReachable.add(var); hits.put(var, varReachable); } for (Iterator<Clause> clauseItr = trace.reverseIterator(trace.axioms()); clauseItr.hasNext(); ) { final Clause clause = clauseItr.next(); final int maxVar = clause.maxVariable(); for (IntSet reachableVars : hits.values()) { if (reachableVars.contains(maxVar)) { for (IntIterator lits = clause.literals(); lits.hasNext(); ) { reachableVars.add(StrictMath.abs(lits.next())); } } } } } final long[] counts = new long[hits.size()]; for (Iterator<Clause> clauseItr = trace.iterator(trace.core()); clauseItr.hasNext(); ) { final Clause clause = clauseItr.next(); final int maxVar = clause.maxVariable(); int i = 0; for (IntSet reachableVars : hits.values()) { if (reachableVars.contains(maxVar)) { counts[i]++; } i++; } } int i = 0; for (IntIterator varItr = hits.indices().iterator(); varItr.hasNext(); ) { final int var = varItr.next(); counts[i] = (counts[i] << 32) | var; i++; } Arrays.sort(counts); return counts; }
/** * {@inheritDoc} * * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) */ public IntSet next(ResolutionTrace trace) { if (hits.isEmpty()) return Ints.EMPTY_SET; // tried everything final IntSet relevantVars = StrategyUtils.coreTailUnits(trace); final long[] byRelevance = sortByRelevance(trace, relevantVars); if (DBG) printRelevant(byRelevance); for (int i = byRelevance.length - 1; i >= 0; i--) { final int var = (int) byRelevance[i]; if (hits.remove(var) != null) { // remove maxVar from the set of relevant variables relevantVars.remove(var); if (relevantVars.isEmpty()) break; // there was only one root formula left // get all axioms and resolvents corresponding to the clauses that // form the translations of formulas identified by relevant vars final IntSet relevantClauses = clausesFor(trace, relevantVars); assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size() - 1); if (DBG) System.out.println("relevant clauses: " + relevantClauses.size() + ", removed " + var); return relevantClauses; } } hits.clear(); return Ints.EMPTY_SET; }
/** * Returns the indices of all axioms and resolvents in the given trace that form the translations * of the formulas identified by the given variables. This method assumes that the axioms in the * given trace were generated by the Kodkod {@linkplain Translator}. * * @return let C = { c: trace.prover.clauses | c.maxVariable() in relevantVars }, T = { c1, c2: C * | c2.maxVariable() in abs(c1.literals) }, A = C.*T | trace.backwardReachable(A) - * trace.backwardReachable(trace.axioms() - A) */ private IntSet clausesFor(ResolutionTrace trace, IntSet relevantVars) { final double hardness = (double) trace.size() / (double) trace.axioms().size(); final double coreRatio = ((double) trace.core().size() / (double) trace.axioms().size()); if (DBG) System.out.println( "trace size: " + trace.size() + ", axioms: " + trace.axioms().size() + ", core: " + trace.core().size() + ", resolvents: " + trace.resolvents().size()); if (DBG) System.out.println("hardness: " + hardness + ", coreRatio: " + coreRatio); final IntSet relevantAxioms = StrategyUtils.clausesFor(trace, relevantVars); if (DBG) System.out.println("relevant axioms: " + relevantAxioms.size()); if (coreRatio < noRecycleRatio) { return relevantAxioms; } else if (hardness < hardnessCutOff) { return trace.learnable(relevantAxioms); } else { IntSet current = relevantAxioms, last; final int maxRelevant = (int) Math.rint(relevantAxioms.size() * recycleLimit); do { last = current; current = trace.directlyLearnable(current); } while (last.size() < current.size() && current.size() < maxRelevant); if (DBG) System.out.println( "last: " + last.size() + ", current: " + current.size() + ", maxRelevant: " + maxRelevant); return current.size() < maxRelevant ? current : last; } }