document code

This commit is contained in:
2025-09-24 16:14:15 +02:00
parent 4451ef60e1
commit 7de3bfc6cd
2 changed files with 33 additions and 8 deletions

View File

@@ -58,9 +58,16 @@ class CSP:
""" """
def revise(csp, xi, xj) -> bool: def revise(csp, xi, xj) -> bool:
"""Reduce the domain of xi if possible
Returns
-------
bool
Whether or not there was a domain reduction
"""
revised = False revised = False
for x in set(csp.domains[xi]): for x in set(csp.domains[xi]):
if not any( if not any( # translation of algorithm's forall expression.
[ [
(x, y) in csp.binary_constraints[(xi, xj)] (x, y) in csp.binary_constraints[(xi, xj)]
for y in csp.domains[xj] for y in csp.domains[xj]
@@ -97,39 +104,57 @@ class CSP:
A solution if any exists, otherwise None A solution if any exists, otherwise None
""" """
def backtrack(csp, assignment: dict[str, Any]) -> dict | None: def backtrack(csp, assignment: dict[str, Any]) -> dict[str, Any] | None:
"""The recursive engine of backtracking_search.
Returns
-------
dict[str, Any]
The solution to bubble up
None
If current branch has no solution
"""
# this is read from stdout in sudoku.py. important to 2c).
# yes, it couldv'e been done differently, but this is
# quick and unintrusive.
print("i have been called") print("i have been called")
if len(assignment) == len(csp.variables): if len(assignment) == len(csp.variables): # completion condition
return assignment # base-case return assignment # base-case
var = select_unassigned_variable(csp, assignment) var = select_unassigned_variable(csp, assignment)
for value in order_domain_values(csp, var, assignment): for value in order_domain_values(csp, var, assignment):
if not consistent(csp, var, value, assignment): if not consistent(csp, var, value, assignment):
continue continue # do nothing (skip iteration)
assignment[var] = value assignment[var] = value
if result := backtrack(csp, assignment): if result := backtrack(csp, assignment):
return result return result # return if not failure
assignment.pop(var) assignment.pop(var)
print("i have failed") print("i have failed")
return None # failure return None # failure
def consistent(csp, var, value, assignment) -> bool: def consistent(csp, var, value, assignment) -> bool:
"""Helper function to determine if an arc is consistent"""
for v in assignment: for v in assignment:
if (var, v) in csp.binary_constraints.keys(): if (var, v) in csp.binary_constraints.keys():
if (value, assignment[v]) not in csp.binary_constraints[(var, v)]: if (value, assignment[v]) not in csp.binary_constraints[(var, v)]:
return False return False
if (v, var) in csp.binary_constraints.keys(): if (v, var) in csp.binary_constraints.keys(): # bi-birectional
if (value, assignment[v]) not in csp.binary_constraints[(v, var)]: if (value, assignment[v]) not in csp.binary_constraints[(v, var)]:
return False return False
return True return True
def select_unassigned_variable(csp, assignment) -> str: def select_unassigned_variable(csp, assignment) -> str:
"""Helper function to find a variable that is yet to be assigned."""
for v in csp.variables: for v in csp.variables:
if v not in assignment.keys(): if v not in assignment.keys():
return v return v
return "this shouldn't happen" return "this shouldn't happen"
# choose least constrained value
def order_domain_values(csp, var, assignment) -> list[Any]: def order_domain_values(csp, var, assignment) -> list[Any]:
"""Helper function to order the domain values.
Orders on the least constrained value
"""
# calculate a sorting key by counting constraints
def compare(value) -> int: def compare(value) -> int:
s = 0 s = 0
for neighbor in [ for neighbor in [
@@ -145,7 +170,7 @@ class CSP:
return sorted(list(csp.domains[var]), key=compare) return sorted(list(csp.domains[var]), key=compare)
return backtrack(self, {}) return backtrack(self, {}) # start with no assignments
def alldiff(variables: list[str]) -> list[tuple[str, str]]: def alldiff(variables: list[str]) -> list[tuple[str, str]]:

Binary file not shown.