Rudy’s OBTF Rudolf Adamkovič

Home / Computer science / N-queens / Solve with home-grown SAT solver


Constraints: Orthogonal threats

Enforce at most one queen in every row and column,

\begin{equation*} \forall (1 \leq i \leq n) \quad \sum_{j = 1}^{n} x_{ij} \leq 1, \end{equation*}

transformed to the conjunctive normal form as

\begin{align*} \forall (i, j) \> \forall (j' > j) \quad & (\lnot x_{ij} \lor \lnot x_{ij'}) \\ \forall (i, j) \> \forall (i' > i) \quad & (\lnot x_{ij} \lor \lnot x_{i'j}). \end{align*}
(defun my-queens-at-most-one-per-row-clauses (size &optional transpose)
  "Return CNF clauses enforcing at most one queen per row.

Implements constraints for SIZE-queens puzzle.  With non-nil TRANSPOSE,
enforce at most one queen per column, instead of row.

The result is a list of lists containing literals, non-zero integers
representing variables, possibly negated.  All returned clauses and
literals are sorted for testability and reproducibility."
  (let ((variables (my-queens-variables size transpose)))
    (sort (mapcan (pcase-lambda (`(,variable ,row ,column))
                    (mapcan (pcase-lambda (`(,variable* ,row* ,column*))
                              (if (and (= row* row)
                                       (> column* column))
                                  (list (list (- variable*)
                                              (- variable)))))
                            variables))
                  variables))))
(ert-deftest my-queens-at-most-one-per-row-clauses/size-2 ()
  (should (equal (my-queens-at-most-one-per-row-clauses 2)
                 '((-4 -3) (-2 -1)))))

(ert-deftest my-queens-at-most-one-per-row-clauses/size-2/transpose ()
  (should (equal (my-queens-at-most-one-per-row-clauses 2 t)
                 '((-4 -2) (-3 -1)))))

(ert-deftest my-queens-at-most-one-per-row-clauses/size-3 ()
  (should (equal (my-queens-at-most-one-per-row-clauses 3)
                 '((-9 -8)
                   (-9 -7)
                   (-8 -7)
                   (-6 -5)
                   (-6 -4)
                   (-5 -4)
                   (-3 -2)
                   (-3 -1)
                   (-2 -1)))))

(ert-deftest my-queens-at-most-one-per-row-clauses/size-3/transpose ()
  (should (equal (my-queens-at-most-one-per-row-clauses 3 t)
                 '((-9 -6)
                   (-9 -3)
                   (-8 -5)
                   (-8 -2)
                   (-7 -4)
                   (-7 -1)
                   (-6 -3)
                   (-5 -2)
                   (-4 -1)))))

(ert-deftest my-queens-at-most-one-per-row-clauses/size-4 ()
  (should (equal (my-queens-at-most-one-per-row-clauses 4)
                 '((-16 -15)
                   (-16 -14)
                   (-16 -13)
                   (-15 -14)
                   (-15 -13)
                   (-14 -13)
                   (-12 -11)
                   (-12 -10)
                   (-12 -9)
                   (-11 -10)
                   (-11 -9)
                   (-10 -9)
                   (-8 -7)
                   (-8 -6)
                   (-8 -5)
                   (-7 -6)
                   (-7 -5)
                   (-6 -5)
                   (-4 -3)
                   (-4 -2)
                   (-4 -1)
                   (-3 -2)
                   (-3 -1)
                   (-2 -1)))))

© 2025 Rudolf Adamkovič under GNU General Public License version 3.
Made with Emacs and secret alien technologies of yesteryear.