自己写的模拟退火方法求解八皇后问题, 大家帮看看, 下周交作业

songofsp3 2010-02-03 07:38:54
import java.util.Random;
import java.util.Date;

public class NQueenSimulatedAnnealing{
private int[] board;
private int[] test;
private int dim;
private Random ran;
private double currentTemperature;
private double coolingCoefficient;
private int internalIter; //number of swaps accepted.
private int initialConflicts, currentConflicts, conflictsDifference;
private int conflictPosition; //a cursor to circulate the whole array, to record a conflict position

public static void main(String[] args){
// int inDimension;
// double inInitialTemperature, inInitialCoolingCoefficient;
// if (args.length == 0){
// System.out.println("At least the dimension of the board is necessary!");
// return;
// }
// inDimension = Integer.parseInt(args[0]);
// if (args.length > 1){
// inInitialTemperature = Double.parseDouble(args[1]);
// if (args.length > 2){
// inInitialCoolingCoefficient = Double.parseDouble(args[2]);
// }else{
// inInitialCoolingCoefficient = 0.995;
// }
// }else{
// inInitialTemperature = inDimension;
// inInitialCoolingCoefficient = 0.995;
// }
// NQueenSimulatedAnnealing nqsa = new NQueenSimulatedAnnealing(inDimension);
// System.out.println("Board dimension: " + nqsa.dim);
// System.out.println("Initial Conflicts: " + nqsa.getConflicts());
// nqsa.solve(inInitialTemperature, inInitialCoolingCoefficient);

NQueenSimulatedAnnealing nqsa = new NQueenSimulatedAnnealing(10000);
System.out.println("Board dimension: " + nqsa.dim);
System.out.println("Initial Conflicts: " + nqsa.getConflicts());
nqsa.solve(1000, 0.99);
}

public NQueenSimulatedAnnealing(){
this(100);
}

public NQueenSimulatedAnnealing(int dimension){
dim = dimension;
internalIter = 0;
conflictPosition = 0;
ran = new Random(new Date().getTime()); //new random sead
board = new int[dim];
for (int i = 0; i < dim; i++){ //set all Queens at the diagonal
board[i] = i;
}
test = board.clone(); //copy one copy of board to test.
initialConflicts = currentConflicts = this.getConflicts();
}

public void solve(double inInitialTemperature, double inCoolingCoefficient){
currentTemperature = inInitialTemperature;
coolingCoefficient = inCoolingCoefficient;
testQueen();
if (dim <= 50){
display();
}else{
System.out.println("\nSolution found! Too large to print!");
}
}

private void testQueen(){
int swap1, swap2;
while(true){ //control temperature
while(true){ //find an acceptable solution
swap1 = findConflictPosition(); //first swap position: a conflict position
swap2 = ran.nextInt(dim); //second swap position: a random position
swap(swap1, swap2); //swap, in array test[]
conflictsDifference = getConflictsDifference(swap1, swap2); //the differece after and before swap, by comparing board[] and test[]
if (conflictsDifference < 0){ //a better solution
swapAccepted(); //accept
break;
}else{ //a worse solution
if(Math.exp(-conflictsDifference/currentTemperature) > ran.nextDouble()){ //still accepted by a certain probability
swapAccepted();
break;
}else{
test = board.clone(); //cancel the swap, by copy back from board[]
}
}
}
printSwapSummary(); //after a new solution is accepted, print the summary
if (currentConflicts == 0 ){ //solved!
break;
}else{
currentTemperature *= coolingCoefficient; //decrease temperature
}
}
}

private int findConflictPosition(){
int i;
while (true){
for (i = 0; i < dim; i++){
if(Math.abs(conflictPosition - i) == Math.abs(board[conflictPosition] - board[i])){ //conflict!
if (conflictPosition != i){
return conflictPosition;
}
}
}
conflictPosition++;
if (conflictPosition == dim) conflictPosition = 0; //start from the beginning is it reaches the end
}
}

private int getConflictsDifference(int swap1, int swap2){ //only check the two Queens swapped, return the difference.
int oldNumber = 0;
int newNumber = 0;
int i = 0;
for (i = 0; i < dim; i++){
if(Math.abs(swap1 - i) == Math.abs(board[swap1] - board[i])){
oldNumber++;
}
if(Math.abs(swap2 - i) == Math.abs(board[swap2] - board[i])){
oldNumber++;
}
if(Math.abs(swap1 - i) == Math.abs(test[swap1] - test[i])){
newNumber++;
}
if(Math.abs(swap2 - i) == Math.abs(test[swap2] - test[i])){
newNumber++;
}
}
return newNumber - oldNumber;
}

private int getConflicts(){ //iteration to get the total conflicts
int i, j;
int counts = 0;
for (i = 0; i < dim; i++){
for (j = i + 1; j < dim; j++){
int temp = test[i] - test[j];
if (temp == i - j){
counts++;
}else if(temp == j - i){
counts++;
}
}
}
return counts;
}

private void swap(int i, int j){ //swap two columns, since only one queen per row and column
int temp = test[i];
test[i] = test[j];
test[j] = temp;
}

private void display(){
int cursor = 0;
System.out.printf("\n*** One Solution ***\n");
while(cursor < dim){
for (int i = 0; i < test[cursor]; i++){
System.out.print("- ");
}
System.out.print("Q ");
for (int i = test[cursor] + 1; i < dim; i++){
System.out.print("- ");
}
System.out.println();
cursor++;
}
System.out.println("*** Solutions end ***\n");
}

private void swapAccepted(){
board = test.clone();
currentConflicts += conflictsDifference;
}

private void printSwapSummary(){
double tempDraw;
System.out.printf("%6d:%8d:%10.2f \t|", ++internalIter, currentConflicts, currentTemperature);
tempDraw = 50. / initialConflicts * currentConflicts;
for (int i = 1; i< tempDraw; i++){
System.out.print("#");
}
System.out.print("\n");
}

}
...全文
1212 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
mc2cd 2011-10-09
  • 打赏
  • 举报
回复
借鉴了你的findConflictPosition这个函数后 效率高多了
songofsp3 2010-02-04
  • 打赏
  • 举报
回复
关键是要求用模拟退火法了,
另外, 要求算一万维, 穷举就死了...
岁月之梦 2010-02-03
  • 打赏
  • 举报
回复
我实际也没用到,帮顶!
JavaAlpha 2010-02-03
  • 打赏
  • 举报
回复
lilianplayer_163 2010-02-03
  • 打赏
  • 举报
回复
实际项目没有用到,大学的那点早就忘了.
建议lz去网上查下.
维基百科里面可能会有.

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧