{"id":16532427,"url":"https://github.com/sayan751/pps","last_synced_at":"2025-10-28T11:30:58.303Z","repository":{"id":57329247,"uuid":"97717641","full_name":"Sayan751/pps","owner":"Sayan751","description":"Provides implementations of some satisfiability algorithms for Propositional formulas.","archived":true,"fork":false,"pushed_at":"2018-05-11T16:10:31.000Z","size":159,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-04T06:35:46.804Z","etag":null,"topics":["propositional-proof-system","sat"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sayan751.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-19T13:12:27.000Z","updated_at":"2024-12-18T23:29:17.000Z","dependencies_parsed_at":"2022-09-01T09:40:43.075Z","dependency_job_id":null,"html_url":"https://github.com/Sayan751/pps","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sayan751%2Fpps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sayan751%2Fpps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sayan751%2Fpps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sayan751%2Fpps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sayan751","download_url":"https://codeload.github.com/Sayan751/pps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238638460,"owners_count":19505605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["propositional-proof-system","sat"],"created_at":"2024-10-11T18:12:37.130Z","updated_at":"2025-10-28T11:30:57.946Z","avatar_url":"https://github.com/Sayan751.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Propositional Proof System (PPS) #\n\nThis repository provides well tested implementations of some satisfiability algorithms for propositional formulas.\n\n[![Build Status](https://travis-ci.org/Sayan751/pps.svg?branch=master)](https://travis-ci.org/Sayan751/pps)\n[![codecov](https://codecov.io/gh/Sayan751/pps/branch/master/graph/badge.svg)](https://codecov.io/gh/Sayan751/pps)\n\n[![NPM](https://nodei.co/npm/pps2.png)](https://nodei.co/npm/pps2/)\n\n* [Getting Started](#getting-started)\n* [Propositional Formulas](#propositional-formulas)\n  * [Formulas in textual forms](#formulas-in-textual-forms)\n  * [Formulas as `CNF` object](#formulas-as-`cnf`-object)\n* [Implemented Satisfiability Algorithms](#implemented-satisfiability-algorithms)\n  * [Truth Table Algorithm](#truth-table-algorithm)\n  * [Independent Set Algorithm](#independent-set-algorithm)\n  * [2-SAT](#2-sat)\n* [Check satisfiability of `CNF` object directly](#check-satisfiability-of-cnf-object-directly)\n* [Check if \u0026#9082; \u0026#8872; \u0026#946;](#check-if---β)\n* [Check if \u0026#9082; \u0026#8776; \u0026#946;](#check-if---β-1)\n* [Check for minimal unsatisfiability (MU)](#check-for-minimal-unsatisfiability-mu)\n* [Convert a formula in NNF to (Q)CNF](#convert-a-formula-in-nnf-to-qcnf)\n\n## Getting Started ##\n\nInstall the package using\n\n```node\nnpm install --save pps2\n```\n\nYes, there is an existing npm package `pps` :broken_heart:\n\nUse it in your code as follows.\n\n```javascript\n// using require\nconst pps2 = require(\"pps2\");\npps2.TruthTable.isSat(\"x and notx\"); // false\npps2.TruthTable.isSat(\"x or notx\"); // true\n\n// or using ES6 import\nimport { TruthTable } from \"pps2\";\nTruthTable.isSat(\"x and notx\"); // false\nTruthTable.isSat(\"x or notx\"); // true\n```\n\n## Propositional Formulas ##\n\nAs said above, this repository provides implementations of some satisfiability algorithms of propositional formulas, it expects the input formulas to be in [CNF](https://en.wikipedia.org/wiki/Conjunctive_normal_form).\nSome valid examples of CNF are x \u0026#8743; y, x \u0026#8744; y, (x \u0026#8744; y) \u0026#8743; (\u0026#172;x \u0026#8744; \u0026#172;y), etc.\nOnly the following connectives in the formula are supported:\n\n* AND (\u0026#8743;)\n* OR (\u0026#8744;)\n* NOT (\u0026#172;)\n\n_Implication, and equivalence in the formula are not supported, and such formulas need to be converted to [NNF](https://en.wikipedia.org/wiki/Negation_normal_form) first._\n\nInput formula can be a string or a `CNF` object.\n\n### Formulas in textual forms ###\n\nIf the formula is a string then it needs to be in any of these following forms:\n\n* (x \u0026#8744; y) \u0026#8743; (\u0026#172;x \u0026#8744; \u0026#172;y) - using unicode chars\n* (x OR y) AND (NOTx OR NOTy) - using textual forms (connectives are case insensitive; i.e. AND, and, or AnD refers same 'AND' connective).\n* (x || y) \u0026\u0026 (!x || !y)\n\nIt also supports mixed forms such as (x OR y) \u0026#8743; (NOTx \u0026#8744; \u0026#172;y) :confused: (yes, there are test cases for that :grin:), however doing so only affects the readability.\n\nAny formula in textual form can be parsed to a `CNF` object. Example:\n\n```javascript\nimport {CNF} from \"pps2\";\nconst cnf: CNF = CNF.parse(\"x and notx\");\n```\n\n### Formulas as `CNF` object ###\n\nAlternatively, you can instantiate a CNF object directly.\nAs a `CNF` is a conjunction of `Clause`(s), which are in turn disjunction of `Literal`(s), to instantiate a `CNF` object needs more or less instantiating all three classes. Below is a minimal example to instantiate x \u0026#8743; \u0026#172;x.\n\n```javascript\nimport {Clause, CNF, Literal} from \"pps2\";\nconst cnf: CNF = new CNF([\n    new Clause([new Literal(\"x\")]), // x\n    new Clause([new Literal(\"x\", true)]) // not x\n]);\n```\n\nThe signature of `Literal`'s `ctor` is as follows:\n\n```javascript\n// by default all literals as positive if not specified otherwise\nconstructor(variable: string, isNegative: boolean = false);\n```\n\nAnother slightly complex example of instantiating (x \u0026#8744; \u0026#172;y) \u0026#8743; (\u0026#172;x \u0026#8744; y):\n\n```javascript\nimport {Clause, CNF, Literal} from \"pps2\";\nconst cnf: CNF = new CNF([\n    new Clause([new Literal(\"x\"), new Literal(\"y\", true)]), // (x OR NOTy)\n    new Clause([new Literal(\"x\", true), new Literal(\"y\")])  // (NOTx OR y)\n]);\n```\n\nThough these examples looks more complex than simply parsing a textual formula, these constructors can be very useful to programmatically construct any arbitrary formula (how do you think the textual formulas are parsed:wink:).\n\n## Implemented Satisfiability Algorithms ##\n\nIn the basic form the satisfiability algorithms decide whether a propositional formula, in `CNF`, is satisfiable or not.\nThese algorithms are implemented in their separate classes, which has a common function `isSat` with following signature.\n\n```javascript\nisSat(cnf: CNF | string): boolean;\n```\n\n### Truth Table Algorithm ###\n\nTruth table is the most basic algorithm for satisfiability checking.\nIf there are `n` variables in the `CNF` then in worst case, this algorithm will try all 2\u003csup\u003en\u003c/sup\u003e binary combinations (truth assignments) for the formula.\nHowever, it returns true as soon as the first satisfying truth assignment is found.\n\nExample:\n\n```javascript\nimport { TruthTable } from \"pps2\";\n\n// unsatisfiable; returns false after trying all 8 truth assignments:\nTruthTable.isSat(\"x AND (NOTx OR y) AND (NOTy OR z) AND NOTz\");\n\n// tautology(always satisfiable); returns true after trying only 1 truth assignment:\nTruthTable.isSat(\"x OR NOTx\");\n```\n\nAdditionally, `TruthTable` can also return the satisfiable model for a given propositional formula in `CNF`.\nExample:\n\n```javascript\nTruthTable.getModel(\"x or notx\"); // [ Map { 'x' =\u003e false }, Map { 'x' =\u003e true } ]\n```\n\n### Independent Set Algorithm ###\n\nThe basic idea of independent set algorithm is to count the number of unsatisfying truth assignments.\nIf the count is 2\u003csup\u003en\u003c/sup\u003e for a formula with `n` variable then the formula is unsatisfiable.\n\nExample:\n\n```javascript\nimport { IndependentSet } from \"pps2\";\n\nIndependentSet.isSat(\"x AND (NOTx OR y) AND (NOTy OR z) AND NOTz\"); //false\n\nIndependentSet.isSat(\"x OR NOTx\"); //true\n```\n\n### 2-SAT ###\n\nThis algorithm first transforms every clause in CNF to implication form.\nForm the implication forms, it generates a directed graph, and concludes the formula to unsatisfiable if the graph contains a [strongly connected component (SCC)](https://en.wikipedia.org/wiki/Strongly_connected_component), with complimentary pair of literals in it.\n\n```javascript\nimport { TwoSAT } from \"pps2\";\n\n// use a string\nTwoSAT.isSat(\"x AND NOTx\"); //false\n\n//or use a CNF object\nTwoSAT.isSat(new CNF(...));\n```\n\n## Check satisfiability of `CNF` object directly ##\n\nTo make things semantically pleasing, `CNF` also exposes a `isSat` method with the help duck typing of SAT checkers (`SATChecker`).\nThis means that you can do following:\n\n```javascript\nconst cnf = new CNF([...]);\n\n// CNF#isSat signature: isSat(satChecker: SATChecker): boolean\n// so we need to pass the algorithm we want use:\n\ncnf.isSat(TruthTable);\n// OR\ncnf.isSat(IndependentSet);\n```\n\nNeat!\n\n## Check if \u0026#9082; \u0026#8872; \u0026#946; ##\n\nCheck if \u0026#9082; \u0026#8872; \u0026#946; (\u0026#9082; entails \u0026#946;); i.e. whenever \u0026#9082; is `true`, if \u0026#946; is `true` as well for those truth assignments or not.\n\n```javascript\nimport { IndependentSet, TruthTable, TwoSAT } from \"pps2\";\nconst alpha = CNF.parse(\"x\");\nconst beta = Clause.parse(\"x OR y\");\n\nIndependentSet.entails(alpha, beta); // true\nTruthTable.entails(alpha, beta); // true\nTwoSAT.entails(alpha, beta); // true\n```\n\n\u003e **Note:** \u0026#9082; \u0026#8872; \u0026#946; iff \u0026#9082; \u0026#8743; \u0026#172;\u0026#946; is not satisfiable. The `CNF` based algorithms such as `IndependentSet`, and `TwoSAT` leverage this fact. Therefore for these algorithms \u0026#9082; \u0026#8743; \u0026#172;\u0026#946; has to be a `CNF`. This puts the following restrictions for the said algorithms:\n\u003e * \u0026#9082; has to be a `CNF`, and\n\u003e * \u0026#946; can be one of the following:\n\u003e   * a `Literal`,\n\u003e   * a disjunctive `Clause`, or\n\u003e   * a `CNF` with only unit clauses.\n\n## Check if \u0026#9082; \u0026#8776; \u0026#946; ##\n\nCheck if \u0026#9082; \u0026#8776; \u0026#946; (\u0026#9082; is equivalent to \u0026#946;); i.e. for all truth assignments v, whether v(\u0026#9082;) == v(\u0026#946;).\n\n```javascript\nimport { TruthTable } from \"pps2\";\n\n// x, and NOTx should not be equivalent\nconst alpha = new CNF([new Clause([new Literal(\"x\")])]);\nconst beta  = new CNF([new Clause([new Literal(\"x\", true)])]);\n\nTruthTable.isEquivalent(alpha, beta); // false\n```\n\n## Check for minimal unsatisfiability (MU) ##\n\nA CNF formula is minimally unsatisfiable if and only if the following conditions hold.\n\n1. The CNF is unsatisfiable, and\n1. Every subsets of clauses that can be formed by excluding a clause every time, are satisfiable.\n\nTo check if a CNF is in MU or not you can use `MinimalUnsatisfiabilityChecker`.\n\nExample:\n\n```javascript\nimport { CNF, MinimalUnsatisfiabilityChecker } from \"pps2\";\n\nconst cnf = CNF.parse(\"(x) AND (NOTx) AND (y)\");\nMinimalUnsatisfiabilityChecker.isMinimallyUnsatisfiable(cnf); // false\n```\n\n## Convert a formula in NNF to (Q)CNF ##\n\nUse `PSGraph` to convert a formula in `NNF` to `CNF`, or more specifically `QCNF` (Quantified CNF; `read about` [quantified boolean formula](https://www-old.cs.uni-paderborn.de/fileadmin/Informatik/AG-Kleine-Buening/files/ss16/pps/qbf-slides1.pdf)).\nThis uses the Parallel-Serial graph algorithm.\nReferences:\n\n* [CNF Transformation by Parallel-Serial Graphs](https://www-old.cs.uni-paderborn.de/fileadmin/Informatik/AG-Kleine-Buening/files/ss11/pps/ps-transform-slides.pdf)\n* [Paper](http://www.ub-net.de/cms/fileadmin/upb/doc/bubeck-3cnf-transform-ipl-2009.pdf)\n\nExample: Converting \u0026#172;a \u0026#8743; ((b \u0026#8743; \u0026#172;c) \u0026#8744; (d \u0026#8743; e))\n\n```javascript\nimport { Connectives, Literal, NNF, PSGraph } from \"pps2\";\n\n// Construct the NNF\nconst NOTa = new Literal(\"a\", true);\nconst b_AND_NOTc = new NNF([new Literal(\"b\"), new Literal(\"c\", true)], Connectives.and);\nconst d_AND_e = new NNF([new Literal(\"d\"), new Literal(\"e\")], Connectives.and);\nconst nnf = new NNF([NOTa, new NNF([b_AND_NOTc, d_AND_e], Connectives.or)], Connectives.and);\n\n// Convert to QCNF.\nconst qcnf = PSGraph.convertNNFToCNF(nnf, \"z\");\nqcnf.toString(); // ∃z1: (¬a) ∧ (b ∨ z1) ∧ (¬c ∨ z1) ∧ (¬z1 ∨ d) ∧ (¬z1 ∨ e)\n```\n\nNote that `convertNNFToCNF` method optionally needs a second parameter, which is the prefix for the internal quantified variables created by the algorithm (refer the `toString` representation).\nIf no prefix is passed then the string `\"internal\"` is used for this purpose, which might not be that nice.\nHowever, if a prefix is used explicitly, then it can't be a variable or prefix of a variable in the input `nnf`.\n\nMore features will be added soon (hopefully :stuck_out_tongue:).\n\nHave fun :relaxed:","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsayan751%2Fpps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsayan751%2Fpps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsayan751%2Fpps/lists"}