void sudoku_check_if_valid_and_finished(struct SudokuPuzzle *puzzle) { assert(NULL != puzzle && "sudoku_check_if_valid_and_finished(): Bad input"); puzzle->m_isFinished = false; // Divide the test into two loops. // Motivation: the second test (for conflicts) takes more time and needs to // be performed only when all cells have been filled for (unsigned int i = 0; i < NROWS*NCOLS; ++i) { if (0 == puzzle->m_board[i].m_value) return; } for (unsigned int i = 0; i < NROWS*NCOLS; ++i) { if (has_conflict(puzzle, i, puzzle->m_board[i].m_value)) return; } puzzle->m_isFinished = true; }
void sudoku_generate_solution(struct SudokuPuzzle *puzzle) { assert(NULL != puzzle && "sudoku_generate_solution(): Bad input"); CandidateListType candidateList [NCOLS*NROWS]; for (unsigned int i = 0; i < NROWS*NCOLS; ++i) { BIT_REFILL_CANDIDATES(candidateList[i]); } // TODO add a fixed counter corresponding to the worst case scenario (we try // all possibilities for each cell) so that we have a hard iteration limit for (unsigned int i = 0; i < NROWS*NCOLS;) { bool found = false; // Try each candidate: if a candidate can be assigned to the cell // without causing a conflit, go to the next cell. // If no suitable candidate was found, then backtrack. while (!BIT_EMPTY(candidateList[i])) { const unsigned int num = get_random_number_from_candidate_list_and_remove_it(candidateList, i); if (!has_conflict(puzzle, i, num)) { puzzle->m_board[i].m_value = num; found = true; ++i; break; } } if (!found) { assert(i > 0 && "sudoku_generate_solution(): Trying to backtrack past 0"); BIT_REFILL_CANDIDATES(candidateList[i]); puzzle->m_board[i].m_value = 0; --i; } } }
/** * Verify option consistency. * * Make sure that the argument list passes our consistency tests. */ LOCAL bool is_consistent(tOptions * pOpts) { tOptDesc * pOD = pOpts->pOptDesc; int oCt = pOpts->presetOptCt; /* * FOR each of "oCt" options, ... */ for (;;) { /* * IF the current option was provided on the command line * THEN ensure that any "MUST" requirements are not * "DEFAULT" (unspecified) *AND* ensure that any * "CANT" options have not been SET or DEFINED. */ if (SELECTED_OPT(pOD)) { if (has_conflict(pOpts, pOD)) return false; } /* * IF this option is not equivalenced to another, * OR it is equivalenced to itself (is the equiv. root) * THEN we need to make sure it occurs often enough. */ if ( (pOD->optEquivIndex == NO_EQUIVALENT) || (pOD->optEquivIndex == pOD->optIndex) ) if (! occurs_enough(pOpts, pOD)) return false; if (--oCt <= 0) break; pOD++; } /* * IF we are stopping on errors, check to see if any remaining * arguments are required to be there or prohibited from being there. */ if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { /* * Check for prohibition */ if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) { if (pOpts->origArgCt > pOpts->curOptIdx) { fprintf(stderr, zNoArgs, pOpts->pzProgName); return false; } } /* * ELSE not prohibited, check for being required */ else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) { if (pOpts->origArgCt <= pOpts->curOptIdx) { fprintf(stderr, zargs_must, pOpts->pzProgName); return false; } } } return true; }
bool solve(cnf& c) { // Create all the helper data structures. assignment a(c); watched_literals w(c); glue_clauses g(c); vsids v(c); flexsize_clause p(c); int conflict_counter = 0; for (;;) { p.clear(); TRACE("main loop start\n"); ASSERT(c.sanity_check()); ASSERT(a.sanity_check()); ASSERT(w.sanity_check()); TRACE(a, "\n", c, "\n"); ASSERT(has_conflict(c, a) == end(c)); // We start out with BCP. This covers degenerate inputs, // and leads to a cleaner induction loop. // This means that upon backtracking, we have to promise that we've // already computed the units. cnf::clause_iterator conflict_clause = nullptr;// has_conflict(c, a); TRACE("BCP: start\n"); while (w.has_units()) { literal unit; cnf::clause_iterator reason; std::tie(unit, reason) = w.pop_unit(); TRACE("BCP: unit = ", unit, ", reason = ", reason, "\n"); if (clause_unsat(reason, a)) { TRACE("BCP: reason is conflict, breaking.\n"); conflict_clause = reason; w.clear_units(); break; } else { TRACE("BCP: pushing implicant ", unit, " -> ", reason, "\n"); ASSERT(unit == clause_implies(reason, a)); a.push_implicant(unit, reason); w.apply(a, unit); } } TRACE("BCP: done\n"); // If there's a conflict, we'll learn from that // and continue. if (conflict_clause) { if (a.curr_level() == -1) { return false; } // trace backwards to make p a UIP. p.adopt(conflict_clause); // a helper class with easier resolution. DBGSTMT(const int old_level = a.curr_level()); // backtrack until there's only one literal from our decision // level left. while (!has_uip(p, a)) { DBGSTMT(if (!a.curr_lit_is_implied()) { std::cout << p << std::endl << a << std::endl; }); ASSERT(a.curr_lit_is_implied()); // we have to resolve against our reasons if (p.contains(-a.curr_lit())) { auto unit = a.curr_lit(); auto reason = a.curr_reason(); p.resolve(reason, -unit); TRACE("Resolved p: ", p, "\n"); } a.pop_single_lit(); ASSERT(clause_unsat(p, a)); } // we better not have actually backtracked beyond our current level. ASSERT(a.curr_level() == old_level); literal uip = has_uip(p, a); TRACE("Found uip: ", uip, "\n"); TRACE("With clause: ", p, "\n"); ASSERT(uip != 0); uip = -uip; ASSERT(clause_unsat(p, a)); int clause_lbd = g.calculate_lbd(a, p); // At this point p is a clause that has a UIP. // We should first learn it, and then backtrack. // We must apply what we've learned to avoid infinite // looping (see useful lecture notes). // // Note that p is now a new unit clause, given a. // And that it's asserting the UIP. // That may induce more BCP. // However, something inconsistent would arise in the case // where *that* BCP would induce more conflict: if p is // asserting using only assignments from "much earlier" // decision levels, then if we imagine ourselves going back // in time where the CNF always had p, we would have backtracked // even then. // // The point is, in that second-order conflict case, the unit // propogation induced by the UIP isn't honestly associated // at the latest decision level. // // To head that off, we do the NCB so that we go back in time // just to when the learned clause P should have always // been there. // // Note: another weird case is that our decision variable // itself may be the UIP. // Nonetheless, the desired level is the max level of the learend // clause --without-- the UIP literal. // // What if the clause is unit? In that case the max level is // defined as 0. That actually seems somewhat well-defined. a.pop_level(); ASSERT(std::all_of(begin(c), end(c), [&](const auto cl) { return !clause_implies(cl, a) || size(cl) == 1; })); // There should be at least 1 unassigned literal in p, // and it should not somehow be made sat... ASSERT(!clause_unsat(p, a)); ASSERT(!clause_sat(p, a)); ASSERT(end(c) == has_conflict(c, a)); p.erase(uip); ASSERT(clause_unsat(p, a)); // Note that this is *inclusive", we want to keep all the assigned // literals in p. int max_level = a.max_literal_level(p); TRACE("NCB backtrack level: ", max_level, "\n"); // we can be = because we already popped a level. ASSERT(max_level <= a.curr_level()); while (a.curr_level() > max_level) { a.pop_level(); } // // now we've made a unit clause! p.insert(uip); ASSERT(uip == clause_implies(p, a)); // At this point we've cleared our watch literals, so // we better not have any more conflict or unit clauses... ASSERT(std::all_of(begin(c), end(c), [&](const auto cl) { return !clause_implies(cl, a) || size(cl) == 1; })); // We learn and apply. c.consider_resizing(); if (g.current_clause_count <= c.clauses_count) { int n = 0; auto m = g.generate_mapping(c, a, n); c.remap_clauses(m.get(), n); g.current_clause_count *= 1.3; } // Learn the clause! auto new_clause_ptr = c.insert_clause(p); g.lbd[new_clause_ptr] = clause_lbd; w.add_clause(new_clause_ptr, uip, a); ASSERT(uip == clause_implies(new_clause_ptr, a)); a.push_implicant(uip, new_clause_ptr); v.apply_clause(new_clause_ptr); w.apply(a, uip); conflict_counter++; } else {
static int merge_dirs (const char *root, char **dirs, int n_dirs) { DIR *dir; char *subdirs[n_dirs]; struct dirent *dirent; struct stat st; char *src_path; char *dest_path; int conflict; int i, j; for (i = 0; i < n_dirs; i++) { if (dirs[i] == NULL) continue; dir = opendir (dirs[i]); if (dir == NULL) continue; while ((dirent = readdir (dir)) != NULL) { src_path = strconcat (dirs[i], "/", dirent->d_name); if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0) continue; dest_path = strconcat (root, "/", dirent->d_name); if (lstat (dest_path, &st) == 0) { free (dest_path); continue; /* We already copyed this file */ } if (lstat (src_path, &st) < 0) { free (dest_path); continue; } if (S_ISCHR (st.st_mode) || S_ISBLK (st.st_mode) || S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)) { fprintf (stderr, "WARNING: ignoring special file %s\n", src_path); free (dest_path); continue; } conflict = has_conflict (dirs, n_dirs, dirent->d_name, i); if (conflict == NO_CONFLICTS) { bind_file (src_path, dest_path, &st); } else if (conflict == DIR_CONFLICT) { if (mkdir (dest_path, st.st_mode & 0777)) fatal_errno ("create merged dir"); if (lchown(dest_path, st.st_uid, st.st_gid) < 0) fatal_errno ("lchown"); for (j = 0; j < n_dirs; j++) subdirs[j] = get_subdir (dirs[j], dirent->d_name); merge_dirs (dest_path, subdirs, n_dirs); for (j = 0; j < n_dirs; j++) { if (subdirs[j]) free (subdirs[j]); } } else fatal ("Filename conflicts, refusing to mount\n"); free (dest_path); } } return 0; }