I implemented the Sosic and Gu fast N-Queens solver first in C++ and later in C#. The five screen shots below were created by latest C# application. None of my other algorithms can compete with this method.





I implemented the Sosic and Gu fast N-Queens solver first in C++ and later in C#. The five screen shots below were created by latest C# application. None of my other algorithms can compete with this method.





N-Queens Tests 8 Queens Microseconds 50 Samples Algorithm Minimum Average Maximum Std Dev Arc-Consistency 3 1846 4148 14220 2294 Arc-Consistency 4 3850 8987 27903 5022 Backjump 175 1057 3873 883 Backmark 198 737 3323 596 Backtracking 171 789 3132 652 Hill-Climber 1991 2097 2913 157 9 Queens Microseconds 50 Samples Algorithm Minimum Average Maximum Std Dev Arc-Consistency 3 2628 5785 15748 3202 Arc-Consistency 4 7492 18057 56587 11114 Backjump 208 1410 6184 1325 Backmark 214 866 4468 880 Backtracking 210 1269 6156 1186 Hill-Climber 1309 1398 1953 102 10 Queens Microseconds 50 Samples Algorithm Minimum Average Maximum Std Dev Arc-Consistency 3 3820 10680 30708 6963 Arc-Consistency 4 12624 46645 148221 31212 Backjump 248 3970 16736 3805 Backmark 283 1504 7613 1433 Backtracking 227 2857 12882 3022 Hill-Climber 24575 25608 33563 2037
My hill-climber results are pretty disappointing. I have gotten some decent runs of back-marking for n = 50 and n = 60 queens. I show the n = 60 queens experiment below.
==Menu==
**Instance Submenu**
1 Single Instance Test
2 Multiple Instances Test
3 Exit
Enter an option '1' to '3': 2
**Algorithm Submenu**
1 Arc-Consistency 3
2 Arc-Consistency 4
3 Backjump
4 Backmark
5 Chronological Bactracking
6 Evolutionary Hill-Climber
7 Exit
Enter an algorithm ('1' to '7'): 4
Enter the number of queens for option '2': 60
Enter the number of samples to be analyzed: 10
Minimum Runtime in Microseconds: 4819
Average Runtime in Microseconds: 10419330
Maximum Runtime in Micorseconds: 45439444
Standard Sample Deviation: 16665688
Notice the misspelling of microseconds.
Most of the six algorithms were developed back in the years 1999 to 2001 when I was a Master of Software Engineering and Doctoral candidate at Auburn University. Professor Gerry V. Dozier was my Master research advisor. The algorithms developed were in alphabetical order:
The first five algorithms were stated in pseudocode in the excellent treatise Foundations of Constraint Satisfaction by Edward Tsang. Below are six runs of my test C++ application (Win32 Console App) using 8 queens and 50 samples.






The Graph Coloring Problem and N-Queens Puzzle are both NP-Complete constraint satisfaction problems. There does not exist polynomial time algorithms to solve large instances of either problem. The Graph Coloring Problem is given a graph of n-vertices and m-edges find the minimum number of colors such that no two connected vertices are of the same color. The N-Queens Puzzle is given a n-by-n chessboard and n-queens place the queens such that no two queens are attacking one another. A queen in chess can move any number of squares diagonally, horizontally, or vertically.
As a Master of Software Engineering graduate student in the era 1998 to 2000, I majored in the subdiscipline of artificial intelligence known as constraint satisfaction. I developed evolutionary hill-climbing algorithms to solve constraint satisfaction problems. I specifically solved instances of the Graph Coloring Problem and the N-Queens Puzzle. I compared my algorithms with other researchers’ algorithms. One of the algorithms tested was Makato Yokoo’s Weak-Commitment Search Algorithm (WCSA). Yakoo wrote a very nice book named “Distributed Constraint Satisfaction” which has excellent flow-charts of several algorithms including the Min-Conflicts Search Algorithm (MCSA) and his WCSA. I implemented both algorithms in the C++ and Java computer languages.
I rewrote the preceding two algorithms in the C# computer language sometime in the epoch 2008 – 2009. Below are three instances of the Graph Coloring Problem with four, eight, and twelve vertices solved by the Yakoo’s WCSA.



Back in the year 1999 I studied Constraint Satisfaction Problems (CSPs) which is a branch of the computer science discipline artificial intelligence (AI). I took a course in Artificial Intelligence and then a Machine Learning course both under Professor Gerry V. Dozier at Auburn University in the Winter and Spring Quarters of 1999. Professor Dozier was my Master of Software Engineering degree advisor. The N-Queens Problem is a constraint satisfaction problem within the setting of a N-by-N chessboard with the queens arranged such the no queens are attacking any other queens. The N-Queens Problem is believed to be a NP-Complete Problem which means only non-deterministic polynomial time algorithms solve the problem. I bought copies of Foundations of Constraint Satisfaction by E. P. K. Tsang for Professor Dozier and me in 2000. The back-marking algorithm is found in section 5.4.3 page 147 of the textbook. I implemented several algorithms from the textbook. Below is the source code for the back-marking algorithm and single runs from N = 4 to N = 12. A single run is not a statistically significantly experiment. Generally, 30 or more experimental trials are needed for statistical significance.
/*
Author: James Pate Williams, Jr. (c) 2000 - 2023
Backmarking algorithm applied to the N-Queens CSP.
Algorithm from _Foundations of Constraint Satisfaction_
by E. P. K. Tsang section 5.4.3 page 147.
*/
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <vector>
#include <chrono>
using namespace std::chrono;
using namespace std;
// https://www.geeksforgeeks.org/measure-execution-time-function-cpp/
int constraintsViolated(vector<int>& Q) {
int a, b, c = 0, i, j, n;
n = Q.size();
for (i = 0; i < n; i++) {
a = Q[i];
for (j = 0; j < n; j++) {
b = Q[j];
if (i != j && a != -1 && b != -1) {
if (a == b) c++;
if (i - j == a - b || i - j == b - a) c++;
}
}
}
return c;
}
bool satisfies(int x, int v, int y, int vp) {
if (x == y) return false;
if (v == vp) return false;
if (x - y == v - vp || x - y == vp - v) return false;
return true;
}
bool Compatible(int x, int v, int* LowUnit, int* Ordering, int** Mark,
vector<int> compoundLabel) {
bool compat = true;
int vp, y = LowUnit[x];
while (Ordering[y] < Ordering[x] && compat) {
if (compoundLabel[y] != -1) {
vp = compoundLabel[y];
if (satisfies(x, v, y, vp))
y = Ordering[y] + 1;
else
compat = false;
}
}
Mark[x][v] = Ordering[y];
return compat;
}
bool BM1(int Level, int* LowUnit, int* Ordering, int** Mark,
vector<int> unlabelled, vector<int> compoundLabel, vector<int>& solution) {
bool result;
int i, v, x, y;
vector<int> Dx(compoundLabel.size());
if (unlabelled.empty()) {
for (i = 0; i < (int)compoundLabel.size(); i++)
solution[i] = compoundLabel[i];
return true;
}
for (i = 0; i < (int)unlabelled.size(); i++) {
x = unlabelled[i];
if (Ordering[x] == Level) break;
}
result = false;
for (i = 0; i < (int)compoundLabel.size(); i++)
Dx[i] = i;
do {
// pick a random value from domain of x
i = rand() % Dx.size();
v = Dx[i];
vector<int>::iterator vIterator = find(Dx.begin(), Dx.end(), v);
Dx.erase(vIterator);
if (Mark[x][v] >= LowUnit[x]) {
if (Compatible(x, v, LowUnit, Ordering, Mark, compoundLabel)) {
compoundLabel[x] = v;
vIterator = find(unlabelled.begin(), unlabelled.end(), x);
unlabelled.erase(vIterator);
result = BM1(Level + 1, LowUnit, Ordering, Mark,
unlabelled, compoundLabel, solution);
if (!result) {
compoundLabel[x] = -1;
unlabelled.push_back(x);
}
}
}
} while (!Dx.empty() && !result);
if (!result) {
LowUnit[x] = Level - 1;
for (i = 0; i < (int)unlabelled.size(); i++) {
y = unlabelled[i];
LowUnit[y] = LowUnit[y] < Level - 1 ? LowUnit[y] : Level - 1;
}
}
return result;
}
bool Backmark1(vector<int> unlabelled, vector<int> compoundLabel, vector<int>& solution) {
int i, n = compoundLabel.size(), v, x;
int* LowUnit = new int[n];
int* Ordering = new int[n];
int** Mark = new int* [n];
for (i = 0; i < n; i++)
Mark[i] = new int[n];
i = 0;
for (x = 0; x < n; x++) {
LowUnit[x] = 0;
for (v = 0; v < n; v++)
Mark[x][v] = 0;
Ordering[x] = i++;
}
return BM1(0, LowUnit, Ordering, Mark, unlabelled, compoundLabel, solution);
}
void printSolution(vector<int>& solution) {
char hyphen[256] = { '\0' };
int column, i, i4, n = solution.size(), row;
if (n <= 12) {
for (i = 0; i < n; i++) {
i4 = i * 4;
hyphen[i4 + 0] = '-';
hyphen[i4 + 1] = '-';
hyphen[i4 + 2] = '-';
hyphen[i4 + 3] = '-';
}
i4 = i * 4;
hyphen[i4 + 0] = '-';
hyphen[i4 + 1] = '\n';
hyphen[i4 + 2] = '\0';
for (row = 0; row < n; row++) {
column = solution[row];
cout << hyphen;
for (i = 0; i < column; i++)
cout << "| ";
cout << "| Q ";
for (i = column + 1; i < n; i++)
cout << "| ";
cout << '|' << endl;
}
cout << hyphen;
}
else
for (row = 0; row < n; row++)
cout << row << ' ' << solution[row] << endl;
}
int main(int argc, char* argv[]) {
while (true)
{
int i, n;
cout << "Number of queens (4 - 12) (0 to quit): ";
cin >> n;
if (n == 0)
break;
if (n < 4 || n > 12)
{
cout << "Illegal number of queens" << endl;
continue;
}
auto start = high_resolution_clock::now();
vector<int> compoundLabel(n, -1), solution(n, -1), unlabelled(n);
for (i = 0; i < n; i++)
unlabelled[i] = i;
if (Backmark1(unlabelled, compoundLabel, solution))
printSolution(solution);
else
cout << "problem has no solution" << endl;
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "Runtime: " << setprecision(3) << setw(5)
<< (double)duration.count() / 1.0e3 << " milliseconds" << endl;
}
return 0;
}








The 8-puzzle is a child’s tiled toy. The toy consists of 8 numbered tiles and a blank space. The object of the game is to get the tiles in the order 1 to 8 going from the top left hand corner for the number 1 tile around the perimeter clockwise and finish with the space in the center of the 3 x 3 board.
A* search is a complete and optimal informed or heuristic search algorithm. A good source for information on uniformed and informed search procedures is the tome “Artificial Intelligence A Modern Approach First and/or Second Edition” by Stuart Russell and Peter Norvig. The second edition has more info on the 8-puzzle and the 15-puzzle. Iterative deepening A* search is also a complete and optimal search algorithm. Below is an instance of the 8-puzzle that requires 10 steps to reach the goal state. I use a different goal state than Russell and Norvig in the second edition of their textbook.




I developed an application in 2015 that uses 5 search algorithms to solve instances of the 15-puzzle.









