{
	"name": "logic-solver",
	"versions": {
		"2.0.0": {
			"name": "logic-solver",
			"version": "2.0.0",
			"description": "General satisfiability solver for logic problems",
			"main": "logic-solver.js",
			"repository": {
				"type": "git",
				"url": "git://github.com/meteor/logic-solver.git"
			},
			"keywords": [
				"sat",
				"solver",
				"logic",
				"constraint"
			],
			"dependencies": {
				"underscore": "^1.7.0"
			},
			"author": {
				"name": "David Greenspan",
				"email": "david@meteor.com"
			},
			"license": "MIT",
			"bugs": {
				"url": "https://github.com/meteor/logic-solver/issues"
			},
			"gitHead": "2719e656323131585eb8027782822fa2673d0c06",
			"homepage": "https://github.com/meteor/logic-solver",
			"_id": "logic-solver@2.0.0",
			"scripts": {},
			"_shasum": "a45365cdc3e8e0208562d3e5210db3cfde988c4d",
			"_from": ".",
			"_npmVersion": "2.1.17",
			"_nodeVersion": "0.10.36",
			"_npmUser": {
				"name": "dgreensp",
				"email": "davidgreenspan@gmail.com"
			},
			"dist": {
				"shasum": "a45365cdc3e8e0208562d3e5210db3cfde988c4d",
				"tarball": "https://registry.npmjs.org/logic-solver/-/logic-solver-2.0.0.tgz"
			},
			"maintainers": [
				{
					"name": "dgreensp",
					"email": "davidgreenspan@gmail.com"
				}
			],
			"directories": {},
			"contributors": []
		},
		"2.0.1": {
			"name": "logic-solver",
			"version": "2.0.1",
			"description": "General satisfiability solver for logic problems",
			"main": "logic-solver.js",
			"repository": {
				"type": "git",
				"url": "git://github.com/meteor/logic-solver.git"
			},
			"keywords": [
				"sat",
				"solver",
				"logic",
				"constraint"
			],
			"dependencies": {
				"underscore": "^1.7.0"
			},
			"author": {
				"name": "David Greenspan",
				"email": "david@meteor.com"
			},
			"license": "MIT",
			"bugs": {
				"url": "https://github.com/meteor/logic-solver/issues"
			},
			"gitHead": "aa1a5d010ffb2f1e1e9077caf3f2c8a46ca80d04",
			"homepage": "https://github.com/meteor/logic-solver#readme",
			"_id": "logic-solver@2.0.1",
			"scripts": {},
			"_shasum": "e9fa47002eb5d8cda7616d41639b97552eb674be",
			"_from": ".",
			"_npmVersion": "3.8.3",
			"_nodeVersion": "5.10.0",
			"_npmUser": {
				"name": "dgreensp",
				"email": "davidgreenspan@gmail.com"
			},
			"dist": {
				"shasum": "e9fa47002eb5d8cda7616d41639b97552eb674be",
				"tarball": "https://registry.npmjs.org/logic-solver/-/logic-solver-2.0.1.tgz"
			},
			"maintainers": [
				{
					"name": "dgreensp",
					"email": "davidgreenspan@gmail.com"
				}
			],
			"_npmOperationalInternal": {
				"host": "packages-16-east.internal.npmjs.com",
				"tmp": "tmp/logic-solver-2.0.1.tgz_1463437309233_0.5546976951882243"
			},
			"directories": {},
			"contributors": []
		}
	},
	"time": {
		"modified": "2017-03-02T17:58:37.107Z",
		"created": "2015-05-06T23:40:54.184Z",
		"2.0.0": "2015-05-06T23:40:54.184Z",
		"2.0.1": "2016-05-16T22:21:51.593Z"
	},
	"users": {},
	"dist-tags": {
		"latest": "2.0.1"
	},
	"_uplinks": {
		"npmjs": {
			"etag": "W/\"cb78f7c061b8612dc288910fc24559e8\"",
			"fetched": 1597847594280
		}
	},
	"_distfiles": {
		"logic-solver-2.0.0.tgz": {
			"url": "https://registry.npmjs.org/logic-solver/-/logic-solver-2.0.0.tgz",
			"sha": "a45365cdc3e8e0208562d3e5210db3cfde988c4d",
			"registry": "npmjs"
		},
		"logic-solver-2.0.1.tgz": {
			"url": "https://registry.npmjs.org/logic-solver/-/logic-solver-2.0.1.tgz",
			"sha": "e9fa47002eb5d8cda7616d41639b97552eb674be",
			"registry": "npmjs"
		}
	},
	"_attachments": {
		"logic-solver-2.0.1.tgz": {
			"shasum": "e9fa47002eb5d8cda7616d41639b97552eb674be"
		}
	},
	"_rev": "12-e8c17a3d495d47eb",
	"_id": "logic-solver",
	"readme": "# Logic Solver\n\n## Introduction\n\nLogic Solver is a boolean satisfiability solver written in JavaScript.\nGiven a problem expressed as logical constraints on boolean\n(true/false) variables, it either provides a possible solution, or\ntells you definitively that there is no possible assignment of the\nvariables that satisfies the constraints.\n\nMany kinds of logic problems can be expressed in terms of constraints\non boolean variables, including Sudoku puzzles, scheduling problems,\nand the package dependency problem faced by package managers that\nautomatically resolve version conflicts.\n\nLogic Solver can handle complex problems with thousands of variables,\nand has some powerful features such as incremental solving and solving\nunder temporary assumptions.  It also supports small-integer sums and\ninequalities, and can minimize or maximize an integer expression.\n\nLogic Solver contains a copy of [MiniSat](http://minisat.se/), an\nindustrial-strength SAT solver, compiled from C++ to JavaScript using\n[Emscripten](http://emscripten.org).  See [About\nMiniSat](#about-minisat) for more information.\n\nLogic Solver can solve a hard Sudoku in under a second in a web browser,\nwith very clean-looking code compared to many constraint solvers.\n[**Try this demo**](http://sudoku-demo.meteor.com/)\n\n## On NPM\n\n```\nvar Logic = require('logic-solver');\n```\n\nhttps://www.npmjs.com/package/logic-solver\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [On NPM](#on-npm)\n- [Example: Dinner Guests](#example-dinner-guests)\n- [Example: Magic Squares](#example-magic-squares)\n- [Variables](#variables)\n  - [Logic.Solver#getVarNum(variableName, [noCreate])](#logicsolvergetvarnumvariablename-nocreate)\n  - [Logic.Solver#getVarName(variableNum)](#logicsolvergetvarnamevariablenum)\n- [Terms](#terms)\n  - [Logic.FALSE, Logic.TRUE](#logicfalse-logictrue)\n  - [Logic.isTerm(value)](#logicistermvalue)\n  - [Logic.isNameTerm(value)](#logicisnametermvalue)\n  - [Logic.isNumTerm(value)](#logicisnumtermvalue)\n  - [Logic.Solver#toNameTerm(term)](#logicsolvertonametermterm)\n  - [Logic.Solver#toNumTerm(term, [noCreate])](#logicsolvertonumtermterm-nocreate)\n- [Formulas](#formulas)\n  - [Logic.isFormula(value)](#logicisformulavalue)\n  - [Logic.not(operand)](#logicnotoperand)\n  - [Logic.or(operands...)](#logicoroperands)\n  - [Logic.and(operands...)](#logicandoperands)\n  - [Logic.xor(operands...)](#logicxoroperands)\n  - [Logic.implies(operand1, operand2)](#logicimpliesoperand1-operand2)\n  - [Logic.equiv(operand1, operand2)](#logicequivoperand1-operand2)\n  - [Logic.exactlyOne(operands...)](#logicexactlyoneoperands)\n  - [Logic.atMostOne(operands...)](#logicatmostoneoperands)\n- [Logic.Solver](#logicsolver)\n  - [new Logic.Solver()](#new-logicsolver)\n  - [Logic.Solver#require(args...)](#logicsolverrequireargs)\n  - [Logic.Solver#forbid(args...)](#logicsolverforbidargs)\n  - [Logic.Solver#solve()](#logicsolversolve)\n  - [Logic.Solver#solveAssuming(assumption)](#logicsolversolveassumingassumption)\n  - [Logic.disablingAssertions(func)](#logicdisablingassertionsfunc)\n- [Logic.Solution](#logicsolution)\n  - [Logic.Solution#getMap()](#logicsolutiongetmap)\n  - [Logic.Solution#getTrueVars()](#logicsolutiongettruevars)\n  - [Logic.Solution#evaluate(expression)](#logicsolutionevaluateexpression)\n  - [Logic.Solution#getFormula()](#logicsolutiongetformula)\n  - [Logic.Solution#getWeightedSum(formulas, weights)](#logicsolutiongetweightedsumformulas-weights)\n  - [Logic.Solution#ignoreUnknownVariables()](#logicsolutionignoreunknownvariables)\n- [Optimization](#optimization)\n  - [Logic.Solver#minimizeWeightedSum(solution, formulas, weights)](#logicsolverminimizeweightedsumsolution-formulas-weights)\n  - [Logic.Solver#maximizeWeightedSum(solution, formulas, weights)](#logicsolvermaximizeweightedsumsolution-formulas-weights)\n- [Bits (integers)](#bits-integers)\n  - [new Logic.Bits(formulas)](#new-logicbitsformulas)\n  - [Logic.isBits(value)](#logicisbitsvalue)\n  - [Logic.constantBits(wholeNumber)](#logicconstantbitswholenumber)\n  - [Logic.variableBits(baseName, N)](#logicvariablebitsbasename-n)\n  - [Logic.equalBits(bits1, bits2)](#logicequalbitsbits1-bits2)\n  - [Logic.lessThan(bits1, bits2)](#logiclessthanbits1-bits2)\n  - [Logic.lessThanOrEqual(bits1, bits2)](#logiclessthanorequalbits1-bits2)\n  - [Logic.greaterThan(bits1, bits2)](#logicgreaterthanbits1-bits2)\n  - [Logic.greaterThanOrEqual(bits1, bits2)](#logicgreaterthanorequalbits1-bits2)\n  - [Logic.sum(operands...)](#logicsumoperands)\n  - [Logic.weightedSum(formulas, weights)](#logicweightedsumformulas-weights)\n- [About MiniSat](#about-minisat)\n\n## Example: Dinner Guests\n\nWe are trying to decide what combination of Alice, Bob, and Charlie\nto invite over to dinner, subject to the following constraints:\n\n* Don't invite both Alice and Bob\n* Invite either Bob or Charlie\n\nSetting up these constraints in code:\n\n```js\nvar solver = new Logic.Solver();\n\nsolver.require(Logic.atMostOne(\"Alice\", \"Bob\"));\nsolver.require(Logic.or(\"Bob\", \"Charlie\"));\n```\n\nSolving now will give us one possible solution, chosen arbitrarily:\n\n```js\nvar sol1 = solver.solve();\nsol1.getTrueVars() // => [\"Bob\"]\n```\n\nLet's see what happens if we invite Alice.  By using `solveAssuming`, we\ncan look for a solution that makes an additional logical expression true\nover the ones we have required so far:\n\n```js\nvar sol2 = solver.solveAssuming(\"Alice\");\nsol2.getTrueVars() // => [\"Alice\", \"Charlie\"]\n```\n\nAha!  It seems that inviting Alice means we can't invite Bob, but then\nwe must invite Charlie!  If our reasoning is correct, it is impossible\nto invite Alice and not invite Charlie.  We can confirm this:\n\n```js\nsolver.solveAssuming(Logic.and(\"Alice\", \"-Charlie\")) // => null\n```\n\n(Note that `\"-Charlie\"` is shorthand for `Logic.not(\"Charlie\")`.)\n\nLet's write some code to list all possible solutions:\n\n```js\nvar solutions = [];\nvar curSol;\nwhile ((curSol = solver.solve())) {\n  solutions.push(curSol.getTrueVars());\n  solver.forbid(curSol.getFormula()); // forbid the current solution\n}\n\nsolutions\n// => [[\"Alice\", \"Charlie\"], [\"Charlie\"], [\"Bob\", \"Charlie\"], [\"Bob\"]]\n```\n\nAs you can see, there are four possible solutions to the original problem.\n\nAfter running the above code, all possible solutions are now\nforbidden, so the solver is in an unsatisfiable state.  Calls to\n`solver.require` and `solver.forbid` are permanent, so we cannot\nreturn to a satisfiable state, and any call to `solve` or\n`solveAssuming` henceforth will return no solution:\n\n```js\nsolver.solve() // => null\n```\n\nIt's informative to look at the clauses generated by Logic Solver during\nthis example.  In this notation, `v` is the boolean \"OR\" operator:\n\n```\n-Alice v -Bob  (at most one of Alice, Bob)\nBob v Charlie  (at least one of Bob, Charlie)\n\nAlice v -$assump1  (solve assuming Alice)\n\n$and1 v -$assump2  (solve assuming Alice and not Charlie)\nAlice v -$and1\n-Charlie v -$and1\n\n-Alice v Bob v -Charlie  (forbid [\"Alice\", \"Charlie\"])\nAlice v Bob v -Charlie   (forbid [\"Charlie\"])\nAlice v -Bob v -Charlie  (etc.)\nAlice v -Bob v Charlie\n```\n\nThese clauses are sent to MiniSat using variable numbers in place of names,\nmaking the entire problem quite compact:\n\n```\n[[-3,-4], [4,5],\n [3,-6],\n [8,-7], [3,-8], [-5,-8],\n [-3,4,-5], [3,4,-5], [3,-4,-5], [3,-4,5]]\n```\n\n## Example: Magic Squares\n\nA 3x3 \"magic square\" is an arrangement of the digits 1 through 9 into a square\nsuch that the digits in each row, column, and diagonal add up to the same number.\nHere is an example from [Wikipedia](http://en.wikipedia.org/wiki/Magic_square):\n\n```\n2 7 6\n9 5 1\n4 3 8\n```\n\nEach row, column, and three-digit diagonal adds up to 15, as you can verify.\n(There are many 3x3 magic squares, but the magic sum is always 15, because\nall the digits together add up to 45!)\n\nLet's use Logic Solver to find magic squares.  We could be fancy about\nit and write code that would generalize to NxN magic squares, but\nlet's keep it simple and name the digit locations as follows:\n\n```\nA B C\nD E F\nG H I\n```\n\nBecause each location holds an integer, we must use integer variables instead\nof boolean variables.  An integer in Logic Solver is represented as a group\nof bits, where each bit is a boolean variable, or an entire boolean formula.\nLet's create a 4-bit group of variables for each digit location:\n\n```js\nvar A = Logic.variableBits('A', 4);\nvar B = Logic.variableBits('B', 4);\nvar C = Logic.variableBits('C', 4);\nvar D = Logic.variableBits('D', 4);\nvar E = Logic.variableBits('E', 4);\nvar F = Logic.variableBits('F', 4);\nvar G = Logic.variableBits('G', 4);\nvar H = Logic.variableBits('H', 4);\nvar I = Logic.variableBits('I', 4);\n\nvar locations = [A, B, C, D, E, F, G, H, I];\n\nA.bits // => [\"A$0\", \"A$1\", \"A$2\", \"A$3\"]\n```\n\nLet's also assign the number 15, in bit form, to a variable for convenience.\n\n```js\nvar fifteen = Logic.constantBits(15);\nfifteen.bits // => [\"$T\", \"$T\", \"$T\", \"$T\"]\n```\n\nThe binary representation of 15 is \"1111\", so its bit form consists of\nfour copies of `Logic.TRUE` or `\"$T\"`.  We didn't have to know that,\nthough, because `Logic.constantBits` generated it for us.\n\nNow, we create a Solver and express our sum constraints:\n\n```js\nvar solver = new Logic.Solver();\n\n_.each([[A,B,C], [D,E,F], [G,H,I], [A,D,G], [B,E,H], [C,F,I],\n        [A,E,I], [G,E,C]],\n       function (terms) {\n         solver.require(Logic.equalBits(Logic.sum(terms), fifteen));\n       });\n```\n\nLet's see what solution we get!\n\n```js\nvar sol1 = solver.solve();\nsol1.evaluate(A) // => 3\nsol1.evaluate(B) // => 10 (uh oh)\n_.map(locations, function (loc) { return sol1.evaluate(loc); })\n// => [3, 10, 2,\n//     4,  5, 6,\n//     8,  0, 7]\n```\n\nOops, it looks like we forgot to specify that each \"digit\" is between\n1 and 9!  There is no harm done, because we have only underspecified\nthe problem.  We can continue to use the same `solver` instance.\n\nNow we add inequalities to make each location A through I hold a number\nbetween 1 and 9 inclusive, and solve again:\n\n```js\n_.each(locations, function (loc) {\n  solver.require(Logic.greaterThanOrEqual(loc, Logic.constantBits(1)));\n  solver.require(Logic.lessThanOrEqual(loc, Logic.constantBits(9)));\n});\n\nvar sol2 = solver.solve();\n_.map(locations, function (loc) { return sol2.evaluate(loc); })\n// => [8, 1, 6,\n//     3, 5, 7,\n//     4, 9, 2]\n```\n\nNow we have a proper magic square!\n\nHowever, it just so happens that we also forgot to specify that the\nnumbers be distinct.  To demonstrate that this is an important missing\nconstraint, we can use `solveAssuming` to ask for a solution where A\nand B are equal:\n\n```js\nvar sol3 = solver.solveAssuming(Logic.equalBits(A, B));\n_.map(locations, function (loc) { return sol3.evaluate(loc); })\n// => [4, 4, 7,\n//     8, 5, 2,\n//     3, 6, 6]\n```\n\nOr where A, B, and C are equal:\n\n```js\nvar sol4 = solver.solveAssuming(Logic.and(Logic.equalBits(A, B),\n                                          Logic.equalBits(B, C)));\n_.map(locations, function (loc) { return sol4.evaluate(loc); })\n// => [5, 5, 5,\n//     5, 5, 5,\n//     5, 5, 5]\n```\n\nA good way to enforce that all locations hold different digits is to\ngenerate a requirement about each pair of different locations:\n\n```js\n_.each(locations, function (loc1, i) {\n  _.each(locations, function (loc2, j) {\n    if (i !== j) {\n      solver.forbid(Logic.equalBits(loc1, loc2));\n    }\n  });\n});\n```\n\nSolving now gives us a proper magic square again:\n\n```js\nvar sol5 = solver.solve();\n_.map(locations, function (loc) { return sol5.evaluate(loc); })\n// => [6, 7, 2,\n//     1, 5, 9,\n//     8, 3, 4]\n```\n\nIf we wished to continue interrogating the solver, we could try asking\nfor a magic square with a 1 in the upper-left corner, or proceed to\nenumerate a list of magic squares.\n\nFinally, let's demonstrate that our \"integers\" are really just groups of\nboolean variables:\n\n```js\nsol5.getTrueVars()\n// => [\"A$1\", \"A$2\", \"B$0\", \"B$1\", \"B$2\", \"C$1\", \"D$0\", \"E$0\", \"E$2\",\n//     \"F$0\", \"F$3\", \"G$3\", \"H$0\", \"H$1\", \"I$2\"]\n\n_.map(A.bits, function (v) { return sol5.evaluate(v); })\n// => [false, true, true, false]\n```\n\nYou may be wondering whether it's bad that we generated 72 constraints\nas part of finding a 3x3 magic square.  While there are certainly much\nfaster ways to calculate magic squares, it is perfectly reasonable\nwhen setting up a logic problem to generate a complete set of pairwise\nconstraints over N variables.  In fact, having more constraints often\nimproves performance in real-world problems, so it is worth generating\nextra constraints even when they are technically redundant.  More\nconstraints means more deductions can be made at each step, meaning\nfewer possibilities need to be tried that ultimately won't work out.\nIn this case, it's important that when the solver assigns a digit to a\nparticular location, it immediately be able to deduce that the same\nnumber does not appear at any other location.\n\n## Variables\n\nVariable names are Strings which can contain spaces and punctuation:\n\n```js\nLogic.implies('it is raining', 'take an umbrella');\n\nLogic.exactlyOne(\"1,1\", \"1,2\", \"1,3\")\n```\n\nRestrictions: A variable name must not be empty, consist of only the\ncharacters `0` through `9`, or start with `-`.  Variable names that\nstart with `$` are reserved for internal use.\n\nYou do not need to declare or create your variables before using them\nin formulas passed to `require` and `forbid`.\n\nWhen you pass a variable name to a Solver for the first time, a\nvariable number is allocated, and that name and number become\nsynonymous for that Solver instance.  You don't need to know about\nvariable numbers to use Logic Solver, but you can always use a\nvariable number in place of a variable name in terms and formulas, in\ncase that is useful.  (It is useful internally, and would probably be\nuseful if you were to wrap Logic Solver in another library.)  Examples\nof Solver methods that may allocate new variables are `require`,\n`forbid`, `solveAssuming`, and `getVarNum`.\n\nIf you want to add a free variable to a Solver but not require\nanything about it, you can use `getVarNum` to cause the variable to be\nallocated.  It will then appear in solutions.\n\n### Methods\n\n#### Logic.Solver#getVarNum(variableName, [noCreate])\n\nReturns the variable number for a variable name, allocating a number if\nthis is the first time this Solver has seen `variableName`.\n\n###### Parameters\n\n* `variableName` - String - A valid variable name.\n* `noCreate` - Boolean - Optional.  If true, this method will return\n  0 instead of allocating a new variable number if `variableName` is new.\n\n###### Returns\n\nInteger - A positive integer variable number, or 0 if `noCreate` is true\nand there is no variable number allocated for `variableName`.\n\n#### Logic.Solver#getVarName(variableNum)\n\nReturns the variable name for a given variable number.  An error is thrown\nif `variableNum` is not an allocated variable number.\n\n###### Parameters\n\n* `variableNum` - Integer - An allocated variable number.\n\n###### Returns\n\nString - A variable name.\n\n## Terms\n\nA Term is a variable name or number, optionally negated.  To negate a\nstring Term, prefix it with `\"-\"`.  Examples of valid Terms are\n`\"foo\"`, `\"-foo\"`, `5`, and `-5`.  In other solvers and papers, you may\nsee Terms referred to as \"literals.\"\n\nThe following are equivalent:\n\n```js\nsolver.require(\"-A\");\nsolver.require(Logic.not(\"A\"));\nsolver.forbid(\"A\");\n```\n\nIn fact, `Logic.not(\"A\")` returns `\"-A\"`.  It is valid to have more\nthan one `-` in a Term (`\"---A\"`), and the meaning will be what you'd\nexpect, but `Logic.not` will never return you such a Term, so in\npractice this case does not come up.  `Logic.not(\"-A\")` returns `\"A\"`.\n\nString Terms are called NameTerms, and numeric Terms are called\nNumTerms.  You will not normally need to use numeric Terms, but if you\ndo, note that it doesn't make sense to share them across Solver\ninstances, because each Solver has its own variable numbers.  See the\n[Variables](#variables) section for more information.\n\n### Constants\n\n#### Logic.FALSE, Logic.TRUE\n\nThese Terms represent the constant boolean values false and true.  You\nmay seem them appear as the internal variables `$F` and `$T` or `1`\nand `2`, which are automatically pinned to false and true.\n\n### Methods\n\n#### Logic.isTerm(value)\n\nReturns whether `value` is a valid Term.  A valid Term is either a\nString consisting of a valid variable name preceded by zero or more\n`-` characters, or a non-zero integer.\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.isNameTerm(value)\n\nReturns whether `value` is a valid NameTerm (a Term that is a String).\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.isNumTerm(value)\n\nReturns whether `value` is a valid NumTerm (a Term that is a Number).\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.Solver#toNameTerm(term)\n\nConverts a Term to a NameTerm if it isn't already.  If `term` is a\nNumTerm, the variable number is translated into a variable name.  An\nerror is thrown if the variable number is not an allocated variable\nnumber of this Solver.\n\n###### Parameters\n\n* `term` - Term - The Term to convert, which may be a NameTerm or\n  NumTerm.\n\n###### Returns\n\nNameTerm\n\n#### Logic.Solver#toNumTerm(term, [noCreate])\n\nConverts a Term to a NumTerm if it isn't already.  If `term` is a\nNameTerm, the variable name is translated into a variable number.  A\nnew variable number is allocated if the variable name has not been\nseen before by this Solver, unless you pass true for `noCreate`.\n\n###### Parameters\n\n* `term` - Term - The Term to convert, which may be a NameTerm or\n  NumTerm.\n* `noCreate` - Boolean - Optional.  If true, this method will not\n  allocate a new variable number if it encounters a new variable name,\n  but will return 0 instead.\n\n###### Returns\n\nNumTerm, or 0 (if `noCreate` is true and a new variable name is encountered)\n\n## Formulas\n\nA Formula is an object representing a boolean expression.\nConceptually, a Formula is built out of Terms and operations that\ncombine Terms.\n\nHere are some examples of Formulas:\n\n```js\n// A and B\nLogic.and(\"A\", \"B\")\n\n// If exactly one of (A, B, C) is true, then A does not equal D.\nLogic.implies(Logic.exactlyOne(\"A\", \"B\", \"C\"),\n              Logic.not(Logic.equiv(\"A\", \"D\")))\n\n// More of (x1, x2, x3) are true than (y1, y2, y3)\nvar xs = [\"x1\", \"x2\", \"x3\"];\nvar ys = [\"y1\", \"y2\", \"y3\"];\nLogic.greaterThan(Logic.sum(xs), Logic.sum(ys))\n```\n\nFormulas are immutable.  To be on the safe side, do not mutate any arrays\nyou use to create a Formula.\n\nFormulas are Solver-independent.  They can be created without a Solver,\nand although Solvers keep track of Formula objects and recognize them\n(to avoid compiling the same Formula twice), a Formula object never\nbecomes tied to one Solver object and can always be reused, as long as\nit doesn't contain any explicit variable numbers (NumTerms).\n\nA Term is not a Formula, but you can always pass a Term anywhere a Formula\nis required.\n\nFunctions such as `Logic.and` and `Logic.greaterThan` are called\nFormula constructor functions.  One thing to note about them is that\nthey do not always return Formulas, but may return Terms as well.\n`Logic.and(\"A\")`, for example, returns `\"A\"`.  Some constructor functions\ntake any number of arguments, which may be nested in arrays, so that\nthe following are equivalent:\n\n```js\nLogic.and(\"A\", \"B\", \"C\")\nLogic.and([\"A\", \"B\", \"C\"])\nLogic.and(\"A\", [[\"B\", \"C\"]], [])\n```\n\nTo use a Formula, you must tell a Solver to `require` or `forbid` it.\nOtherwise, the Formula does not take effect.\n\n```js\nvar solver = new Logic.Solver();\nsolver.require(\"A\");\n\nLogic.exactlyOne(\"A\", \"B\"); // no effect, just creates a Formula\n\nsolver.require(Logic.exactlyOne(\"A\", \"B\")); // this works\n\nvar myFormula = Logic.exactlyOne(\"A\", \"B\");\nsolver.require(myFormula); // this also works\n```\n\nYou should save and reuse Formula objects whenever possible, because\nthe Solver will recognize the Formula object and not recompile it.\nInternally, each Formula is replaced by a variable in the Solver, such\nas `$and1` for a `Logic.and`, and clauses are generated that relate\nthe variable to the operands of the Formula.  When you pass the same\nFormula object again, it is replaced by the same variable, and the\nFormula only needs to be compiled once.\n\nFormulas that operate on integers are documented in the\n[Bits](#bits-integers) section.\n\n### Methods\n\n#### Logic.isFormula(value)\n\nReturns true if `value` is a Formula object.  (A Term is not a Formula.)\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.not(operand)\n\nRepresents a boolean expression that is true when its operand is false,\nand vice versa.\n\nWhen called on an operand that is a NameTerm, NumTerm, or Formula, returns\na value of the same kind.\n\n###### Parameters\n\n* `operand` - Formula or Term\n\n###### Returns\n\nFormula or Term (same kind as `operand`)\n\n###### Examples\n\n```js\nLogic.not(\"A\") // => \"-A\"\nLogic.not(\"-A\") // => \"A\"\nLogic.not(Logic.and(\"A\", \"B\")) // => a Formula object\n```\n\n#### Logic.or(operands...)\n\nRepresents a boolean expression that is true when at least one of its\noperands is true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.and(operands...)\n\nRepresents a boolean expression that is true when all of its operands\nare true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.xor(operands...)\n\nRepresents a boolean expression that is true when an odd number of its\noperands are true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.implies(operand1, operand2)\n\nRepresents a boolean expression that is true unless `operand1` is true and\n`operand2` is false.  In other words, if this Formula is required to be true,\nand `operand1` is true, then `operand2` must be true.\n\n###### Parameters\n\n* `operand1` - Formula or Term\n* `operand2` - Formula or Term\n\n###### Returns\n\nFormula or Term\n\n#### Logic.equiv(operand1, operand2)\n\nRepresents a boolean expression that is true when `operand1` and `operand2`\nare either both true or both false.\n\n###### Parameters\n\n* `operand1` - Formula or Term\n* `operand2` - Formula or Term\n\n###### Returns\n\nFormula or Term\n\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.exactlyOne(operands...)\n\nRepresents a boolean expression that is true when exactly one of its\noperands is true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n#### Logic.atMostOne(operands...)\n\nRepresents a boolean expression that is true when zero or one of its\noperands are true.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, or Arrays\n\n###### Returns\n\nFormula or Term\n\n## Logic.Solver\n\nYou create a Logic.Solver with `new Logic.Solver()`.\n\nA Solver maintains a list of Formulas that must be true (or false),\nwhich you can think of as a list of constraints.  Each Solver instance\nembeds a self-contained MiniSat instance, which learns and remembers\nfacts that are derived from the constraints.  At any time, you can ask\nthe Solver for a solution that satisfies the current constraints, and\nit will either provide one (chosen arbitrarily) or report that none\nexists.  You can then continue to add more constraints and solve again.\n\nSee [Example: Dinner Guests](#example-dinner-guests) for a good\nintroduction to Solver.\n\nConstraints are only ever added, never removed.  If the current\nconstraints are not satisfiable, then `solve()` will return null, and\nadding additional constraints cannot make the problem solvable again.\nHowever, using `solveAssuming`, you can look for a solution with a\nparticular Formula temporarily in force.  If `solveAssuming` returns\nnull, there is no harm done, and you can continue to solve under other\nassumptions or add more constraints.\n\nSometimes `solve()` will take a long time!  That is to be expected.\nThe best thing to do is to try expressing the problem in a different\nway, with fewer variables, more sharing of common subexpressions, or\nmore constraints between variables so that the solver can make\nimportant deductions in fewer steps.  Also try wrapping your code in\n`Logic.disablingAssertions(function () { ... })` in case runtime type\nchecks are slowing down Formula compilation.\n\nIf you need an extra speed boost in Node, you could help me create a\nbinary npm package containing a native-compiled MiniSat.\n\n### Constructor\n\n#### new Logic.Solver()\n\n### Methods\n\n#### Logic.Solver#require(args...)\n\nRequires that the Formulas and Terms listed in `args` be true in order\nfor a solution to be valid.\n\n###### Parameters\n\n* `args...` - Zero or more Formulas, Terms, or Arrays\n\n#### Logic.Solver#forbid(args...)\n\nRequires that the Formulas and Terms listed in `args` be *false* in\norder for a solution to be valid.\n\n###### Parameters\n\n* `args...` - Zero or more Formulas, Terms, or Arrays\n\n#### Logic.Solver#solve()\n\nFinds a solution that satisfies all the constraints specified with\n`require` and `forbid`, or determines that no such solution is\npossible.  A solution is an assignment of all the variables to boolean\nvalues.\n\nTo find more than one solution, you can forbid the first solution\n(using `solver.forbid(solution.getFormula())`, and solve again.\n\nSolving is fully incremental, and each call to `solve()` has the\nbenefit of everything learned by previous calls to `solve()`.\nRe-solving with one or two new constraints is typically very fast,\nbecause no work is repeated.\n\nThere is no guarantee of which solution is found if there are more\nthan one.  However, some statements can be made about what to expect:\n\n* MiniSat starts by trying a solution where all variables are false,\n  so underconstrained variables will tend to be set to false.\n\n* Calling `solve()` repeatedly, with no intervening method calls, will\n  in practice return the same solution each time.  On the other hand,\n  if you call `solve`, then `solveAssuming`, then `solve` again, the\n  call to `solveAssuming` will affect the solution returned by the\n  second `solve`.\n\n* Logic Solver and MiniSat are deterministic, so the same series of\n  calls on a new Solver will generally produce the same results.\n  However, the results may not be stable across different versions of\n  Logic Solver.\n\n###### Returns\n\nLogic.Solution, or null if no solution is possible\n\n#### Logic.Solver#solveAssuming(assumption)\n\nLike `solve()`, but looks for a solution that additionally satisfies\n`assumption`.  This is especially useful for testing whether a new\nconstraint would make the problem unsolvable before requiring it,\nor for \"querying\" the solver about different types of solutions.\n\nNote that any solution returned by `solveAssuming` is also a valid\nsolution for `solve` to return.  If you call `solve`, then\n`solveAssuming`, then `solve` again, the second `solve` will typically\nreturn the same solution as `solveAssuming`, because the internal\nstate of the solver has been changed (even though no new permanent\nconstraints have been introduced).\n\n###### Parameters\n\n* `assumption` - Formula or Term\n\n###### Returns\n\nLogic.Solution or null\n\n#### Logic.disablingAssertions(func)\n\nCalls `func()`, disabling runtime type checks and assertions for the\nduration.  This speeds up the processing of complex Formulas,\nespecially when integers or large numbers of variables are involved,\nat the price of not validating the arguments to most function calls.\nIt doesn't affect the time spent in MiniSat.\n\n###### Parameters\n\n* `func` - Function\n\n###### Returns\n\nAny - The return value of `func()`.\n\n## Logic.Solution\n\nA Solution represents an assignment or mapping of the Solver\nvariables to true/false values.  Solution objects are returned by\n`Logic.Solver#solve` and `Logic.Solver#solveAssuming`.\n\n(Variables internal to the Solver, which start with `$` and which\nyou'd probably only encounter while poking around in internals, are\nnot considered part of the assignment.)\n\n### Methods\n\n#### Logic.Solution#getMap()\n\nReturns a complete mapping of variables to their assigned values.\n\n###### Returns\n\nObject - Dictionary whose keys are variable names and whose values are\nbooleans\n\n#### Logic.Solution#getTrueVars()\n\nReturns a list of all the variables that are assigned to true by this\nSolution.\n\n###### Returns\n\nArray of String - Names of the variables that are assigned to true\n\n#### Logic.Solution#evaluate(expression)\n\nEvaluates a Formula or Term under this Solution's\nassignment of the variables, returning a boolean value.  For example:\n\n```js\nsolution.evaluate('A')\nsolution.evaluate('-A')\nsolution.evaluate(Logic.or('A', 'B'))\nsolution.evaluate(myFormula) // Formula given to the Solver earlier\n```\n\nIf `expression` is a Bits, the result of evaluation is an integer:\n\n```js\nvar x = Logic.variableBits('x', 3); // 3-digit binary variable\nvar y = Logic.variableBits('y', 3);\nvar xySum = Logic.sum(x, y);\nvar five = Logic.constantBits(5);\n\nvar solver = new Logic.Solver;\nsolver.require(Logic.equalBits(xySum, five));\nvar solution = solver.solve();\nsolution.evaluate(x) // 2 (for example)\nsolution.evaluate(y) // 3 (for example)\nsolution.evaluate(five) // 5\n```\n\nIt is an error to try to evaluate an unknown variable or a variable that\ndid not exist at the time the Solution was created, unless you call\n`ignoreUnknownVariables()` first.\n\n###### Parameters\n\n* `expression` - Formula, Term, or Bits\n\n###### Returns\n\nBoolean or Integer\n\n#### Logic.Solution#getFormula()\n\nCreates a Formula (or Term) which can be used to require, or forbid,\nthat variables are assigned to the exact values they have in this\nSolution.\n\nTo find all solutions to a logic problem:\n\n```js\nvar solver = new Logic.Solver;\nsolver.require(Logic.or('A', 'B'));\n\nvar allSolutions = [];\nvar curSolution = null;\nwhile ((curSolution = solver.solve())) {\n  allSolutions.push(curSolution.getTrueVars());\n  solver.forbid(curSolution.getFormula());\n}\n\nallSolutions // [[\"A\"], [\"A\", \"B\"], [\"B\"]]\n```\n\nAdding a constraint and solving again in this way is quite efficient.\n\nThe Formula or Term returned may not be used with any other Solver instance\nbesides the one that produced this Solution.\n\n###### Returns\n\nFormula or Term\n\n#### Logic.Solution#getWeightedSum(formulas, weights)\n\nEquivalent to `evaluate(Logic.weightedSum(formulas, weights))`, but\nmuch faster because the addition is done using integer arithmetic,\nnot boolean logic.  Rather than constructing a Bits and evaluating it,\n`getWeightedSum` simply evaluates each of the Formulas to a boolean\nvalue and then sums the weights corresponding to the Formulas that\nevaluate to true.\n\nSee `Logic.weightedSum`.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nInteger\n\n#### Logic.Solution#ignoreUnknownVariables()\n\nCauses all evaluation by this Solution instance, from now on, to treat\nvariables that aren't part of this Solution as false instead of\nthrowing an error.  This includes unrecognized variable names and\nvariables that were created after this Solution was created.\n\nThis method cannot be undone.  Good style is to call it once when you\nfirst get the Solution object, or not at all.\n\n## Optimization\n\nLogic Solver can perform basic integer optimization, using a\ncombination of inequalities and incremental solving.  The methods in\nthis section are utilities for minimizing or maximizing the value of a\nweighted sum, which is a type of problem sometimes called\npseudo-boolean optimization.\n\nTo understand how these methods work, remember that if you have one\nsolution and want another solution to the same problem, a good\ntechnique is to forbid the current solution and then re-solve.  In a\nsimilar vein, if you have one solution and want another solution that\nyields a larger or smaller value for an integer expression, you can\nsimply express this new constraint as an inequality and re-solve.  The\nfinal wrinkle is to use `solveAssuming` to test out each inequality\nbefore requiring it, so that when the minimum or maximum value is\nfound, the solver is not put into an unsatisfiable state.  The methods\nin this section implement this technique for you.\n\nThis approach to integer optimization works surprisingly well, even when it\ntakes many iterations to achieve the optimum value of a large cost function.\nHowever, depending on the structure of your problem, it may be quite a\ntime-consuming operation.\n\n### Methods\n\n#### Logic.Solver#minimizeWeightedSum(solution, formulas, weights)\n\nFinds a Solution that minimizes the value of\n`Logic.weightedSum(formulas, weights)`, and adds a requirement that\nthis mininum value is obtained (in the sense of calling\n`Solver#require` on this Solver).\n\nTo determine this minimum value, call\n`solution.getWeightedSum(formulas, weights)` on the returned Solution.\n\nA currently valid Solution must be passed in as a starting point.\nThis starting Solution must have been obtained by calling `solve` or\n`solveAssuming` on this Solver, and in addition, being \"currently\nvalid\" means that no calls to `require` or `forbid` have been made\nsince the Solution was produced that conflict with its assignments.\n\nNote that while this method may add constraints to the Solver, the Solver\nis always in a satisfiable state both before and after this method is\ncalled.\n\n###### Parameters\n\n* `solution` - Logic.Solution - A currently valid Solution for this Solver.\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nLogic.Solution - A valid Solution that achieves the minimum value of\nthe weighted sum.  It may be `solution` if no improvement on the original\nvalue of the weighted sum is possible.\n\n#### Logic.Solver#maximizeWeightedSum(solution, formulas, weights)\n\nFinds a Solution that maximizes the value of\n`Logic.weightedSum(formulas, weights)`, and adds a requirement that\nthis maximum value is obtained (in the sense of calling\n`Solver#require` on this Solver).\n\nTo determine this maximum value, call\n`solution.getWeightedSum(formulas, weights)` on the returned Solution.\n\nA currently valid Solution must be passed in as a starting point.\nThis starting Solution must have been obtained by calling `solve` or\n`solveAssuming` on this Solver, and in addition, being \"currently\nvalid\" means that no calls to `require` or `forbid` have been made\nsince the Solution was produced that conflict with its assignments.\n\nNote that while this method may add constraints to the Solver, the Solver\nis always in a satisfiable state both before and after this method is\ncalled.\n\n###### Parameters\n\n* `solution` - Logic.Solution - A currently valid Solution for this Solver.\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nLogic.Solution - A valid Solution that achieves the maximum value of\nthe weighted sum.  It may be `solution` if no improvement on the original\nvalue of the weighted sum is possible.\n\n\n## Bits (integers)\n\nA Bits object represents an N-digit binary number (non-negative\ninteger) as an array of N Formulas.  That is, it has a Formula\nfor the boolean value of each bit.  The Formulas are stored in an\narray called `bits` with the least significant bit first, so `bits[0]`\nis the ones digit, `bits[1]` is the twos digit, `bits[2]` is the fours\ndigit, and so on.  (Note that this is the opposite order from how we\nusually write numbers!  It's much more convenient because the index\ninto the array is always the same as the power of two, with numbers\ngrowing to the right as they gain larger-valued digits.)\n\nYou usually don't construct a Bits using the constructor, but instead\nusing `Logic.constantBits`, `Logic.variableBits`, or an operation on\nFormulas such as `Logic.sum`.  When you create an integer variable\nusing `Logic.variableBits`, you specify the number of bits N, but in\nother cases the number of bits is calculated automatically.  For\nexample, `Logic.sum()` with no arguments returns a 0-length Bits.\n`Logic.sum('A', 'B')` returns a 2-length Bits which is the equivalent\nof `new Logic.Bits([Logic.xor('A', 'B'), Logic.and('A', 'B')])`.\n\nSee [Example: Magic Squares](#example-magic-squares) for a good example\nof using Bits.\n\nTo avoid confusion with NumTerms, there is no automatic promotion of\nintegers to Bits.  If you want to use a constant like 5, you must\ncall `Logic.constantBits(5)` to get a Bits object.\n\nThere is currently no explicit subtraction nor any negative numbers in\nLogic Solver.\n\n###### Fields\n\n* `bits` - Array of Formula or Term - Read-only.\n\n### Constructor\n\n#### new Logic.Bits(formulas)\n\nAs previously mentioned, it's more common to create a Bits object\nusing `Logic.constantBits`, `Logic.variableBits`, `Logic.sum`, or\n`Logic.weightedSum` than using this constructor.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term - Becomes the value of\n  the `bits` property of this Bits.  The array is not copied, so\n  don't mutate the original array.  Unlike many Logic Solver\n  methods, this constructor does not take a variable number\n  of arguments, but requires exactly one array.\n\n### Methods\n\n#### Logic.isBits(value)\n\nReturns true if `value` is a Bits object.\n\n###### Parameters\n\n* `value` - Any\n\n###### Returns\n\nBoolean\n\n#### Logic.constantBits(wholeNumber)\n\nCreates a constant Bits representing the given number.\n\nFor example, `Logic.constantBits(4)` is equivalent to\n`new Logic.Bits([Logic.FALSE, Logic.FALSE, Logic.TRUE])`.\n\n###### Parameters\n\n* `wholeNumber` - non-negative integer\n\n###### Returns\n\nBits\n\n#### Logic.variableBits(baseName, N)\n\nCreates a Bits representing an N-digit integer variable.\n\nFor example, `Logic.variableBits('A', 3)` is equivalent to\n`new Logic.Bits(['A$0', 'A$1', 'A$2'])`.\n\n###### Parameters\n\n* `baseName` - String\n* `N` - non-negative integer\n\n###### Returns\n\nBits\n\n#### Logic.equalBits(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` and `bits2`\nare the same integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.lessThan(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is less than\n`bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.lessThanOrEqual(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is less than\nor equal to `bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.greaterThan(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is greater than\n`bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.greaterThanOrEqual(bits1, bits2)\n\nRepresents a boolean expression that is true when `bits1` is greater than\nor equal to `bits2`, interpreting each as a non-negative integer.\n\n###### Parameters\n\n* `bits1` - Bits\n* `bits2` - Bits\n\n###### Returns\n\nFormula or Term\n\n#### Logic.sum(operands...)\n\nRepresents an integer expression that is the sum of the values of all\nthe operands.  Bits are interpreted as integers, and booleans are\ninterpreted as 1 or 0.\n\nAs with Formula constructor functions that take a variable number of\narguments, the operands may be nested in arrays arbitrarily and\narbitrarily deeply.\n\n###### Parameters\n\n* `operands...` - Zero or more Formulas, Terms, Bits, or Arrays\n\n###### Returns\n\nBits\n\n#### Logic.weightedSum(formulas, weights)\n\nRepresents an integer expression that is a weighted sum of the given\nFormulas and Terms, after mapping false to 0 and true to 1.\n\nIn other words, the sum is:\n`(formulas[0] * weights[0]) + (formulas[1] * weights[1]) + ...`,\nwhere `formulas[0]` is replaced with 0 or 1 based on the boolean value\nof that Formula.\n\n`weights` may either be an array of non-negative integers, or a single\nnon-negative integer, in which case that weight is used for all formulas.\nIf `weights` is an array, it must have the same length as `formulas`.\n\n###### Parameters\n\n* `formulas` - Array of Formula or Term\n* `weights` - Array of non-negative integers, or a single non-negative integer\n\n###### Returns\n\nBits\n\n\n## About MiniSat\n\nSolving satisfiability problems (\"SAT-solving\") is notoriously\ndifficult from an algorithmic perspective, but solvers such as MiniSat\nimplement advanced techniques that have come out of years of research.\nYou can read more about MiniSat on its web page at http://minisat.se/.\n\nMiniSat accepts input in \"conjunctive normal form,\" which is a fairly\nlow-level representation of a logic problem.  Logic Solver's main job\nis to take arbitrary boolean formulas that you specify, such as\n\"exactly one of A, B, and C is true,\" and compile them into a list of\nstatements that must all be satisfied -- a conjunction of clauses --\neach of which is a simple disjunction such as: \"A or B or C.\"  \"Not A,\nor not B.\"\n\nAlthough MiniSat operates on a low-level representation of the problem\nand has no explicit knowledge of its overall structure, it is able to\nuse sophisticated techniques to derive new clauses that are implied by\nthe existing clauses.  A naive solver would try assigning values to\nsome of the variables until a conflict occurs, and then backtrack, but\nnot really learn anything from the conflict.  Even custom solvers\nwritten for a particular problem often work this way.  Solvers such as\nMiniSat, on the other hand, employ [Conflict-Driven Clause\nLearning](http://en.wikipedia.org/wiki/Conflict-Driven_Clause_Learning),\nwhich means that when they backtrack, they learn new clauses.  These\nnew clauses narrow the search space and cause subsequent trials to\nreach a conflict sooner, until the entire problem is found to be\nunsatisfiable or a valid assignment is found.\n\nIn principle, Logic Solver could be used as a clause generator for\nother SAT-solver backends besides MiniSat, or for a backend consisting\nof MiniSat compiled to native machine code instead of JavaScript."
}