diff --git a/assignment2/csp.py b/assignment2/csp.py index c7c0d61..9dbd3be 100644 --- a/assignment2/csp.py +++ b/assignment2/csp.py @@ -58,9 +58,16 @@ class CSP: """ 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 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)] for y in csp.domains[xj] @@ -97,39 +104,57 @@ class CSP: 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") - if len(assignment) == len(csp.variables): + if len(assignment) == len(csp.variables): # completion condition return assignment # base-case var = select_unassigned_variable(csp, assignment) for value in order_domain_values(csp, var, assignment): if not consistent(csp, var, value, assignment): - continue + continue # do nothing (skip iteration) assignment[var] = value if result := backtrack(csp, assignment): - return result + return result # return if not failure assignment.pop(var) print("i have failed") return None # failure def consistent(csp, var, value, assignment) -> bool: + """Helper function to determine if an arc is consistent""" for v in assignment: if (var, v) in csp.binary_constraints.keys(): if (value, assignment[v]) not in csp.binary_constraints[(var, v)]: 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)]: return False return True def select_unassigned_variable(csp, assignment) -> str: + """Helper function to find a variable that is yet to be assigned.""" for v in csp.variables: if v not in assignment.keys(): return v return "this shouldn't happen" - # choose least constrained value 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: s = 0 for neighbor in [ @@ -145,7 +170,7 @@ class CSP: 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]]: diff --git a/assignment2/delivery.pdf b/assignment2/delivery.pdf index 92ac6f8..8394388 100644 Binary files a/assignment2/delivery.pdf and b/assignment2/delivery.pdf differ