UNPKG

propositional

Version:

Propositional logic symbolic computation library

163 lines (162 loc) 6.36 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.simplify = void 0; const AST = __importStar(require("../syntax/ast")); const token_1 = require("../syntax/token"); const generate_1 = require("../syntax/generate"); const equivalence_1 = require("../syntax/equivalence"); /** * Simplify an expression under the following principles: * - !0 <=> 1 * - !1 <=> 0 * * - !!a <=> a * * - (a & a) <=> a * - (a | a) <=> a * - (a ^ a) <=> 0 * - (a => a) <=> 1 * - (a <=> a) <=> 1 * * - (a & !a) <=> 0 * - (a | !a) <=> 1 * - (a ^ !a) <=> 1 * - (a <=> !a) <=> 0 * * - (a => !a) <=> !a * - (!a => a) <=> a * * - (0 & a) <=> 0 * - (0 | a) <=> a * - (0 ^ a) <=> a * - (0 => a) <=> 1 * - (0 <=> a) <=> !a * * - (1 & a) <=> a * - (1 | a) <=> 1 * - (1 ^ a) <=> !a * - (1 => a) <=> a * - (1 <=> a) <=> a * * - (a => 0) <=> !a * - (a => 1) <=> 1 */ function simplify(expression) { switch (true) { case expression instanceof AST.UnaryExpression: let inner = simplify(expression.inner); // !0, !1 if (inner instanceof AST.Literal && inner.value.type == token_1.TokenType.CONSTANT) { if ((0, equivalence_1.syntacticallyEquivalent)(inner, generate_1.FALSE)) { return generate_1.TRUE; } else { return generate_1.FALSE; } } // !!a <=> a if (inner instanceof AST.UnaryExpression) { return simplify(inner.inner); } return (0, generate_1.not)(inner); case expression instanceof AST.Literal: return expression; case expression instanceof AST.BinaryExpression: let left = simplify(expression.left); let right = simplify(expression.right); // left == right if ((0, equivalence_1.syntacticallyEquivalent)(left, right)) { switch (expression.operator.type) { case token_1.TokenType.AND: case token_1.TokenType.OR: return left; case token_1.TokenType.XOR: return generate_1.FALSE; case token_1.TokenType.IF: case token_1.TokenType.IFF: return generate_1.TRUE; } } // !left = right if ((0, equivalence_1.syntacticallyEquivalent)((0, generate_1.not)(left), right) || (0, equivalence_1.syntacticallyEquivalent)(left, (0, generate_1.not)(right))) { switch (expression.operator.type) { case token_1.TokenType.AND: case token_1.TokenType.IFF: return generate_1.FALSE; case token_1.TokenType.OR: case token_1.TokenType.XOR: return generate_1.TRUE; case token_1.TokenType.IF: return right; } } // Simplify logic for 1s and 0s by swapping right 1s and 0s to the left if (((0, equivalence_1.syntacticallyEquivalent)(right, generate_1.TRUE) || (0, equivalence_1.syntacticallyEquivalent)(right, generate_1.FALSE)) && expression.operator.type != token_1.TokenType.IF) { let temp = left; left = right; right = temp; } // left == 0 if ((0, equivalence_1.syntacticallyEquivalent)(left, generate_1.FALSE)) { switch (expression.operator.type) { case token_1.TokenType.AND: return generate_1.FALSE; case token_1.TokenType.OR: case token_1.TokenType.XOR: return right; case token_1.TokenType.IF: return generate_1.TRUE; case token_1.TokenType.IFF: return simplify((0, generate_1.not)(right)); } } // left == 1 if ((0, equivalence_1.syntacticallyEquivalent)(left, generate_1.TRUE)) { switch (expression.operator.type) { case token_1.TokenType.OR: return generate_1.TRUE; case token_1.TokenType.XOR: return simplify((0, generate_1.not)(right)); case token_1.TokenType.AND: case token_1.TokenType.IF: case token_1.TokenType.IFF: return right; } } // a => 0 if ((0, equivalence_1.syntacticallyEquivalent)(right, generate_1.FALSE)) { return simplify((0, generate_1.not)(left)); } // a => 1 if ((0, equivalence_1.syntacticallyEquivalent)(right, generate_1.TRUE)) { return generate_1.TRUE; } // Otherwise, no simplification available return new AST.BinaryExpression(left, expression.operator, right); } } exports.simplify = simplify;