Constraint Satisfaction Engine in JavaScript
Constraint satisfaction problems (CSPs) are a powerful tool for solving a wide range of problems, from scheduling and resource allocation to puzzle solving and configuration management. This challenge asks you to build a basic constraint satisfaction engine in JavaScript. Your engine should be able to define variables, domains, and constraints, and then attempt to find a solution that satisfies all constraints.
Problem Description
You are tasked with creating a JavaScript class called CSP (Constraint Satisfaction Problem). This class should allow users to define a CSP with variables, their possible values (domains), and constraints between those variables. The engine should then be able to search for a solution that satisfies all constraints.
Key Requirements:
- Variable Definition: The
CSPclass should allow users to add variables to the problem. Each variable should have a name (string) and a domain (an array of possible values). - Constraint Definition: The
CSPclass should allow users to add constraints. A constraint is a function that takes an assignment (an object where keys are variable names and values are their assigned values) and returnstrueif the assignment satisfies the constraint, andfalseotherwise. - Solving: The
CSPclass should have asolve()method that attempts to find a solution to the problem. This method should return an assignment (an object) if a solution is found, ornullif no solution exists. - Backtracking Search: The
solve()method should implement a backtracking search algorithm to explore the search space.
Expected Behavior:
The solve() method should systematically explore possible assignments, assigning values to variables one at a time. If an assignment violates a constraint, the algorithm should backtrack and try a different value. If all possible assignments have been explored without finding a solution, the algorithm should return null.
Edge Cases to Consider:
- Empty Domain: A variable with an empty domain should immediately lead to a failure to find a solution.
- Inconsistent Constraints: The constraints might be inconsistent, meaning no solution exists. The engine should gracefully handle this and return
null. - No Variables: If no variables are added to the CSP, the
solve()method should return an empty object (representing an empty assignment). - Variable Already Assigned: The backtracking algorithm should handle the case where a variable has already been assigned a value.
Examples
Example 1:
Input:
variables: [{name: 'A', domain: [1, 2]}, {name: 'B', domain: [1, 2]}]
constraints: [(assignment => assignment.A !== assignment.B)]
Output:
{ A: 1, B: 2 } (or { A: 2, B: 1 })
Explanation:
The variables A and B can each be 1 or 2. The constraint requires that A and B have different values. A possible solution is A=1 and B=2.
Example 2:
Input:
variables: [{name: 'A', domain: [1, 2]}, {name: 'B', domain: [1, 2]}, {name: 'C', domain: [1, 2]}]
constraints: [
(assignment => assignment.A !== assignment.B),
(assignment => assignment.B !== assignment.C),
(assignment => assignment.A !== assignment.C)
]
Output:
{ A: 1, B: 2, C: 1 } (or other valid permutations)
Explanation:
This is a more complex constraint network. The constraints ensure that A, B, and C all have different values.
Example 3: (Inconsistent Constraints)
Input:
variables: [{name: 'A', domain: [1, 2]}, {name: 'B', domain: [1, 2]}]
constraints: [(assignment => assignment.A === assignment.B)]
Output:
null
Explanation:
The constraint requires A and B to have the same value. However, the domain of each variable only contains 1 and 2. This is an inconsistent constraint, and no solution exists.
Constraints
- Variable Names: Variable names must be unique strings.
- Domain Values: Domain values can be any JavaScript data type (numbers, strings, booleans, etc.).
- Constraint Function: The constraint function must accept a single argument (an assignment object) and return a boolean value.
- Performance: While optimal performance is not required for this challenge, the backtracking search should be reasonably efficient for problems with a small number of variables and constraints (e.g., up to 10 variables). Avoid infinite loops.
Notes
- The backtracking search algorithm is a common approach for solving CSPs. Consider using recursion to implement the search.
- The order in which variables are assigned can significantly impact the performance of the search. Consider using a heuristic (e.g., minimum remaining values) to choose the next variable to assign. (This is optional for this challenge, but a good consideration for future improvements).
- Focus on correctness and clarity of code. Good error handling is appreciated, but not strictly required.
- The assignment object returned by
solve()should only contain variables that have been assigned a value.