https://github.com/james-langridge/csp-solver-playground
TypeScript implementation of a constraint satisfaction problem solver using backtracking search with MRV heuristic and AC-3 inference.
https://github.com/james-langridge/csp-solver-playground
constraint-satisfaction-problem csp-solver
Last synced: 10 months ago
JSON representation
TypeScript implementation of a constraint satisfaction problem solver using backtracking search with MRV heuristic and AC-3 inference.
- Host: GitHub
- URL: https://github.com/james-langridge/csp-solver-playground
- Owner: james-langridge
- Created: 2025-07-20T09:36:33.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-07-21T11:51:15.000Z (11 months ago)
- Last Synced: 2025-07-21T13:43:08.050Z (11 months ago)
- Topics: constraint-satisfaction-problem, csp-solver
- Language: TypeScript
- Homepage:
- Size: 46.9 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# CSP Solver Playground
> [!CAUTION]
> This is a playground implementation for experimentation and learning. Use with caution.
## Features
- **Immutable Data Structures**: Enables backtracking without manual state restoration
- **Search Heuristics**:
- MRV (Minimum Remaining Values) for variable selection
- Degree heuristic for tie-breaking
- Extensible value ordering framework
- **Constraint Propagation**: AC-3 (Arc Consistency) algorithm implementation
- **Constraint Types**: Unary, binary, and all-different constraints
- **TypeScript Types**: Type definitions for all public APIs
- **Built-in Problem Generators**: Classic CSP examples included (map coloring, N-Queens)
## Usage Example
```typescript
import { CSPBuilder, constraints, solveCSP } from 'csp-solver-ts';
// Create a simple map coloring problem
const csp = new CSPBuilder()
.addVariables(['WA', 'NT', 'SA'], ['red', 'green', 'blue'])
.addConstraint(constraints.differentValues('WA', 'NT'))
.addConstraint(constraints.differentValues('WA', 'SA'))
.addConstraint(constraints.differentValues('NT', 'SA'))
.build();
// Solve it
const result = solveCSP(csp);
if (result.success) {
console.log('Solution found:', result.assignment);
console.log('Statistics:', result.stats);
}
```
## Core Concepts
### CSP Definition
A Constraint Satisfaction Problem consists of:
- **Variables**: Entities that need values assigned
- **Domains**: Possible values for each variable
- **Constraints**: Restrictions on valid assignments
### Solver Algorithm
The solver uses backtracking search with:
1. **Variable Selection**: MRV (Minimum Remaining Values) heuristic
2. **Constraint Propagation**: AC-3 algorithm
3. **Search**: Depth-first search with backtracking
### Implementation
The codebase uses:
- Immutable data structures for CSP components
- Side-effect free functions for solver logic
- TypeScript for type checking
## API Reference
### Building CSPs
```typescript
const builder = new CSPBuilder()
.addVariable(variable, domain)
.addVariables(variables, sharedDomain)
.addConstraint(constraint)
.addAllDifferent(variables)
.addPairwiseConstraints(variables, constraintFactory)
.build();
```
### Constraint Factories
```typescript
// Binary constraints
constraints.differentValues(var1, var2) // var1 ≠ var2
constraints.equalTo(variable, value) // variable = value
// Global constraints
constraints.allDifferent([var1, var2, ...])
// Custom constraints
constraints.custom(
(assignment) => { /* return true if satisfied */ },
scope,
description
)
```
### Solving
```typescript
const result = solveCSP(csp);
if (result.success) {
// Access the solution
for (const [variable, value] of result.assignment) {
console.log(`${variable} = ${value}`);
}
// Performance metrics
console.log(`Nodes explored: ${result.stats.nodesExplored}`);
console.log(`Time: ${result.stats.timeMs}ms`);
}
```
## Examples
### Map Coloring
```typescript
import { problems, solveCSP } from 'csp-solver-ts';
const australia = problems.createAustraliaMapProblem();
const result = solveCSP(australia);
```
### N-Queens
```typescript
const queens = problems.createNQueensProblem(8);
const result = solveCSP(queens);
if (result.success) {
// Visualize the board
const board = Array(8).fill(null).map(() => Array(8).fill('.'));
for (const [row, col] of result.assignment) {
const r = parseInt(row.replace('row', ''));
const c = parseInt(col.replace('col', ''));
board[r][c] = 'Q';
}
console.log(board.map(row => row.join(' ')).join('\n'));
}
```
### Sudoku (Custom Implementation)
```typescript
const sudoku = new CSPBuilder();
// Add variables for each cell
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
sudoku.addVariable(`r${row}c${col}`, ['1','2','3','4','5','6','7','8','9']);
}
}
// Add row constraints
for (let row = 0; row < 9; row++) {
const rowVars = Array.from({length: 9}, (_, col) => `r${row}c${col}`);
sudoku.addAllDifferent(rowVars);
}
// Add column constraints...
// Add box constraints...
// Add given values...
const result = solveCSP(sudoku.build());
```
## Implementation Details
The solver uses several techniques to improve efficiency:
- **Immutable Data Structures**: Enables backtracking without manual state restoration
- **MRV Heuristic**: Reduces nodes explored by choosing most constrained variables first
- **AC-3 Algorithm**: Prunes search space through constraint propagation
- **Early Failure Detection**: Domain wipeout immediately triggers backtracking
Note: Performance characteristics will vary based on problem complexity and structure. The implementation prioritizes code clarity and correctness over raw performance.
## Debugging and Logging
The solver includes built-in logging to help understand algorithm behavior:
### Setup
1. Copy `.env.example` to `.env`:
```bash
cp .env.example .env
```
2. Edit `.env` to enable logging:
```
CSP_DEBUG=true
CSP_LOG_LEVEL=debug # or trace, info
```
### Running with Logging
```bash
# Development mode with hot reload
npm run dev:debug
# Compiled version
npm run example:debug
# Without logging (uses defaults)
npm run dev
npm run example
```
Log levels:
- **info**: High-level solver progress (start, solution found, stats)
- **debug**: Variable selection, backtracking, inference results
- **trace**: Detailed step-by-step execution, value assignments, arc processing
Example output with debug logging:
```
[INFO] Starting CSP solver { variables: 7, constraints: 9 }
[DEBUG] Variable WA has domain size 3
[DEBUG] Variable NT has domain size 3
[INFO] Beginning search
[DEBUG] MRV selected WA (domain size: 3, constraints: 2)
[DEBUG] Selected variable WA with domain size 3
[DEBUG] AC-3 starting with 2 arcs in queue after WA assignment
[DEBUG] AC-3 completed: processed 4 arcs
[DEBUG] Backtracking from WA = red
[INFO] Solution found! { timeMs: 12.5, nodesExplored: 7, inferencesApplied: 3 }
```
## Contributing
Possible areas for enhancement:
- Additional constraint types
- Value ordering heuristics (e.g., LCV)
- Alternative inference algorithms
- Additional problem examples
- Performance optimizations
## License
MIT