int totalNQueens(int n) { if (n < 1) return 0; vector<int> usedRows(n, -1); vector<vector<bool> > used(n, vector<bool>(n, false)); int num = 0; findNQueens(0, n, usedRows, used, num); return num; }
void withoutReplacementImpl(withoutReplacementArgs& args) { boost::numeric::ublas::matrix<double>& matrix = args.matrix; int n = args.n; int seed = args.seed; double alpha = args.alpha; if(matrix.size1() != matrix.size2()) { throw std::runtime_error("Matrix must be square"); } if(n < 1) { throw std::runtime_error("Input n must be at least 1"); } int dimension = matrix.size1(); boost::mt19937 randomSource; randomSource.seed(seed); std::vector<double> columnSums(dimension,0); for(int row = 0; row < dimension; row++) { for(int column = 0; column < dimension; column++) { columnSums[column] += std::fabs(matrix(row, column)); } } std::vector<double> currentColumnSums(dimension), newCurrentColumnSums; std::vector<int> availableColumns(dimension), newAvailableColumns; std::vector<int> availableRows(dimension), newAvailableRows; std::vector<int> previousEntry(1), newPreviousEntry; std::vector<bool> usedRows(dimension), newUsedRows; std::vector<mpfr_class> weights(1, 1), newWeights; //Get out the choices at the start. std::vector<possibility> possibilities; for(int i = 0; i < dimension; i++) { for(int j = 0; j < dimension; j++) { possibility nextPos; nextPos.parent = 0; nextPos.previousEntry = i; nextPos.newEntry = j; possibilities.push_back(nextPos); } } //These choices are all derived from a single particle at the start std::copy(columnSums.begin(), columnSums.end(), currentColumnSums.begin()); for(int i = 0; i < dimension; i++) { availableColumns[i] = i; availableRows[i] = i; } std::fill(usedRows.begin(), usedRows.end(), false); sampling::sampfordFromParetoNaiveArgs samplingArgs; samplingArgs.n = n; samplingArgs.weights.resize(dimension*dimension); for(int i = 0; i < (int)possibilities.size(); i++) { possibility& pos = possibilities[i]; if(pos.previousEntry == pos.newEntry) { samplingArgs.weights[i] = alpha * std::fabs(matrix(pos.previousEntry, pos.newEntry)) / (dimension*(dimension - 1)); } else { samplingArgs.weights[i] = std::fabs(matrix(pos.previousEntry, pos.newEntry)) / dimension; } } int currentSamples = 1; for(int permutationCounter = 0; permutationCounter < dimension; permutationCounter++) { //Draw sample if((int)possibilities.size() <= n) { newCurrentColumnSums.resize(possibilities.size()*dimension); newAvailableColumns.resize(possibilities.size()*(dimension - permutationCounter-1)); newAvailableRows.resize(possibilities.size()*(dimension - permutationCounter-1)); newUsedRows.resize(possibilities.size()*dimension); newPreviousEntry.resize(possibilities.size()); int newAvailableColumnsIndex = 0; int newAvailableRowsIndex = 0; for(int i = 0; i < (int)possibilities.size(); i++) { possibility& pos = possibilities[i]; std::copy(currentColumnSums.begin() + pos.parent * dimension, currentColumnSums.begin() + (pos.parent + 1) * dimension, newCurrentColumnSums.begin() + dimension * i); newCurrentColumnSums[dimension*i + pos.newEntry] -= std::fabs(matrix(pos.previousEntry, pos.newEntry)); std::copy(usedRows.begin() + pos.parent*dimension, usedRows.begin() + (pos.parent + 1) * dimension, newUsedRows.begin() + dimension*i); newUsedRows[dimension*i + pos.previousEntry] = true; for(int j = 0; j < dimension - permutationCounter; j++) { if(availableColumns[j + pos.parent*(dimension - permutationCounter)] != pos.newEntry) { newAvailableColumns.at(newAvailableColumnsIndex) = availableColumns.at(j + pos.parent*(dimension - permutationCounter)); newAvailableColumnsIndex++; } if(availableRows[j + pos.parent*(dimension - permutationCounter)] != pos.previousEntry) { newAvailableRows.at(newAvailableRowsIndex) = availableRows.at(j + pos.parent*(dimension - permutationCounter)); newAvailableRowsIndex++; } } if(newUsedRows[i*dimension + pos.newEntry]) { newPreviousEntry[i] = -1; } else { newPreviousEntry[i] = pos.newEntry; } } newWeights.swap(samplingArgs.weights); currentSamples = possibilities.size(); } else { sampfordFromParetoNaive(samplingArgs, randomSource); newCurrentColumnSums.resize(n*dimension); newAvailableColumns.resize(n*(dimension - permutationCounter-1)); newAvailableRows.resize(n*(dimension - permutationCounter-1)); newUsedRows.resize(n*dimension); newWeights.resize(n); newPreviousEntry.resize(n); int newAvailableColumnsIndex = 0; int newAvailableRowsIndex = 0; for(int i = 0; i < n; i++) { possibility& pos = possibilities[samplingArgs.indices[i]]; std::copy(currentColumnSums.begin() + pos.parent * dimension, currentColumnSums.begin() + (pos.parent + 1) * dimension, newCurrentColumnSums.begin() + dimension * i); newCurrentColumnSums[dimension*i + pos.newEntry] -= std::fabs(matrix(pos.previousEntry, pos.newEntry)); std::copy(usedRows.begin() + pos.parent*dimension, usedRows.begin() + (pos.parent + 1) * dimension, newUsedRows.begin() + dimension*i); newUsedRows[dimension*i + pos.previousEntry] = true; for(int j = 0; j < dimension - permutationCounter; j++) { if(availableColumns[j + pos.parent*(dimension - permutationCounter)] != pos.newEntry) { newAvailableColumns.at(newAvailableColumnsIndex) = availableColumns.at(j + pos.parent*(dimension - permutationCounter)); newAvailableColumnsIndex++; } if(availableRows[j + pos.parent*(dimension - permutationCounter)] != pos.previousEntry) { newAvailableRows.at(newAvailableRowsIndex) = availableRows.at(j + pos.parent*(dimension - permutationCounter)); newAvailableRowsIndex++; } } if(newUsedRows[i*dimension + pos.newEntry]) { newPreviousEntry[i] = -1; } else { newPreviousEntry[i] = pos.newEntry; } newWeights[i] = samplingArgs.weights[samplingArgs.indices[i]] / samplingArgs.rescaledWeights[samplingArgs.indices[i]]; } currentSamples = n; } previousEntry.swap(newPreviousEntry); currentColumnSums.swap(newCurrentColumnSums); availableColumns.swap(newAvailableColumns); availableRows.swap(newAvailableRows); usedRows.swap(newUsedRows); weights.swap(newWeights); //If we're not at the end, get out the list of possibilities and also weights if(permutationCounter != dimension - 1) { possibilities.clear(); samplingArgs.weights.clear(); for(int i = 0; i < currentSamples; i++) { if(previousEntry[i] == -1) { for(int j = 0; j < dimension - permutationCounter - 1; j++) { for(int k = 0; k < dimension - permutationCounter - 1; k++) { possibility pos; pos.parent = i; pos.previousEntry = availableRows[(dimension - permutationCounter - 1) * i + j]; pos.newEntry = availableColumns[(dimension - permutationCounter - 1) * i + k]; possibilities.push_back(pos); if(j == k || usedRows[pos.newEntry + dimension * i]) { if(dimension - 2 != permutationCounter) { samplingArgs.weights.push_back(weights[i] * alpha * std::fabs(matrix(pos.previousEntry, pos.newEntry))/ (dimension - permutationCounter - 2)); } else { samplingArgs.weights.push_back(weights[i] * alpha * std::fabs(matrix(pos.previousEntry, pos.newEntry))); } } else { samplingArgs.weights.push_back(weights[i] * std::fabs(matrix(pos.previousEntry, pos.newEntry))); } } } } else { for(int j = 0; j < dimension - permutationCounter - 1; j++) { possibility pos; pos.parent = i; pos.previousEntry = previousEntry[i]; pos.newEntry = availableColumns[(dimension - permutationCounter - 1) * i + j]; possibilities.push_back(pos); if(j == previousEntry[i] || usedRows[pos.newEntry + dimension * i]) { if(dimension - 2 != permutationCounter) { samplingArgs.weights.push_back(weights[i] * alpha * std::fabs(matrix(pos.previousEntry, pos.newEntry)) / (dimension - permutationCounter - 2)); } else { samplingArgs.weights.push_back(weights[i] * alpha * std::fabs(matrix(pos.previousEntry, pos.newEntry))); } } else { samplingArgs.weights.push_back(weights[i] * std::fabs(matrix(pos.previousEntry, pos.newEntry))); } } } } } } args.estimate = 0; for(int i = 0; i < (int)weights.size(); i++) { args.estimate += weights[i]; } }