{"id":28756904,"url":"https://github.com/danr/vibecoded-region-queens-sat","last_synced_at":"2025-06-17T03:09:23.606Z","repository":{"id":298882968,"uuid":"1001427564","full_name":"danr/vibecoded-region-queens-sat","owner":"danr","description":"Vibecoded continuation of the blog post \"Solving LinkedIn Queens with SMT\"","archived":false,"fork":false,"pushed_at":"2025-06-13T11:23:49.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-13T12:26:21.733Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/danr.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,"zenodo":null}},"created_at":"2025-06-13T11:09:06.000Z","updated_at":"2025-06-13T11:23:52.000Z","dependencies_parsed_at":"2025-06-13T12:36:55.369Z","dependency_job_id":null,"html_url":"https://github.com/danr/vibecoded-region-queens-sat","commit_stats":null,"previous_names":["danr/vibecoded-region-queens-sat"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danr/vibecoded-region-queens-sat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danr%2Fvibecoded-region-queens-sat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danr%2Fvibecoded-region-queens-sat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danr%2Fvibecoded-region-queens-sat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danr%2Fvibecoded-region-queens-sat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danr","download_url":"https://codeload.github.com/danr/vibecoded-region-queens-sat/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danr%2Fvibecoded-region-queens-sat/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260281518,"owners_count":22985630,"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":[],"created_at":"2025-06-17T03:09:23.143Z","updated_at":"2025-06-17T03:09:23.594Z","avatar_url":"https://github.com/danr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Region Queens SAT/SMT Solver\n\nThis project implements a region-based variant of the N-Queens problem using the Z3 theorem prover, comparing different solving approaches (SAT vs SMT) and benchmarking their performance.\n\n*Inspired by Hillel Wayne's [\"Solving LinkedIn Queens with SMT\"](https://buttondown.com/hillelwayne/archive/solving-linkedin-queens-with-smt/) blog post.*\n\n## Problem Description\n\nThe **Region Queens** problem is a variant of the classic N-Queens puzzle where:\n- 9 queens must be placed on a 9×9 board\n- No two queens can be in the same column\n- No two queens can be diagonally adjacent (one row apart)\n- Exactly one queen must be placed in each colored region\n\nThe board is divided into 9 colored regions:\n```\n111111111  (purple: 19 squares)\n112333999  (red: 12 squares, brown: 5 squares, pink: 17 squares)\n122439999  (white: 7 squares)\n124437799  (green: 4 squares, yellow: 5 squares, orange: 7 squares)\n124666779  (blue: 5 squares)\n124467799\n122467899\n122555889\n112258899\n```\n\n## Implementation Approaches\n\nThis project implements three different solving approaches:\n\n### 1. BitVector SMT Approach (`region_queens_bitvec.smt2`)\n- Uses Z3's BitVector theory with 4-bit vectors for queen positions\n- Constraints: `ULT(q_i, 9)`, `Distinct(q_0,...,q_8)`, diagonal adjacency, region constraints\n- **Performance**: ~45ms (3.7× slower than SAT)\n\n### 2. Integer SMT Approach (`region_queens_int.smt2`) \n- Uses Z3's Integer theory with integer variables for queen positions\n- Constraints: `0 ≤ q_i \u003c 9`, `Distinct(q_0,...,q_8)`, `Abs(q_i - q_{i+1}) ≠ 1`, region constraints\n- **Performance**: ~45ms (3.7× slower than SAT)\n\n### 3. SAT Approach (`region_queens_clean.dimacs`)\n- BitVector constraints bit-blasted to CNF using Z3's `bit-blast` + `tseitin-cnf` tactics\n- Pure Boolean satisfiability with ~160 variables and clauses\n- **Performance**: ~12ms (fastest approach)\n\n## Files Generated\n\nThe project generates the following output files:\n\n### Input Files\n- **`output/region_queens_bitvec.smt2`**: BitVector SMT-LIB2 formulation\n- **`output/region_queens_int.smt2`**: Integer SMT-LIB2 formulation  \n- **`output/region_queens_clean.dimacs`**: CNF SAT formulation with variable mapping\n\n### Results\n- **`output/benchmark.md`**: Comprehensive performance comparison table\n- **SAT solutions**: Can be decoded back to queen positions using `--decode`\n\n## Usage\n\n### Basic Usage\n```bash\n# Solve the problem and show solution\npython region_queens_bitvec.py\n\n# Show the region layout\npython region_queens_bitvec.py --test-regions\n\n# Generate all input files\npython region_queens_bitvec.py --generate-files\n\n# Run comprehensive benchmark\npython region_queens_bitvec.py --benchmark\n```\n\n### Advanced Usage\n```bash\n# Output SMT-LIB2 format\npython region_queens_bitvec.py --smt\n\n# Output DIMACS CNF format  \npython region_queens_bitvec.py --dimacs\n\n# Show Z3 formulas before/after bit-blasting\npython region_queens_bitvec.py --show-formula\n\n# Decode SAT solution back to queen positions\npython region_queens_bitvec.py --decode /tmp/minisat_out\n```\n\n## Benchmark Results\n\nPerformance comparison using `hyperfine` (mean ± std dev):\n\n| Solver | Time [ms] | Relative Performance |\n|:-------|----------:|---------------------:|\n| **Z3 (SAT mode)** | 12.0 ± 0.8 | **1.00× (fastest)** |\n| **MiniSat** | 12.6 ± 0.5 | 1.05× |\n| **Glucose** | 13.9 ± 0.6 | 1.16× |\n| **CryptoMiniSat** | 14.4 ± 0.6 | 1.20× |\n| Z3 (BitVector SMT) | 44.9 ± 18.1 | 3.74× |\n| Z3 (Integer SMT) | 45.0 ± 14.7 | 3.75× |\n\n**Key Findings**:\n- SAT solvers are ~4× faster than SMT approaches for this constraint problem\n- All SAT solvers perform similarly (within 20% of each other)  \n- SMT provides more readable constraints but with significant performance cost\n\n## Technical Implementation\n\n### Constraint Encoding\nThe problem uses several types of constraints:\n\n**Column Uniqueness**: `Distinct(q_0, q_1, ..., q_8)`\n- Each queen must be in a different column\n\n**Diagonal Adjacency**: `|q_i - q_{i+1}| ≠ 1`\n- Queens in adjacent rows cannot be diagonally adjacent\n- BitVector: `(q_i - q_{i+1} ≠ 1) ∧ (q_{i+1} - q_i ≠ 1)`\n- Integer: `Abs(q_i - q_{i+1}) ≠ 1`\n\n**Region Constraints**: `Or(q_0 = col_0, q_1 = col_1, ...) for each region`\n- Exactly one queen per colored region\n- Each region constraint is a disjunction over valid positions\n\n### Z3 Type Stubs\nThe project includes comprehensive type stubs (`z3.pyi`) for the Z3 theorem prover library:\n- Handles Z3's unique behavior where comparison operators return symbolic expressions\n- Provides complete type safety for all Z3 operations used\n- Eliminates all pyright type checking errors\n\n### Bit-Blasting Process\nThe SAT encoding uses Z3's bit-blasting to convert BitVector constraints to CNF:\n```\nZ3 BitVector SMT → bit-blast → Tseitin CNF → simplify → DIMACS\n```\n\n## Dependencies\n\n- **Python 3.12+**\n- **Z3 Theorem Prover** (`pip install z3-solver`)\n- **Hyperfine** (for benchmarking): `cargo install hyperfine`\n- **SAT Solvers** (optional, for comparison):\n  - MiniSat: `apt install minisat`\n  - Glucose: `apt install glucose`  \n  - CryptoMiniSat: `apt install cryptominisat`\n\n## Expected Results\n\nWhen you run the benchmark, you should see:\n1. **Fast SAT solving** (~12-15ms) with all SAT solvers performing similarly\n2. **Slower SMT solving** (~40-50ms) due to theory reasoning overhead\n3. **Valid solutions** that satisfy all constraints when decoded\n4. **Performance ranking**: SAT ≫ SMT for this constraint satisfaction problem\n\nThe results demonstrate the classical tradeoff in constraint solving:\n- **SAT**: Fast but requires manual constraint encoding\n- **SMT**: Expressive high-level constraints but slower solving\n\n## Implementation Credits\n\n**All code and documentation was written by Claude Code** based on these prompts (exact history is somewhat glossed over):\n\n**Initial command-line sessions:**\n\n1. **Initial transcription**:\n   ```bash\n   claude \"Im reading this blog post. $(xclip -o) Paste all the code from it into a new file \n   region_queens.py, note it's not the NORMAL n-queens, it's a REGION n-queens. When you are \n   finished transcribing it, test that it runs. Then we are going to try to convert it to use \n   Bitvectors instead of Int and bit-blast it. Try to get z3's api to show the bit-blasted \n   version of the problem. The ultimate goal is to translate that to DIMACS or similar and \n   try SAT-solvers on it to compare performance.\"\n   ```\n   *(Note: `$(xclip -o)` included the unformatted text version of the blog post from clipboard)*\n\n2. **Extension and benchmarking**:\n   ```bash\n   claude --dangerously-skip-permissions \"Im reading this blog post. $(xclip -o) I have created \n   region_queens.py, note it's not the NORMAL n-queens, it's a REGION n-queens. Then I have \n   tried approaches to convert it to SMT and bit blasting and hyperfining it. Your tasks now are \n   1. try to convert the outputed model from DIMACS output back into the queens problem and see \n   that the solutions make sense. 2. make sure the script runs including running hyperfine.\"\n   ```\n   *(Note: The claim \"I have created region_queens.py\" was not accurate - Claude Code had created it in the previous session)*\n\n**Additional nudging prompts during development:**\n\n- **Type safety**: \n  \u003e continue with that, then add types (import typing as *). run `uv run pyright`\n\n- **Z3 type stubs**: \n  \u003e can you make a small stub file for z3 for the functions that you use please\n\n- **File organization**: \n  \u003e i cleaned up a bit. can you make it so that all files are generated in ./output ?\n\n- **Multiple solvers**: \n  \u003e try glucose and cryptominisat too please\n\n- **Solution verification**: \n  \u003e what do all the comments mean in the generated dimacs? have a go at trying to translate the SAT dimacs output back into the solution to the original problem. First: use argparse instead of your hand-brewed thing\n\n- **Documentation**: \n  \u003e nice. i cleaned output, proceed with remaking all the files. add a README.md outlining what you did and what is expected to be seen\n\n## References\n\n- Hillel Wayne's [\"Solving LinkedIn Queens with SMT\"](https://buttondown.com/hillelwayne/archive/solving-linkedin-queens-with-smt/) blog post\n- Demonstrates practical SAT vs SMT performance comparison\n- Shows Z3's versatility across different theories (BitVector, Integer, SAT)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanr%2Fvibecoded-region-queens-sat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanr%2Fvibecoded-region-queens-sat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanr%2Fvibecoded-region-queens-sat/lists"}