/******************************************************************************* * Copyright (C) 2009-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.logic.sat.weighted; import java.util.Vector; import probcog.logic.GroundAtom; import probcog.logic.PossibleWorld; import probcog.logic.WorldVariables; import probcog.logic.sat.SampleSAT; import probcog.srl.Database; /** * Implementation of the MaxWalkSAT algorithm as described Kautz, Selman & Jiang (1997) * @author Dominik Jain */ public class MaxWalkSAT extends SampleSAT implements IMaxSAT { protected int maxSteps = 1000; protected PossibleWorld bestState = null; public MaxWalkSAT(WeightedClausalKB kb, PossibleWorld state, WorldVariables vars, Database db) throws Exception { super(kb, state, vars, db.getEntries()); } @Override protected Constraint makeConstraint(probcog.logic.sat.Clause c) { return new WeightedClause((probcog.logic.sat.weighted.WeightedClause)c); } protected class WeightedClause extends Clause { boolean isHard; double weight; public WeightedClause(probcog.logic.sat.weighted.WeightedClause wc) { super(wc.lits); weight = wc.weight; isHard = wc.isHard; } } @Override protected double deltaCost(GroundAtom gndAtom) { double delta = 0; // consider newly unsatisfied constraints (negative) Vector<Constraint> bn = this.bottlenecks.get(gndAtom.index); if(bn != null) for(Constraint c : bn) delta -= ((WeightedClause)c).weight; // consider newly satisfied constraints (positive) Vector<Constraint> occs = this.GAOccurrences.get(gndAtom.index); if(occs != null) for(Constraint c : occs) if(c.flipSatisfies(gndAtom)) delta += ((WeightedClause)c).weight; return delta; } @Override public void makeMove() { walkSATMove(); } @Override protected void walkSATMove() { // pick an unsatisfied constraint // with probability p, satisfy the constraint randomly if(rand.nextDouble() < this.pWalkSAT) { Constraint c = unsatisfiedConstraints.get(rand.nextInt(unsatisfiedConstraints.size())); c.satisfyRandomly(); } // with probability 1-p, satisfy it greedily else { Vector<Constraint> hardUnsat = new Vector<Constraint>(); for(Constraint c : unsatisfiedConstraints) { WeightedClause wc = (WeightedClause)c; if(wc.isHard) hardUnsat.add(c); } if(!hardUnsat.isEmpty()) { Constraint c = hardUnsat.get(rand.nextInt(hardUnsat.size())); c.satisfyGreedily(); } else { Constraint c = unsatisfiedConstraints.get(rand.nextInt(unsatisfiedConstraints.size())); c.satisfyGreedily(); } } } @Override public PossibleWorld getBestState() { return bestState; } @Override public void run() throws Exception { initialize(); double bestSum = Double.MAX_VALUE; int bestHardMissing = Integer.MAX_VALUE; for(int step = 1; step <= this.maxSteps; step++) { double unsatisfiedSum = 0.0; int hardMissing = 0; for(Constraint c : unsatisfiedConstraints) { WeightedClause wc = (WeightedClause)c; unsatisfiedSum += wc.weight; if(wc.isHard) hardMissing++; } boolean newBest = false; if(unsatisfiedSum < bestSum) { bestSum = unsatisfiedSum; bestHardMissing = hardMissing; newBest = true; this.bestState = state.clone(); } boolean printStatus = newBest || step % 10 == 0; if(printStatus) System.out.printf(" step %d: %d hard constraints unsatisfied, sum of unsatisfied weights: %f, best: %f (%d) %s\n", step, hardMissing, unsatisfiedSum, bestSum, bestHardMissing, newBest ? "[NEW BEST]" : ""); if(unsatisfiedSum == 0) break; makeMove(); } System.out.printf("solution quality: sum of unsatisfied constraints: %f, hard constraints unsatisfied: %d\n", bestSum, bestHardMissing); PossibleWorld bestState = this.getBestState(); for(Constraint c : this.constraints) { WeightedClause wc = (WeightedClause)c; if(wc.isHard) { if(!wc.isTrue(bestState)) System.out.println(wc); } } } @Override public void setMaxSteps(int steps) { maxSteps = steps; } @Override public String getAlgorithmName() { return String.format("%s[p=%f]", this.getClass().getSimpleName(), this.pWalkSAT); } }