0
我在模拟退火算法解决n皇后问题有一些麻烦。基本上,我已经找到了更好的方法,这很好,但是我运行了一个公式来检查它是否应该采取“坏”的行动。根据我的理解,公式是e ^(电路板状态计算的变化)/ CurrentTemperature。这个数字应该与随机双数或浮点数进行比较,如果随机数大于等式,算法应该采取“坏”的举动。那我得到的问题是,该公式始终为真正接近1或超过1这里是一些我的代码(让我知道如果有更多的应提供):模拟退火N皇后概率论坛
temperature = n*100; //initializes starting temperature
currentTemp = n*100;
int cooldown = n*2; //initializes cool down temperature
float examine = 0; //this is the change in board calculation
int cost = 1;
boolean betterMove = false;
queen = new int[n];
int[][] board = graph; // generates a board of n size
float ran = 0; //random float to compare to
double compareAgainst = 0; //formula variable
cost = calculate(board, n); //calculates the cost
while (cost > 0 && currentTemp > 0)
{
// chooses a random queen to move that has a heuristic higher than zero
int Q = rand.nextInt(n);
while (queen[Q] == 0)
Q = rand.nextInt(n);
betterMove = false;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (board[i][j] == 1 && j == Q)
{
while (!betterMove)
{
int move = i;
while (move == i)
move = rand.nextInt(n); //pick a random move
tempBoard[i][j] = 0; //erase old position
tempBoard[move][j] = 1; //set new position
examine = calculate(tempBoard, n) - calculate(board, n); //calculates the difference between the change in boards
ran = rand.nextFloat(); //generates random number to compare against
compareAgainst = Math.pow(Math.E, (-examine/currentTemp)); //formula out of the book, basically is e^(change in board state divided by currentTemp)
if (calculate(tempBoard, n) < calculate(board, n)) //if this is a better move
{
for (int a = 0; a < n; a++)
for (int b = 0; b < n; b++)
board[a][b] = tempBoard[a][b]; //set it to the board
cost = calculate(board, n);
currentTemp -= cooldown; //cool down the temperature
betterMove = true;
}
else if(calculate(tempBoard,n) >= calculate(board,n)) //if this is a worse move
{
if(verbose == 1) //outputs whether or not this is a bad move and outputs function value and random float for simulated annealing purposes
{
System.out.println("This is a worse move");
System.out.println("The numbers for Simulated Annealing:");
System.out.println("Random number = " + ran);
System.out.println("Formula = " + compareAgainst);
System.out.println("Examine = " + examine);
}
if(ran > compareAgainst) //if the random float is greater than compare against, take the bad move
{
for (int a = 0; a < n; a++)
for (int b = 0; b < n; b++)
board[a][b] = tempBoard[a][b]; //take the move
cost = calculate(board, n);
currentTemp-= cooldown;
betterMove = true;
}
else //if not, do not take the move
{
for (int a = 0; a < n; a++)
for (int b = 0; b < n; b++)
tempBoard[a][b] = board[a][b];
}
currentTemp-= cooldown;
betterMove = true;
}
}
}
i = n;
j = n;
}
}
}
}
我已经尝试了一些诸如使检查变量为负数或取得棋盘状态差异的绝对值等事情。另外,被调用的计算函数基本上扫描板并返回有多少个皇后冲突,这是一个整数。让我知道是否需要更多的澄清。感谢
[这里](https://github.com/droolsjbpm/drools-planner/blob/master /drools-planner-core/src/main/java/org/drools/planner/core/localsearch/decider/acceptor/simulatedannealing/SimulatedAnnealingAcceptor.java#L28)是我在Java中的模拟退火实现,它在N个皇后和[更多高级用例](http://docs.jboss.org/drools/release/5.5.0.Final/drools-planner-docs/html_single/index.html#downloadAndRunTheExamples)。也许它有帮助。它适用于多个分数级别(其中分数超过1就是双倍)。 – 2013-03-04 09:09:01
@GeoffreyDeSmet你好杰弗里,请你再次发送你的密码。我无法打开您的链接。 – svlzx 2013-11-05 23:28:28
@svlzx [这是我现在的SA实现](https://github.com/droolsjbpm/optaplanner/blob/master/optaplanner-core/src/main/java/org/optaplanner/core/impl/localsearch/decider/acceptor /simulatedannealing/SimulatedAnnealingAcceptor.java) – 2013-11-06 07:17:00