Package aima.core.logic.propositional.algorithms

Source Code of aima.core.logic.propositional.algorithms.DPLL

package aima.core.logic.propositional.algorithms;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import aima.core.logic.propositional.parsing.PEParser;
import aima.core.logic.propositional.parsing.ast.Sentence;
import aima.core.logic.propositional.parsing.ast.Symbol;
import aima.core.logic.propositional.parsing.ast.UnarySentence;
import aima.core.logic.propositional.visitors.CNFClauseGatherer;
import aima.core.logic.propositional.visitors.CNFTransformer;
import aima.core.logic.propositional.visitors.SymbolClassifier;
import aima.core.logic.propositional.visitors.SymbolCollector;
import aima.core.util.Converter;
import aima.core.util.SetOps;

/**
* @author Ravi Mohan
* @author Mike Stampone
*/
public class DPLL {

  private static final Converter<Symbol> SYMBOL_CONVERTER = new Converter<Symbol>();

  /**
   * Returns <code>true</code> if the specified sentence is satisfiable. A
   * sentence is satisfiable if it is true in, or satisfied by, some model.
   *
   * @param s
   *            a sentence in propositional logic
   *
   * @return <code>true</code> if the specified sentence is satisfiable.
   */
  public boolean dpllSatisfiable(Sentence s) {

    return dpllSatisfiable(s, new Model());
  }

  /**
   * Returns <code>true</code> if the specified sentence is satisfiable. A
   * sentence is satisfiable if it is true in, or satisfied by, some model.
   *
   * @param string
   *            a String representation of a Sentence in propositional logic
   *
   * @return <code>true</code> if the specified sentence is satisfiable.
   */
  public boolean dpllSatisfiable(String string) {
    Sentence sen = (Sentence) new PEParser().parse(string);
    return dpllSatisfiable(sen, new Model());
  }

  /**
   * Returns <code>true</code> if the specified sentence is satisfiable. A
   * sentence is satisfiable if it is true in, or satisfied by, some model.
   *
   * @param s
   *            a sentence in propositional logic
   * @param m
   *            a model the sentence must be true in
   *
   * @return <code>true</code> if the specified sentence is satisfiable.
   */
  public boolean dpllSatisfiable(Sentence s, Model m) {
    Set<Sentence> clauses = new CNFClauseGatherer()
        .getClausesFrom(new CNFTransformer().transform(s));
    List<Symbol> symbols = SYMBOL_CONVERTER.setToList(new SymbolCollector()
        .getSymbolsIn(s));
    // System.out.println(" numberOfSymbols = " + symbols.size());
    return dpll(clauses, symbols, m);
  }

  public List<Sentence> clausesWithNonTrueValues(List<Sentence> clauseList,
      Model model) {
    List<Sentence> clausesWithNonTrueValues = new ArrayList<Sentence>();
    for (int i = 0; i < clauseList.size(); i++) {
      Sentence clause = clauseList.get(i);
      if (!(isClauseTrueInModel(clause, model))) {
        if (!(clausesWithNonTrueValues.contains(clause))) {// defensive
          // programming not really necessary
          clausesWithNonTrueValues.add(clause);
        }
      }

    }
    return clausesWithNonTrueValues;
  }

  public SymbolValuePair findPureSymbolValuePair(List<Sentence> clauseList,
      Model model, List<Symbol> symbols) {
    List<Sentence> clausesWithNonTrueValues = clausesWithNonTrueValues(
        clauseList, model);
    Sentence nonTrueClauses = LogicUtils.chainWith("AND",
        clausesWithNonTrueValues);
    // System.out.println("Unsatisfied clauses = "
    // + clausesWithNonTrueValues.size());
    Set<Symbol> symbolsAlreadyAssigned = model.getAssignedSymbols();

    // debug
    // List symList = asList(symbolsAlreadyAssigned);
    //
    // System.out.println(" assignedSymbols = " + symList.size());
    // if (symList.size() == 52) {
    // System.out.println("untrue clauses = " + clausesWithNonTrueValues);
    // System.out.println("model= " + model);
    // }

    // debug
    List<Symbol> purePositiveSymbols = SYMBOL_CONVERTER.setToList(SetOps
        .difference(new SymbolClassifier()
            .getPurePositiveSymbolsIn(nonTrueClauses),
            symbolsAlreadyAssigned));

    List<Symbol> pureNegativeSymbols = SYMBOL_CONVERTER.setToList(SetOps
        .difference(new SymbolClassifier()
            .getPureNegativeSymbolsIn(nonTrueClauses),
            symbolsAlreadyAssigned));
    // if none found return "not found
    if ((purePositiveSymbols.size() == 0)
        && (pureNegativeSymbols.size() == 0)) {
      return new SymbolValuePair();// automatically set to null values
    } else {
      if (purePositiveSymbols.size() > 0) {
        Symbol symbol = new Symbol(
            (purePositiveSymbols.get(0)).getValue());
        if (pureNegativeSymbols.contains(symbol)) {
          throw new RuntimeException("Symbol " + symbol.getValue()
              + "misclassified");
        }
        return new SymbolValuePair(symbol, true);
      } else {
        Symbol symbol = new Symbol(
            (pureNegativeSymbols.get(0)).getValue());
        if (purePositiveSymbols.contains(symbol)) {
          throw new RuntimeException("Symbol " + symbol.getValue()
              + "misclassified");
        }
        return new SymbolValuePair(symbol, false);
      }
    }
  }

  //
  // PRIVATE METHODS
  //

  private boolean dpll(Set<Sentence> clauses, List<Symbol> symbols,
      Model model) {
    // List<Sentence> clauseList = asList(clauses);
    List<Sentence> clauseList = new Converter<Sentence>()
        .setToList(clauses);
    // System.out.println("clauses are " + clauses.toString());
    // if all clauses are true return true;
    if (areAllClausesTrue(model, clauseList)) {
      // System.out.println(model.toString());
      return true;
    }
    // if even one clause is false return false
    if (isEvenOneClauseFalse(model, clauseList)) {
      // System.out.println(model.toString());
      return false;
    }
    // System.out.println("At least one clause is unknown");
    // try to find a unit clause
    SymbolValuePair svp = findPureSymbolValuePair(clauseList, model,
        symbols);
    if (svp.notNull()) {
      List<Symbol> newSymbols = new ArrayList<Symbol>(symbols);
      newSymbols.remove(new Symbol(svp.symbol.getValue()));
      Model newModel = model.extend(new Symbol(svp.symbol.getValue()),
          svp.value.booleanValue());
      return dpll(clauses, newSymbols, newModel);
    }

    SymbolValuePair svp2 = findUnitClause(clauseList, model, symbols);
    if (svp2.notNull()) {
      List<Symbol> newSymbols = new ArrayList<Symbol>(symbols);
      newSymbols.remove(new Symbol(svp2.symbol.getValue()));
      Model newModel = model.extend(new Symbol(svp2.symbol.getValue()),
          svp2.value.booleanValue());
      return dpll(clauses, newSymbols, newModel);
    }

    Symbol symbol = (Symbol) symbols.get(0);
    // System.out.println("default behaviour selecting " + symbol);
    List<Symbol> newSymbols = new ArrayList<Symbol>(symbols);
    newSymbols.remove(0);
    return (dpll(clauses, newSymbols, model.extend(symbol, true)) || dpll(
        clauses, newSymbols, model.extend(symbol, false)));
  }

  private boolean isEvenOneClauseFalse(Model model, List<Sentence> clauseList) {
    for (int i = 0; i < clauseList.size(); i++) {
      Sentence clause = clauseList.get(i);
      if (model.isFalse(clause)) {
        // System.out.println(clause.toString() + " is false");
        return true;
      }

    }

    return false;
  }

  private boolean areAllClausesTrue(Model model, List<Sentence> clauseList) {

    for (int i = 0; i < clauseList.size(); i++) {
      Sentence clause = clauseList.get(i);
      // System.out.println("evaluating " + clause.toString());
      if (!isClauseTrueInModel(clause, model)) { // ie if false or
        // UNKNOWN
        // System.out.println(clause.toString()+ " is not true");
        return false;
      }

    }
    return true;
  }

  private boolean isClauseTrueInModel(Sentence clause, Model model) {
    List<Symbol> positiveSymbols = SYMBOL_CONVERTER
        .setToList(new SymbolClassifier().getPositiveSymbolsIn(clause));
    List<Symbol> negativeSymbols = SYMBOL_CONVERTER
        .setToList(new SymbolClassifier().getNegativeSymbolsIn(clause));

    for (Symbol symbol : positiveSymbols) {
      if ((model.isTrue(symbol))) {
        return true;
      }
    }
    for (Symbol symbol : negativeSymbols) {
      if ((model.isFalse(symbol))) {
        return true;
      }
    }
    return false;

  }

  private SymbolValuePair findUnitClause(List<Sentence> clauseList,
      Model model, List<Symbol> symbols) {
    for (int i = 0; i < clauseList.size(); i++) {
      Sentence clause = (Sentence) clauseList.get(i);
      if ((clause instanceof Symbol)
          && (!(model.getAssignedSymbols().contains(clause)))) {
        // System.out.println("found unit clause - assigning");
        return new SymbolValuePair(new Symbol(
            ((Symbol) clause).getValue()), true);
      }

      if (clause instanceof UnarySentence) {
        UnarySentence sentence = (UnarySentence) clause;
        Sentence negated = sentence.getNegated();
        if ((negated instanceof Symbol)
            && (!(model.getAssignedSymbols().contains(negated)))) {
          // System.out.println("found unit clause type 2 -
          // assigning");
          return new SymbolValuePair(new Symbol(
              ((Symbol) negated).getValue()), false);
        }
      }

    }

    return new SymbolValuePair();// failed to find any unit clause;

  }

  public class SymbolValuePair {
    public Symbol symbol;// public to avoid unnecessary get and set

    // accessors

    public Boolean value;

    public SymbolValuePair() {
      // represents "No Symbol found with a boolean value that makes all
      // its literals true
      symbol = null;
      value = null;
    }

    public SymbolValuePair(Symbol symbol, boolean bool) {
      // represents "Symbol found with a boolean value that makes all
      // its literals true
      this.symbol = symbol;
      value = new Boolean(bool);
    }

    public boolean notNull() {
      return (symbol != null) && (value != null);
    }

    @Override
    public String toString() {
      String symbolString, valueString;
      if (symbol == null) {
        symbolString = "NULL";
      } else {
        symbolString = symbol.toString();
      }
      if (value == null) {
        valueString = "NULL";
      } else {
        valueString = value.toString();
      }
      return symbolString + " -> " + valueString;
    }
  }
}
TOP

Related Classes of aima.core.logic.propositional.algorithms.DPLL

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.