📄 search.txt
字号:
/************************************************************************
* *
* AN EXPERIMENTAL TABU SEARCH CODE FOR THE N-QUEENS PROBLEM *
* *
* Copyright (C) 1992 by Manuel Laguna *
* *
* Last revision: May 4, 1992. Version: 1.1 *
* *
* TSQUEEN.C : <n> number of queens *
* <tabu_size> size of the tabu list *
* <max_iter> maximum number of iterations *
* <seed> seed for the random number generator *
* *
************************************************************************/
#include <stdio.h>
#define TRACE 1 /* set = 1 to display information every iteration */
#define ZERO 0 /* set = 1 to disallow zero moves */
#define FIS 0 /* set = 1 to implement first-improving strategy */
#define MAX(X,Y) ( (X) > (Y) ? (X) : (Y) )
struct move_info {
int i;
int j;
int value;
};
/************************************************************************
* *
* FUNCTION PROTOTYPES *
* *
************************************************************************/
void tabu_search(int n, int tabu_size, int max_iter);
int initialization(int n, int *pi, int *d1, int *d2, int **tabu_time);
void indexx(int n, int *arrin, int *indx);
void update_best(int n, int *pi_best, int *pi_curr, int *c_best, int c_curr);
void best_move(int n, int iter, int c_best, int c_curr, int *pi, int *d1,
int *d2, int **tabu_time, struct move_info *move);
int evaluate(int i, int j, int *pi, int *d1, int *d2);
void execute_move(struct move_info move, int *pi, int *d1, int *d2);
void print_solution(int flag, int n, int *pi, int c, int iter);
/***************** Memory Allocation Prototypes *************************/
int *ivector(int nl, int nh);
void free_ivector(int *v, int nl);
int **imatrix(int nrl, int nrh, int ncl, int nch);
void free_imatrix(int **m, int nrl, int nrh, int ncl);
void nrerror(char *error_text);
/************************************************************************
* *
* MAIN FUNCTION *
* *
************************************************************************/
void main(int argc, char **argv)
{
int n; /* number of queens */
int tabu_size; /* size of the short term memory function */
int max_iter; /* maximum number of iterations */
int seed; /* seed for random number generator */
if (argc != 5) nrerror("TSQUEEN: <n> <tabu_size> <max_iter> <seed>");
n = atoi(argv[1]);
tabu_size = atoi(argv[2]);
max_iter = atoi(argv[3]);
seed = atoi(argv[4]);
srandom(seed*314);
tabu_search(n, tabu_size, max_iter);
}
/************************************************************************
* *
* TABU SEARCH *
* *
************************************************************************/
void tabu_search(int n, int tabu_size, int max_iter)
{
int iter; /* iteration counter */
int iter_best; /* iteration where best was found */
int *d1; /* queens in negative diagonals */
int *d2; /* queens in positive diagonals */
int *pi_curr; /* current queen configuration */
int *pi_best; /* best queen configuration */
int c_curr; /* number of collisions in pi_curr */
int c_best; /* number of collisions in pi_best */
int **tabu_time; /* tabu structure for swap moves */
struct move_info move; /* information related to best move */
d1 = ivector(2, 2*n);
d2 = ivector(-n+1, n-1);
pi_curr = ivector(1, n);
pi_best = ivector(1, n);
tabu_time = imatrix(1, n, 1, n);
do {
c_curr = initialization(n, pi_curr, d1, d2, tabu_time);
} while (c_curr == 0);
update_best(n, pi_best, pi_curr, &c_best, c_curr);
iter_best = 0;
iter = 0;
print_solution(0, n, pi_best, c_best, iter_best);
while (iter < max_iter && c_best > 0) {
++iter;
best_move(n, iter, c_best, c_curr, pi_curr, d1, d2,
tabu_time, &move);
execute_move(move, pi_curr, d1, d2);
tabu_time[move.i][move.j] = iter + tabu_size;
c_curr += move.value;
#if TRACE
printf("SWAP(%3d, %3d) = %3d\n", move.i, move.j, move.value);
#endif
if (c_curr < c_best) {
update_best(n, pi_best, pi_curr, &c_best, c_curr);
iter_best = iter;
}
#if TRACE
print_solution(1, n, pi_curr, c_curr, iter);
#endif
}
print_solution(2, n, pi_best, c_best, iter_best);
free_ivector(d1, 2);
free_ivector(d2, -n+1);
free_ivector(pi_curr, 1);
free_ivector(pi_best, 1);
free_imatrix(tabu_time, 1, n, 1);
}
/************************************************************************
* *
* INITIALIZATION *
* *
************************************************************************/
int initialization(int n, int *pi, int *d1, int *d2, int **tabu_time)
{
int i; /* queen index */
int *r; /* uniform random number */
int collisions; /* total number of collisions */
r = ivector(1, n);
for (i = 1; i <= n; ++i) r[i] = random();
indexx(n, r, pi);
for (i = 2; i <= 2*n; ++i) {
d1[i] = 0;
d2[i-n-1] = 0;
}
for (i = 1; i <= n; ++i) {
++d1[i+pi[i]];
++d2[i-pi[i]];
}
collisions = 0;
for (i = 2; i <= 2*n; ++i) {
collisions += MAX(0, d1[i]-1);
collisions += MAX(0, d2[i-n-1]-1);
}
free_ivector(r, 1);
return collisions;
}
/************************************************************************
* *
* CONSTRUCTION OF AN INDEX TABLE *
* *
************************************************************************/
void indexx(int n, int *arrin, int *indx)
{
int l, j, ir, indxt, i;
int q;
for (j = 1; j <= n; j++) indx[j] = j;
if (n == 1) return;
l = (n >> 1) + 1;
ir = n;
for (;;) {
if (l > 1)
q = arrin[(indxt = indx[--l])];
else {
q = arrin[(indxt = indx[ir])];
indx[ir] = indx[1];
if (--ir == 1) {
indx[1] = indxt;
return;
}
}
i = l;
j = l << 1;
while (j <= ir) {
if ( j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
if (q < arrin[indx[j]]) {
indx[i] = indx[j];
j += (i = j);
}
else j = ir + 1;
}
indx[i] = indxt;
}
}
/************************************************************************
* *
* UPDATE BEST SOLUTION *
* *
************************************************************************/
void update_best(int n, int *pi_best, int *pi_curr, int *c_best, int c_curr)
{
int i; /* queen index */
for (i = 1; i <= n; ++i)
pi_best[i] = pi_curr[i];
*c_best = c_curr;
}
/************************************************************************
* *
* BEST MOVE *
* *
************************************************************************/
void best_move(int n, int iter, int c_best, int c_curr, int *pi, int *d1,
int *d2, int **tabu_time, struct move_info *move)
{
int i; /* queen i index */
int j; /* queen j index */
int value; /* value of move under consideration */
move->value = n + 1;
for (i = 1; i <= n-1; ++i) {
for (j = i+1; j <= n; ++j) {
value = evaluate(i, j, pi, d1, d2);
#if ZERO
if (value) {
#endif
if (tabu_time[i][j] < iter || c_curr + value < c_best) {
if (value < move->value) {
move->value = value;
move->i = i;
move->j = j;
}
}
#if ZERO
}
#endif
#if FIS
if (move->value < 0) break;
#endif
}
#if FIS
if (move->value < 0) break;
#endif
}
}
/************************************************************************
* *
* MOVE EVALUATION *
* *
************************************************************************/
int evaluate(int i, int j, int *pi, int *d1, int *d2)
{
int c;
c = MAX(0, d1[i+pi[i]]-2) + MAX(0, d2[i-pi[i]]-2) - d1[i+pi[i]] -
d2[i-pi[i]] + 2;
if (i+pi[i] != j+pi[j]) c += MAX(0, d1[j+pi[j]]-2) - d1[j+pi[j]] + 1;
if (i-pi[i] != j-pi[j]) c += MAX(0, d2[j-pi[j]]-2) - d2[j-pi[j]] + 1;
if (i+pi[i] == j+pi[j] && d1[i+pi[i]] > 2) --c;
if (i-pi[i] == j-pi[j] && d2[i-pi[i]] > 2) --c;
c += d1[i+pi[j]] + d2[i-pi[j]] - MAX(0, d1[i+pi[j]]-1) -
MAX(0, d2[i-pi[j]]-1);
if (i+pi[j] != j+pi[i]) c += d1[j+pi[i]] - MAX(0, d1[j+pi[i]]-1);
if (i-pi[j] != j-pi[i]) c += d2[j-pi[i]] - MAX(0, d2[j-pi[i]]-1);
if (i+pi[j] == j+pi[i] || i-pi[j] == j-pi[i]) ++c;
return c;
}
/************************************************************************
* *
* EXECUTE MOVE *
* *
************************************************************************/
void execute_move(struct move_info move, int *pi, int *d1, int *d2)
{
int j; /* column index */
--d1[move.i+pi[move.i]];
--d2[move.i-pi[move.i]];
--d1[move.j+pi[move.j]];
--d2[move.j-pi[move.j]];
++d1[move.i+pi[move.j]];
++d2[move.i-pi[move.j]];
++d1[move.j+pi[move.i]];
++d2[move.j-pi[move.i]];
j = pi[move.j];
pi[move.j] = pi[move.i];
pi[move.i] = j;
}
/************************************************************************
* *
* PRINT BEST SOLUTION *
* *
************************************************************************/
void print_solution(int flag, int n, int *pi, int c, int iter)
{
int i; /* queen index */
int j; /* column index */
if (flag == 0) printf("\nStarting solution:\n\n");
if (flag == 1) printf("\nSolution found at iteration %4d:\n\n", iter);
if (flag == 2) printf("\nBest solution found:\n\n");
printf(" Number of collisions = %6d\n", c);
if (flag == 2) printf(" Number of iterations = %6d\n", iter);
printf("\n ");
for (j = 1; j <= n; ++j) printf("%3d", j);
for (i = 1; i <= n; ++i) {
printf("\n%3d", i);
for (j = 1; j <= n; ++j)
if (pi[i] == j) printf(" **"); else printf(" __");
}
printf("\n\n");
}
/************************************************************************
* *
* MEMORY ALLOCATION FUNCTIONS *
* *
************************************************************************/
int *ivector(int nl, int nh)
{
int *v;
v = (int *)malloc((unsigned)(nh-nl+1)*sizeof(int));
if (!v) nrerror("Memory allocation failure in ivector()");
return v - nl;
}
void free_ivector(int *v, int nl)
{
free((char*) (v + nl));
}
int **imatrix(int nrl, int nrh, int ncl, int nch)
{
int i;
int **m;
m = (int **)malloc((unsigned)(nrh - nrl +1)*sizeof(int*));
if (!m) nrerror("allocation failure 1 in imatrix()");
m -= nrl;
for(i = nrl; i <= nrh ; i++) {
m[i]= (int*)malloc((unsigned)(nch - ncl +1)*sizeof(int));
if (!m[i]) nrerror("allocation failure 2 in imatrix()");
m[i] -= ncl;
}
return m;
}
void free_imatrix(int **m, int nrl, int nrh, int ncl)
{
int i;
for (i = nrh; i >= nrl; i--)
free((char*) (m[i] + ncl));
free((char *)(m + nrl));
}
void nrerror(char *error_text)
{
fprintf(stderr,"\n%s\n",error_text);
fprintf(stderr,"... now exiting to system ...\n");
exit(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -