Implementation of the Davis-Putnam-Logemann-Loveland (DPLL) algorithm.
Everytime the #solve() method is called a new valuation is created and passed to the successive
steps of the
algorithm.
- Evalutate the CNF formula with the current valuation by calling
CnfFormula#evaluate(Valuation) - Return the solution of the valuation (a map) if evaluation is
true - Run the unit propagate step of the algorithm by calling
CnfFormula#unitPropagate(Valuation) - Run the pure literal assign step of the algorithm by calling
CnfFormula#pureLiteralAssign(Valuation) - re-evaluate the CNF formula with the current valuation.
- Return the solution of the valuation (a map) if evaluation is
true - Return
undefinedif the evaluation isfalse - Choose a variable and assign it to
true - Return the solution of the valuation (a map) if evaluation is
true - Re-run the algorithm with the variable assigned to
falseinstead
The algorithm will eventually converge to either a solution or undefined.
Step 8 is known as the splitting rule. Two selection modes are available:
random selection amongst unassigned variables; enabled by default or by calling
#randomVariableSelection()variable with highest occurrence amongst the unassigned variables; enabled by calling
#highestOccurrenceVariableSelection()var dpll = require('./src/dpll.js'); [...] var solver = new dpll.Solver(formula); var solution = solver.highestOccurrenceVariableSelection().solve();
More about...
Valuation: Valuation.js
CNF formula: CnfFormula.js
Map: Map.js
Source code
import Valuation.js
var Valuation = require('./Valuation');Constructor - takes the formula to be solved as an input.
function Solver(formula) {
'use strict';true for selection of unassigned random variable, false for selection of unassigned variable with highest
occurrence.
var useRandomSelection = true;Runs all steps of the algorithm eventually calling itself back if need be. Fills the specified
valuation along the way.
function run(valuation) {
var formulaEval = formula.evaluate(valuation);
if (formulaEval === undefined) {
formula.unitPropagate(valuation);
formula.pureLiteralAssign(valuation);
var afterOptimEval = formula.evaluate(valuation);
if (true === afterOptimEval) {
return valuation.solution();
} else if (false === afterOptimEval) {
return undefined;
} else {select variable to assign
var newVar;
if (useRandomSelection) {
newVar = valuation.randomUnassignedVariable();
} else {
newVar = valuation.highestOccurrenceVariable();
}evaluate with truth value = true.
valuation.putSolution(newVar, true);
var afterNewVarTrueEval = formula.evaluate(valuation);
if (true === afterNewVarTrueEval) {solution found.
return valuation.solution();
} else {set truth value to false and rerun.
valuation.putSolution(newVar, false);
return run(valuation);
}
}
} else if (formulaEval) {
return valuation.solution();
} else {
return undefined;
}
}Sets the variable selection alogrithm to random selection mode and return this.
this.randomVariableSelection = function() {
useRandomSelection = true;
return this;
};Sets the variable selection alogrithm to highest occurrence selection mode and return this.
this.highestOccurrenceVariableSelection = function() {
useRandomSelection = false;
return this;
};Tries and solves the CNF. Returns either a map whose keys are the variables and values are
either true or false.
if the CNF formula has been solved the result will NOT
contain the variables that have been optimized away. For instance
if the formula contains the clause (x | -x | y) and x is not present
in any other clause of the formula, then x is optimized away and therefore
its value is irrelevant - i.e. it can be true or false.
this.solve = function() {
var valuation = new Valuation(formula.variables());
return run(valuation);
};
};expose API to Node.js
module.exports = Solver;