code: def backtracking_search(csp,
                          select_unassigned_variable = first_unassigned_variable,
                          order_domain_values = unordered_domain_values,
                          inference = no_inference):
      
  
      def backtrack(assignment):
          if len(assignment) == len(csp.vars):
              return assignment
          var = select_unassigned_variable(assignment, csp)
          for value in order_domain_values(var, assignment, csp):
              if 0 == csp.nconflicts(var, value, assignment):
                  csp.assign(var, value, assignment)
                  removals = csp.suppose(var, value)
                  if inference(csp, var, value, assignment, removals):
                      result = backtrack(assignment)
                      if result is not None:
                          return result
                  csp.restore(removals)
          csp.unassign(var, assignment)
          return None
  
      result = backtrack({})
      assert result is None or csp.goal_test(result)
      return result
docs: [Fig. 6.5]
      >>> backtracking_search(australia) is not None
      True
      >>> backtracking_search(australia, select_unassigned_variable=mrv) is not None
      True
      >>> backtracking_search(australia, order_domain_values=lcv) is not None
      True
      >>> backtracking_search(australia, select_unassigned_variable=mrv, order_domain_values=lcv) is not None
      True
      >>> backtracking_search(australia, inference=forward_checking) is not None
      True
      >>> backtracking_search(australia, inference=mac) is not None
      True
      >>> backtracking_search(usa, select_unassigned_variable=mrv, order_domain_values=lcv, inference=mac) is not None
      True