001 /* 002 * Created on Feb 9, 2005 003 * 004 */ 005 package aima.logic.propositional.algorithms; 006 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.Random; 010 import java.util.Set; 011 012 import aima.logic.propositional.parsing.PEParser; 013 import aima.logic.propositional.parsing.ast.Sentence; 014 import aima.logic.propositional.parsing.ast.Symbol; 015 import aima.logic.propositional.visitors.CNFClauseGatherer; 016 import aima.logic.propositional.visitors.CNFTransformer; 017 import aima.logic.propositional.visitors.SymbolCollector; 018 import aima.util.Converter; 019 import aima.util.Util; 020 021 /** 022 * @author Ravi Mohan 023 * 024 */ 025 026 public class WalkSAT { 027 private Model myModel; 028 029 private Random random = new Random(); 030 031 public Model findModelFor(String logicalSentence, int numberOfFlips, 032 double probabilityOfRandomWalk) { 033 myModel = new Model(); 034 Sentence s = (Sentence) new PEParser().parse(logicalSentence); 035 CNFTransformer transformer = new CNFTransformer(); 036 CNFClauseGatherer clauseGatherer = new CNFClauseGatherer(); 037 SymbolCollector sc = new SymbolCollector(); 038 039 List symbols = new Converter<Symbol>().setToList(sc.getSymbolsIn(s)); 040 Random r = new Random(); 041 for (int i = 0; i < symbols.size(); i++) { 042 Symbol sym = (Symbol) symbols.get(i); 043 myModel = myModel.extend(sym, Util.randomBoolean()); 044 } 045 List<Sentence> clauses = new Converter<Sentence>() 046 .setToList(clauseGatherer.getClausesFrom(transformer 047 .transform(s))); 048 049 for (int i = 0; i < numberOfFlips; i++) { 050 if (getNumberOfClausesSatisfiedIn(new Converter<Sentence>() 051 .listToSet(clauses), myModel) == clauses.size()) { 052 return myModel; 053 } 054 Sentence clause = clauses.get(random.nextInt(clauses.size())); 055 056 List<Symbol> symbolsInClause = new Converter<Symbol>().setToList(sc 057 .getSymbolsIn(clause)); 058 if (random.nextDouble() >= probabilityOfRandomWalk) { 059 Symbol randomSymbol = symbolsInClause.get(random 060 .nextInt(symbolsInClause.size())); 061 myModel = myModel.flip(randomSymbol); 062 } else { 063 Symbol symbolToFlip = getSymbolWhoseFlipMaximisesSatisfiedClauses( 064 new Converter<Sentence>().listToSet(clauses), 065 symbolsInClause, myModel); 066 myModel = myModel.flip(symbolToFlip); 067 } 068 069 } 070 return null; 071 } 072 073 private Symbol getSymbolWhoseFlipMaximisesSatisfiedClauses( 074 Set<Sentence> clauses, List<Symbol> symbols, Model model) { 075 if (symbols.size() > 0) { 076 Symbol retVal = symbols.get(0); 077 int maxClausesSatisfied = 0; 078 for (int i = 0; i < symbols.size(); i++) { 079 Symbol sym = symbols.get(i); 080 if (getNumberOfClausesSatisfiedIn(clauses, model.flip(sym)) > maxClausesSatisfied) { 081 retVal = sym; 082 maxClausesSatisfied = getNumberOfClausesSatisfiedIn( 083 clauses, model.flip(sym)); 084 } 085 } 086 return retVal; 087 } else { 088 return null; 089 } 090 091 } 092 093 private int getNumberOfClausesSatisfiedIn(Set clauses, Model model) { 094 int retVal = 0; 095 Iterator i = clauses.iterator(); 096 while (i.hasNext()) { 097 Sentence s = (Sentence) i.next(); 098 if (model.isTrue(s)) { 099 retVal += 1; 100 } 101 } 102 return retVal; 103 } 104 }