/*
* Copyright (C) 2009-2012 University of Freiburg
*
* This file is part of SMTInterpol.
*
* SMTInterpol 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.
*
* SMTInterpol 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 SMTInterpol. If not, see <http://www.gnu.org/licenses/>.
*/
package de.uni_freiburg.informatik.ultimate.smtinterpol.proof;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause;
import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Literal;
import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent;
/**
* Collection of proof tree transformations. The algorithms are taken from
* Fontaine, Merz, Woltzenlogel Paleo, "Compression of Propositional Resolution
* Proofs via Partial Regularization"
* @author Juergen Christ
*/
public final class Transformations {
private Transformations() {
// Hide constructor
}
public static enum AvailableTransformations {
NONE {
@Override
public Clause transform(Clause proof) {
return proof;
}
},
LU {
@Override
public Clause transform(Clause proof) {
return Transformations.lowerUnits(proof);
}
},
RPI {
@Override
public Clause transform(Clause proof) {
return Transformations.recycleUnits(proof);
}
},
RPILU {
@Override
public Clause transform(Clause proof) {
return Transformations.lowerUnits(
Transformations.recycleUnits(proof));
}
},
LURPI {
@Override
public Clause transform(Clause proof) {
return Transformations.recycleUnits(
Transformations.lowerUnits(proof));
}
};
public abstract Clause transform(Clause proof);
}
/**
* Lower the unit resolutions.
* @param proof The proof tree.
* @return New proof tree with units lowered.
*/
public static Clause lowerUnits(Clause proof) {
assert proof.getSize() == 0;
OccurrenceCounter occ = new OccurrenceCounter();
Map<Clause, Integer> counts = occ.count(proof);
occ = null; // done with it
UnitCollector uc = new UnitCollector();
Queue<Antecedent> units = uc.collectUnits(proof, counts);
Map<Clause, Set<Literal>> deletedNodes = uc.getDeletedNodes();
uc = null; // done with it
FixProofDAG fix = new FixProofDAG();
final Clause tmpproof = fix.fix(proof, deletedNodes);
final ArrayDeque<Antecedent> fixedUnits =
new ArrayDeque<Antecedent>(units.size());
while (!units.isEmpty()) {
final Antecedent a = units.remove();
fixedUnits.add(new Antecedent(a.mPivot,
fix.fix(a.mAntecedent, deletedNodes)));
}
// Clear space
counts = null;
units = null;
deletedNodes = null;
fix = null;
// Track literals in the hyper-resolution
final HashSet<Literal> lits = new HashSet<Literal>();
for (int i = 0; i < tmpproof.getSize(); ++i) {
lits.add(tmpproof.getLiteral(i));
}
if (lits.isEmpty()) {
return tmpproof;
}
// Reinsert unit literals
Antecedent[] antes = new Antecedent[fixedUnits.size()];
int antepos = 0;
while (!fixedUnits.isEmpty()) {
final Antecedent unit = fixedUnits.remove();
if (lits.contains(unit.mPivot.negate())) {
antes[antepos++] = unit;
lits.remove(unit.mPivot.negate());
for (int i = 0; i < unit.mAntecedent.getSize(); ++i) {
final Literal l = unit.mAntecedent.getLiteral(i);
if (l != unit.mPivot) {
lits.add(l);
}
}
}
}
if (antepos < antes.length) {
final Antecedent[] tmp = new Antecedent[antepos];
System.arraycopy(antes, 0, tmp, 0, antepos);
antes = tmp;
}
assert lits.isEmpty();
return new Clause(new Literal[0], new ResolutionNode(tmpproof, antes));
}
/**
* Recycle resolution pivots.
* @param proof The proof tree.
* @return New proof tree.
*/
public static Clause recycleUnits(Clause proof) {
assert proof.getSize() == 0;
OccurrenceCounter occ = new OccurrenceCounter();
final Map<Clause, Integer> counts = occ.count(proof);
occ = null; // done with it
RecyclePivots rp = new RecyclePivots();
final Map<Clause, Set<Literal>> deleted = rp.regularize(proof, counts);
rp = null; // done with it
final FixProofDAG fix = new FixProofDAG();
return fix.fix(proof, deleted);
}
}