示例#1
0
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;
}
示例#2
0
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;
        }
    }
}
示例#3
0
文件: check.c 项目: sambuc/netbsd
/**
 *  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;
}
示例#4
0
文件: sat.cpp 项目: agorenst/sat
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 {
示例#5
0
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;
}