nqueens min-conflic搜索性能低下

问题描述 投票:1回答:1

我正在执行nqueens min-conflict搜索,如]所述>

[Norvig,S.&Peter,J. R. and。 (2014)。人工智能是一种现代方法。在皮尔逊(第58卷,第12期)中。enter image description here

作者提到这种启发式方法非常有效:

enter image description here

然而,当我实现它时,我不能在一分钟之内解决超过5000个问题。尽管作者在50次迭代中实现了100万次迭代的速度,但我的实现通常会在5000次迭代中进行1000次迭代。 Another question提到了类似的结果。

关于我在做什么错的任何想法?是算法上的还是我在不应该使用的循环中使用?

update()是主要方法。

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <tuple>
#include <limits>
#include <queue>
#include <list>
#include <algorithm>
#include <map>

using namespace std;

/*
 * The n-queens problem solver
 * 
 * size      - the number of queens
 * isVerbose - whether the intermediate nodes are displayed
 */
//column,conflicts[row]


class NqueensSearch {
public:
    unsigned iterations = 0;
    unsigned boardSize;
    ofstream myfile;
    bool is_debug;
    bool isVerbose;

    NqueensSearch(int size, bool isVerbose) {
        boardSize = (unsigned) size;
        this->isVerbose = isVerbose;
    }

    void intialize(unsigned currentState[]) {
        int min = 0;
        int max = boardSize - 1;
        for (unsigned i = 0; i < boardSize; i++) {
            currentState[i] = rand() % (max - min + 1) + min;
        }

    }

    unsigned randomMax(unsigned max) {
        unsigned min = 0;
        return rand() % (max - min + 1) + min;
    }

    unsigned randomRowOrColumn() {
        return randomMax(boardSize - 1);
    }

    void debug(const string message) {
        if (is_debug) {
            myfile << message << endl;
        }
    }

    void enable_debug() {
        is_debug = true;
        if (is_debug) {
            myfile.open("debug.txt");
        }
    }

    void printBoard(const unsigned currentState[]) {
        string header;
        for (unsigned i = 0; i < boardSize - 1; i++) {
            header += "-";

        }
        header += to_string(iterations);
        cout << header << endl;


        for (unsigned i = 0; i < boardSize; i++) {

            string line;
            unsigned place = currentState[i];
            for (unsigned j = 0; j < boardSize; j++) {
                if (j == place) {
                    line += "Q";
                } else {
                    line += "*";
                }

            }
            cout << line << endl;

        }
    }



    bool isConflict(unsigned row, unsigned column, unsigned otherRow, unsigned otherColumn) {
        if (row == otherRow) {
            debug("same row " + to_string(row));
            return false;
        }
        unsigned rowDistance = abs((int) row - (int) otherRow);
        if (column == otherColumn) {
            return true;
        } else if (abs((int) column - (int) otherColumn) == rowDistance) {
            return true;
        }
        return false;
    }

    bool isGoal(const unsigned currentState[]) {
        bool result = true;
        for (unsigned row = 0; row < boardSize; row++) {
            for (unsigned otherRow = 0; otherRow < boardSize; otherRow++) {
                if (isConflict(row, currentState[row], otherRow, currentState[otherRow])) {
                    result = false;
                }
            }
        }

        return result;

    }

    unsigned getMinConflictColumn(const unsigned currentState[], unsigned row) {
        unsigned columnOfMinConflict = 0;
        unsigned queenColumn = currentState[row];
        unsigned minConflicts = numeric_limits<unsigned>::max();
        debug("getMinConflictColumn, row:" + to_string(row));

        for (unsigned column = 0; column < boardSize; column++) {
            unsigned conflicCout = 0;

            if (column == queenColumn) continue;
            for (unsigned otherRow = 0; otherRow < boardSize; otherRow++) {
                if (row == otherRow)//same row ignore
                {
                    //debug("same row "+to_string(row));
                    continue;
                }
                if (isConflict(row, column, otherRow, currentState[otherRow])) {
                    conflicCout++;
                }

            }
            if (conflicCout == 0) {
                debug("\t noflict at " + to_string(column) + " : " + to_string(row));
            }
            debug("Conflict at " + to_string(column) + ":" + to_string(row) + " = " + to_string(conflicCout));
            if (conflicCout < minConflicts) {
                debug("Conflict updated");
                minConflicts = conflicCout;
                columnOfMinConflict = column;
            }

        }

        return columnOfMinConflict;

    }



    void placeQueen(unsigned currentState[], unsigned row, unsigned column) {
        currentState[row] = column;
    }


    list<unsigned> rowsInConflict(const unsigned currentState[]) {
        list<unsigned> rowsInConflict; //TODO change to map

        for (unsigned row = 0; row < boardSize; row++) {
            for (unsigned otherRow = 0; otherRow < boardSize; otherRow++) {
                if (isConflict(row, currentState[row], otherRow, currentState[otherRow])) {
                    rowsInConflict.push_front(row);
                    debug("row in conflict " + to_string(row));
                    rowsInConflict.push_front(otherRow);
                    //return rowsInConflict;
                }
            }
        }

        return rowsInConflict;
    }

    bool update(unsigned currentState[]) {
                unsigned randomRow, column;

        list<unsigned> conflictRows = rowsInConflict(currentState);
        if (conflictRows.empty()) {
            return true;
        }

        list<unsigned>::iterator it = conflictRows.begin();
        std::advance(it, rand() % conflictRows.size());
        randomRow = (unsigned) *it;

        column = getMinConflictColumn(currentState, randomRow);
        placeQueen(currentState, randomRow, column);


        return false;

    }



    void solve_nqueen(unsigned size, bool isVerbose) {
        boardSize = size;
        unsigned rowSpace[size];




        //enable_debug();
        intialize(rowSpace);
        if (isVerbose) {
            printBoard(rowSpace);
        }


        while (!update(rowSpace)) {
            if (isVerbose) {
                printBoard(rowSpace);

            }
            if (iterations >= 1000) {
                cout << "Random restart." << endl;
                intialize(rowSpace);
                iterations = 0;
            }
            iterations++;
        }
        printBoard(rowSpace);




    }

};

/*
 * The main function.
 */
int main(int argc, char** argv) {

    int size;
    bool isVerbose = false, isArgValid = true;

    if (argc == 2) {
        size = atoi(argv[1]);
        isArgValid = (size > 0);
    } else if (argc == 3) {
        if (strcmp(argv[1], "-v") == 0) {
            isVerbose = true;
            size = atoi(argv[2]);
            isArgValid = (size > 0);
        } else {
            isArgValid = false;
        }
    } else {
        isArgValid = false;
    }

    if (!isArgValid) {
        cout << "Error in command line arguments." << endl;
        cout << "Usage: " << argv[0] << " [-v] n" << endl;
        cout << "where n is the number of queens and the size of the board (nxn)." << endl;
        cout << "The option -v enables the output of the intermediate states of" << endl;
        cout << "the search procedure." << endl;
        return 1;
    }

    NqueensSearch problem(size, isVerbose);
    problem.solve_nqueen(size, isVerbose);
    //solve_nqueen(size, isVerbose);

    return 0;
}


我正在实施Norque,S.,&Peter,J. R. and。提到的nqueens最小冲突搜索。 (2014)。人工智能是一种现代方法。在皮尔逊(第58卷,第12期)中。作者...

c++ algorithm search heuristics n-queens
1个回答
0
投票

正如我在评论中所说,如果您要尽量减少交换次数,从良好的初始配置开始至关重要。在我的nQueens实现中,我有3种不同的方法来为每个皇后生成初始行:

© www.soinside.com 2019 - 2024. All rights reserved.