{"id":18376207,"url":"https://github.com/bunji2/smtrun","last_synced_at":"2025-04-11T04:42:15.862Z","repository":{"id":95709998,"uuid":"247670224","full_name":"bunji2/smtrun","owner":"bunji2","description":"smtrun (described in Japanese)","archived":false,"fork":false,"pushed_at":"2020-03-17T11:50:44.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T04:42:12.009Z","etag":null,"topics":["front-end","go-z3","golang","smt","smt-solver","z3"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bunji2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-16T10:12:56.000Z","updated_at":"2020-03-17T11:50:46.000Z","dependencies_parsed_at":"2023-05-21T17:30:47.206Z","dependency_job_id":null,"html_url":"https://github.com/bunji2/smtrun","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunji2%2Fsmtrun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunji2%2Fsmtrun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunji2%2Fsmtrun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bunji2%2Fsmtrun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bunji2","download_url":"https://codeload.github.com/bunji2/smtrun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345281,"owners_count":21088242,"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":["front-end","go-z3","golang","smt","smt-solver","z3"],"created_at":"2024-11-06T00:22:15.014Z","updated_at":"2025-04-11T04:42:15.839Z","avatar_url":"https://github.com/bunji2.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# smtrun --- front-end of go-z3\n\ngo-z3 のフロントエンド言語 SMTL を実装してみた。実装の特徴として Golang の ast パッケージを利用してみた。\n\nなんで最初から Python を使わないのか？ Golang の AST を使ってみたかったから。\n\n## SMT とは\n\nSMT は \"Satisfiable Modulo Theories\" の略であり、充足可能性の判定を行う手法の一つである。\n特徴として、一階述語論理式を扱うことができる。このような充足可能性を判定するものを SMT Solver と呼ぶ。\n\nここでは SMT Solver として [go-z3](https://github.com/mitchellh/go-z3) を使用した。\n\n## 使い方\n\nまずは最初に使い方を見てもらったほうがわかりやすい。\n\n次のような条件式が与えられているときに、x と y を自動的に求めてみる。\n\n![](https://latex.codecogs.com/gif.latex?x\u0026plus;y=24\\wedge{x-y=2})\n\n\nSMTL では上を次のように記述する。\n\n```\npackage smtl\n\nfunc main() {\n\tvar x int\n\tvar y int\n\tassert(x+y == 24)\n\tassert(x-y == 2)\n}\n```\n\n上のテキストを \"foo.smtl\" というファイル名で保存しておく。\n\n実際に変数 x と y の解決は \"smtrun\" コマンドで求める。\n\n```\n% smtrun foo.smtl\nx = 13\ny = 11\n```\n\n## 数独の例\n\n3 x 3 の数独を解く例を示す。\n\n```\n4│□│□\n─┼─┼─\n□│□│7\n─┼─┼─\n□│□│□\n```\n\n条件は以下の通りである。\n\n* 各マス目には 1 〜 9 の異なる数字が入る。\n* 各マス目の縦・横・斜めの合計はいずれも 15 となる。\n\n```\n// sudoku.smtl\n// 3x3 の数独を解く例\n\npackage smtl\n\nfunc main() {\n  // 各マス目の並び\n\t// c00 c01 c02\n\t// c10 c11 c12\n\t// c20 c21 c22\n\n\tvar c00, c01, c02 int\n\tvar c10, c11, c12 int\n\tvar c20, c21, c22 int\n\n\t// 値の範囲\n\tassert(c00\u003e=1 \u0026\u0026 c00\u003c=9)\n\tassert(c01\u003e=1 \u0026\u0026 c01\u003c=9)\n\tassert(c02\u003e=1 \u0026\u0026 c02\u003c=9)\n\tassert(c10\u003e=1 \u0026\u0026 c10\u003c=9)\n\tassert(c11\u003e=1 \u0026\u0026 c11\u003c=9)\n\tassert(c12\u003e=1 \u0026\u0026 c12\u003c=9)\n\tassert(c20\u003e=1 \u0026\u0026 c20\u003c=9)\n\tassert(c21\u003e=1 \u0026\u0026 c21\u003c=9)\n\tassert(c22\u003e=1 \u0026\u0026 c22\u003c=9)\n\n\t// c00 〜 c22 は一意な値\n\tassert(distinct(c00, c01, c02, c10, c11, c12, c20, c21, c22))\n\n\t// 判明している値\n\tassert(c00 == 4)\n\tassert(c12 == 7)\n\n\t// 縦の合計=15\n\tassert(c00+c10+c20 == 15)\n\tassert(c01+c11+c21 == 15)\n\tassert(c02+c12+c22 == 15)\n\n\t// 横の合計=15\n\tassert(c00+c01+c02 == 15)\n\tassert(c10+c11+c12 == 15)\n\tassert(c20+c21+c22 == 15)\n\n\t// 斜めの合計=15\n\tassert(c00+c11+c22 == 15)\n\tassert(c02+c11+c20 == 15)\n\n}\n```\n\nsmtrun コマンドを実行すると次のようになる。\n\n```\n% smtrun sudoku.smtl \nc00 = 4\nc01 = 9\nc02 = 2\nc10 = 3\nc11 = 5\nc12 = 7\nc20 = 8\nc21 = 1\nc22 = 6\n```\n\n解答は次の通りである。\n\n```\n4│9│2\n─┼─┼─\n3│5│7\n─┼─┼─\n8│1│6\n```\n\n\n## SMTL について\n\nSMTL (SMT Language) の構文は Golang に類似するが、使用できる文や演算子が限定されている。\n\n例えば SMTL において、if 文、for 文、代入文などの多くのプログラミングで用意されている構文は存在しないし、二項演算子の \"/\" や文字列を扱うための構文もない。\n\nSMTL の BNF を以下に示す。\n\n```\nprogram\n  := package main_function\n\npackage\n  := \"package\" \"smtl\"\n\nmain_function\n  := \"func\" \"main\" \"(\" \")\" \"{\" statement_list \"}\"\n\nstatement_list\n  := statement\n  |  statement statement_list\n\nstatement\n  := \"var\" identifier type\n  |  assertion\n\nassertion\n  := \"assert\" \"(\" expression \")\"\n\nexpression\n  := \"distinct\" \"(\" identifier_list \")\"\n  |  expr\n\nexpr\n  := \"true\"\n  |  \"false\"\n  |  identifier\n  |  int_lit\n  |  expr binary_op expr\n  |  unary_op expr\n  |  expr \".\" \"implies\" \"(\" expr \")\"\n  |  expr \".\" \"iff\" \"(\" expr \")\"\n  |  \"(\" expr \")\"\n\nidentifier_list\n  := identifier\n\t|  identifier \",\" identifier_list\n\nbinary_op\n  := \"+\"\n  |  \"-\"\n  |  \"*\"\n  |  \"==\"\n  |  \"!=\"\n  |  \"\u003e\"\n  |  \"\u003c\"\n  |  \"\u003e=\"\n  |  \"\u003c=\"\n\nunary_op\n  := \"!\"\n\ntype\n  := \"int\"\n  |  \"bool\"\n\nDefinitions of identifier and int_lit are according to Golang syntax definition.\nRefer:\n  https://golang.org/ref/spec#Identifiers\n  https://golang.org/ref/spec#Integer_literals\n```\n\n## ビルド方法\n\n開発環境は arm の debian を使用したが、intel の linux でもほぼ同様と思われる。\n\n### go-z3 のビルド\n\n事前に gcc、g++、python、そして golang をインストールしておくこと。\n\n```\n% go get github.com/mitchellh/go-z3\n% cd $GOPATH/src/github.com/mitchellh/go-z3\n```\n\nmake の前に、少しソースの修正が必要となる。\nz3.go の cgo 宣言の行を vi などのエディタで次のように修正する。\n\n```\n修正前：\n// #cgo LDFLAGS: ${SRCDIR}/libz3.a -lstdc++\n\n修正後：\n// #cgo LDFLAGS: ${SRCDIR}/libz3.a -lstdc++ -lm\n```\n\nあとは go-z3 の手順通り make すればよい。\n\n```\n% make\n```\n\n\n詳細は [go-z3](https://github.com/mitchellh/go-z3) を参照のこと。\n\n\n### smtrun コマンドのビルド\n\n```\n% go get github.com/bunji2/smtrun\n% go build github.com/bunji2/smtrun\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunji2%2Fsmtrun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbunji2%2Fsmtrun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbunji2%2Fsmtrun/lists"}