{"id":33973048,"url":"https://github.com/d3lph1/boollet","last_synced_at":"2026-03-17T22:05:24.860Z","repository":{"id":56961092,"uuid":"465150977","full_name":"D3lph1/Boollet","owner":"D3lph1","description":"Boolean algebra toolkit for PHP","archived":false,"fork":false,"pushed_at":"2022-03-12T12:19:28.000Z","size":126,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-27T18:50:12.254Z","etag":null,"topics":["boolean-algebra","normal-forms","sat","sat-solver","truth-table","zhegalkin-polynomial"],"latest_commit_sha":null,"homepage":"","language":"PHP","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/D3lph1.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":"2022-03-02T04:04:29.000Z","updated_at":"2025-01-03T01:26:25.000Z","dependencies_parsed_at":"2022-08-21T05:40:17.743Z","dependency_job_id":null,"html_url":"https://github.com/D3lph1/Boollet","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/D3lph1/Boollet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D3lph1%2FBoollet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D3lph1%2FBoollet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D3lph1%2FBoollet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D3lph1%2FBoollet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/D3lph1","download_url":"https://codeload.github.com/D3lph1/Boollet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D3lph1%2FBoollet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27697367,"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","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["boolean-algebra","normal-forms","sat","sat-solver","truth-table","zhegalkin-polynomial"],"created_at":"2025-12-13T01:00:41.984Z","updated_at":"2025-12-13T01:01:32.860Z","avatar_url":"https://github.com/D3lph1.png","language":"PHP","readme":"\u003cdiv align=\"center\"\u003e\n    \u003cimg width=\"250\" height=\"250\" src=\"logo.png\"\u003e\n\u003c/div\u003e\n\n# Boollet\n\nBoollet is a boolean algebra toolkit for PHP.\n\n[![PHP Version Require](http://poser.pugx.org/d3lph1/boollet/require/php)](https://packagist.org/packages/d3lph1/boollet)\n[![License](http://poser.pugx.org/d3lph1/boollet/license)](https://packagist.org/packages/d3lph1/boollet)\n\n## Features\n\n- [x] [Expression object API](#value-binding)\n- [x] [Expression parser](#expression-parser)\n- [x] [Building truth tables](#building-truth-table)\n- [x] [Complete conjunctive/disjunctive normal form calculation](#complete-conjunctivedisjunctive-normal-form-calculation)\n- [x] [Zhegalkin Polynomial calculation](#zhegalkin-polynomial-calculation)\n- [x] [SAT and UNSAT solvers](#sat-and-unsat-solvers)\n\n## Requirements\n\n* PHP \u003e= 8.1\n\n## Installation\n\n```bash\ncomposer require d3lph1/boollet\n```\n\n## Usage\n### Expression object API\n\nYou can create either `UnaryExpression` or `BinaryExpression` with one or two operands respectively:\n\n```php\nuse D3lph1\\Boollet\\Structure\\Expression\\{Variable, UnaryExpression, BinaryExpression};\nuse D3lph1\\Boollet\\Structure\\Operator\\{UnaryOperators, BinaryOperators};\n\n$expr = new BinaryExpression(\n    new UnaryExpression(UnaryOperators::NOT, new Variable(false)),\n    BinaryOperators::AND,\n    new BinaryExpression(new Variable(true), BinaryOperators::OR, new Variable(false, label: 'Z'))\n);\n\necho $expr; // (!A ⋀ (B ⋁ Z))\n```\n\n\u003e If there is no label for variable specified, it will be assigned with sequentially autogenerated symbols. \n\nEvaluate the expression with initial variable values:\n\n```php\n$val = $expr-\u003eevaluate(); // true\n```\n\nEvaluate the expression with overwritten variable values (It can be partially overwritten): \n\n```php\n$val = $expr-\u003eevaluate(['A' =\u003e true, 'B' =\u003e true, 'Z' =\u003e true]) // false\n```\n\n### Value binding\n\nIn the example above there are only static variable values which could not be changed dynamically without expression reconstructing.\n\nTo change value of variable at runtime you should use `Variable::set()` method. For convenient batch value setup there is `ValueBinder` class:\n\n```php\nuse D3lph1\\Boollet\\ValueBinder;\n\n$a = new Variable(false);\n$b = new Variable(true);\n$z = new Variable(false, label: 'Z');\n\n$expr = new BinaryExpression(\n    new UnaryExpression(UnaryOperators::NOT, $a),\n    BinaryOperators::AND,\n    new BinaryExpression($b, BinaryOperators::OR, $z)\n);\n\n$binder = new ValueBinder();\n$binder-\u003ebind($a);\n$binder-\u003ebindAll([$b, $z]);\n\n$binder-\u003eset([\n    'A' =\u003e true,\n    'B' =\u003e true,\n    'Z' =\u003e true\n])\n\n$expr-\u003eevaluate(); // true\n```\n\n### Expression parser\n\nFor parsing stringed expressions uses `ShuntingYardParser` parser implementation. Under the hood it uses Dijkstra's algorithm of the same name.\n\n```php\nuse D3lph1\\Boollet\\Parser\\{Lexer, Reader\\StringInputReader, ShuntingYardParser};\n\n$lexer = Lexer::default();\n$input = new StringInputReader('X ⊕ Y → (X ⋀ Z)');\n$parser = new ShuntingYardParser($lexer);\n\n$expr = $parser-\u003eparse($input);\n\necho $expr; // ((X ⊕ Y) → (X ⋀ Z))\n```\n\n### Building truth table\n\n```php\nuse D3lph1\\Boollet\\TruthTable;\n\n$table = TruthTable::tabulate($expr);\n$table-\u003esetLabel('f(X ⊕ Y → (X ⋀ Z))');\n\necho $table;\n```\n\n```\n+---+---+---+--------------------+\n| X | Y | Z | f(X ⊕ Y → (X ⋀ Z)) |\n+---+---+---+--------------------+\n| 0 | 0 | 0 |                  1 |\n| 0 | 0 | 0 |                  1 |\n| 0 | 1 | 0 |                  0 |\n| 0 | 1 | 0 |                  0 |\n| 1 | 0 | 0 |                  0 |\n| 1 | 0 | 0 |                  1 |\n| 1 | 1 | 0 |                  1 |\n| 1 | 1 | 0 |                  1 |\n+---+---+---+--------------------+\n```\n\n### Complete conjunctive/disjunctive normal form calculation\n\nClass `NormalForms` provides utility methods to find complete conjunctive (or disjunctive ) normal form representations.\n\n```php\nuse D3lph1\\Boollet\\NormalForm\\NormalForms;\n\n// $expr ~ ((X ⊕ Y) → (X ⋀ Z))\n\n$ccnf = NormalForms::calculateCompleteConjunctive($expr); // ((X ⋁ (!Y ⋁ Z)) ⋀ ((X ⋁ (!Y ⋁ !Z)) ⋀ (!X ⋁ (Y ⋁ Z))))\n$cdnf = NormalForms::calculateCompleteDisjunctive($expr); // ((!X ⋀ (!Y ⋀ !Z)) ⋁ ((!X ⋀ (!Y ⋀ Z)) ⋁ ((X ⋀ (!Y ⋀ Z)) ⋁ ((X ⋀ (Y ⋀ !Z)) ⋁ (X ⋀ (Y ⋀ Z))))))\n```\n\n### Zhegalkin Polynomial calculation\n\nFor such needs you can use `ZhegalkinPolynomial` utility class:\n\n```php\nuse \\D3lph1\\Boollet\\ZhegalkinPolynomial;\n\n// $expr ~ (!X → ((!Y ⊕ X) ⋀ !Z))\n\n$polynomial = ZhegalkinPolynomial::calculate($expr);\n\necho $polynomial; // ((Z ⋀ (Y ⋀ X)) ⊕ ((Y ⋀ X) ⊕ ((Z ⋀ X) ⊕ ((Z ⋀ Y) ⊕ (Y ⊕ (Z ⊕ 1))))))\n```\n\n### SAT and UNSAT solvers\n\nBoollet provides naive algorithm implementations to solve [boolean (un)satisfiability problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem).\n\n\n \u003e SAT is the problem of determining if there exists an interpretation that satisfies a given boolean formula (formula becomes `true`).\n\n \u003e UNSAT is the problem of determining if there exists an interpretation that not satisfies a given boolean formula (formula becomes `false`). \n\n`CompleteDisjunctiveNormalFormSATSolver` works only with expressions in complete disjunctive normal form. Whereas `CompleteConjunctiveNormalFormUNSATSolver` uses only expressions in complete conjunctive normal form.\n\nThe second argument of the method `findAllPossibleSolutions()` takes an array of variables with respect to which it is required to solve the problem.\nOther variables whose labels are not passed to this argument must have values (in the example below `y` is such variable).\n\n```php\nuse \\D3lph1\\Boollet\\SAT\\CompleteDisjunctiveNormalFormSATSolver;\n// $expr ~ X ⋁ (Y ⋀ Z)\n\n$y-\u003eset(false);\n\n$cdnf = NormalForms::calculateCompleteDisjunctive($expr);\n\n$sat = new CompleteDisjunctiveNormalFormSATSolver();\n$solutions = $sat-\u003efindAllPossibleSolutions($cdnf, ['X', 'Z']);\n$solutions = $sat-\u003efindAllPossibleSolutions($cdnf, ['X', 'Z']);\n```\n\n`$solutions` will look like this:\n\n```php\n^ array:2 [▼\n  0 =\u003e array:2 [▼\n    \"X\" =\u003e true\n    \"Z\" =\u003e false\n  ]\n  1 =\u003e array:2 [▼\n    \"X\" =\u003e true\n    \"Z\" =\u003e true\n  ]\n]\n```\n\nTo conveniently define results constraints, you can use `findAllPossibleSolutionsWithConstraints()`:\n\n```php\nuse D3lph1\\Boollet\\Constraints\\Constraints;\n\n$solutions = $sat-\u003efindAllPossibleSolutionsWithConstraints($cdnf, ['X', 'Z'], new class() implements Constraints {\n    public function isSatisfy(array $values): bool\n    {\n        return $values['X'];\n    }\n});\n```\n\n`$solutions` will look like this:\n\n```php\n^ array:1 [▼\n  0 =\u003e array:2 [▼\n    \"X\" =\u003e true\n    \"Z\" =\u003e false\n  ]\n]\n```\n\n## License\n\nThis code is published under the [MIT license](https://opensource.org/licenses/MIT). This means you can do almost anything with it, as long as the copyright notice and the accompanying license file is left intact.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd3lph1%2Fboollet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd3lph1%2Fboollet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd3lph1%2Fboollet/lists"}