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    }