random — ошибка с минимальными / максимальными аргументами из-за переполнения стекаiform_real_distribution

У меня есть функция для генерации (псевдо) случайного блуждания по квадратной решетке, где блуждание не должно выходить за границы этого квадрата, полная функция приведена ниже:

/**
* @brief Performs a single random walk returning the final distance from the origin
*
* Completes a random walk on a square lattice using the mersenne twister engine based pseudo-random
* number-generator (PRNG). The walk will not breach the boundaries of the square size provided to
* the function. The random walk starts at the origin and ends after some parameterised number of steps.
* Position co-ordinates of the walk for each iteration are sent to an output file.
*
* @param squareSideLength Length of square lattice side
* @param steps Number of steps to compute random walk up to
* @param engine Mersenne Twister engine typedef (used for generating random numbers locally)
* @param distribution Default distribution of random walk
* @param outputFile [Default nullptr] Pointer to file to write co-ordinate data of random walk to
* @return final distance of the particle from the origin
*/
double randomWalkSquareLattice(int squareSideLength, int steps, std::mt19937& engine, std::uniform_real_distribution<double>& distribution, std::ofstream* outputFile = nullptr) {

// store the half-length of the square lattice
const int halfSquareLength = squareSideLength / 2;

// initialise co-ordinates to the origin
double positionX = 0.0;
double positionY = 0.0;

// assign the default distribution to distDefault
std::uniform_real_distribution<double> distDefault = distribution;

// loop over a number of iterations given by the steps parameter
for (int i = 0; i < steps; i++) {

std::cout << positionX << "\t" << positionY << std::endl;

// if the x-position of the particle is >= to positive
// half square lattice length then generate decremental
// random number (avoiding breaching the boundary)
if (positionX >= halfSquareLength) {
double offset = positionX - halfSquareLength;
std::cout << std::endl << offset << std::endl;
std::uniform_real_distribution<double> distOffset(-offset, -1.0);
positionX += distOffset(engine);
}

// else if the x-position of the particle is <= to negative
// half square lattice length then generate incremental random
// number (avoiding breaching the boundary)
else if (positionX <= -halfSquareLength) {
double offset = std::abs(positionX + halfSquareLength);
std::cout << std::endl << offset << std::endl;
std::uniform_real_distribution<double> distOffset(offset, 1.0);
positionX += distOffset(engine);
}

// else (in case where x-position of particle is not touching
// the lattice boundary) generate default random number
else {
positionX += distDefault(engine);
}

// if the y-position of the particle is >= to positive
// half square lattice length then generate decremental
// random number (avoiding breaching the boundary)
if (positionY >= halfSquareLength) {
double offset = positionY - halfSquareLength;
std::cout << std::endl << offset << std::endl;
std::uniform_real_distribution<double> distOffset(-offset, -1.0);
positionY += distOffset(engine);
}

// else if the y-position of the particle is <= to negative
// half square lattice length then generate incremental
// random number (avoiding breaching the boundary)
else if (positionY <= -halfSquareLength) {
double offset = std::abs(positionY + halfSquareLength);
std::cout << std::endl << offset << std::endl;
std::uniform_real_distribution<double> distOffset(offset, 1.0);
positionY += distOffset(engine);
}

// else (in case where y-position of particle is not touching
// the lattice boundary) generate default random number
else {
positionY += distDefault(engine);
}

// if an outputFile is supplied to the function, then write data to it
if (outputFile != nullptr) {
*outputFile << positionX << "\t" << positionY << std::endl;
}

}

// compute final distance of particle from origin
double endDistance = std::sqrt(positionX*positionX + positionY*positionY);

return endDistance;

}

В тех случаях, когда условия, видимые в методе, не позволяют выходить за пределы границ. Однако, когда это вызывается с достаточным количеством шагов (так что выполняется любое из этих условий), я получаю сообщение об ошибке:

invalid min and max arguments for uniform_real

Обратите внимание, что dist, который я посылаю этой функции:

std::uniform_real_distribution<double> dist(-1.0,1.0);

И поэтому (как вы можете видеть из значений, напечатанных на терминале), проблема не в том, что смещение когда-либо будет больше, чем максимальное значение, заданное distOffset в любом из условных случаев.

Является ли проблема, что я не могу дать u_r_d двойное значение произвольной точности? Или что-то еще здесь играет, что мне не хватает?

Редактировать: я должен добавить, что это значения, используемые в main ():

int main(void) {
std::uniform_real_distribution<double> dist(-1.0, 1.0);

std::random_device randDevice;

std::mt19937 engine(randDevice());
//std::cout << dist(engine) << std::endl;
// Dimensions of Square Lattice
const int squareLength = 100;

// Number of Steps in Random Walk
const int nSteps = 10000;

randomWalkSquareLattice(squareLength, nSteps, engine, dist);
}

-1

Решение

uniform_real_distribution(a,b); требует, чтобы a ≤ b,

Если positionX == halfSquareLength, затем,

double offset = positionX - halfSquareLength;

это то же самое, что сказать

double offset = positionX - positionX;

а также offset будет ноль.

Это приводит к

std::uniform_real_distribution<double> distOffset(-0.0, -1.0);

и нарушает a ≤ b,

0

Другие решения

Вот решение, которое я придумал, похоже, пока работает для всех тестовых случаев:

/**
* @brief Performs a single random walk returning the final distance from the origin
*
* Completes a random walk on a square lattice using the mersenne twister engine based pseudo-random
* number-generator (PRNG). The walk will not breach the boundaries of the square size provided to
* the function. The random walk starts at the origin and ends after some parameterised number of steps.
* Position co-ordinates of the walk for each iteration are sent to an output file.
*
* @param squareSideLength Length of square lattice side
* @param steps Number of steps to compute random walk up to
* @param engine Mersenne Twister engine typedef (used for generating random numbers locally)
* @param distribution Default distribution of random walk
* @param outputFile [Default nullptr] Pointer to file to write co-ordinate data of random walk to
* @return final distance of the particle from the origin
*/
double randomWalkSquareLattice(int squareSideLength, int steps, std::mt19937& engine, std::uniform_real_distribution<double>& distribution, std::ofstream* outputFile = nullptr) {

// store the half-length of the square lattice
const int halfSquareLength = squareSideLength / 2;

// initialise co-ordinates to the origin
double positionX = 0.0;
double positionY = 0.0;

// assign the default distribution to distDefault
std::uniform_real_distribution<double> distDefault = distribution;

std::uniform_real_distribution<double> distBound(0.0, 1.0);

double oS;

// loop over a number of iterations given by the steps parameter
for (int i = 0; i < steps; i++) {

//std::cout << positionX << "\t" << positionY << std::endl;

positionX += distDefault(engine);
positionY += distDefault(engine);

// if the x-position of the particle is >= to positive
// half square lattice length then generate decremental
// random number (avoiding breaching the boundary)
if (positionX >= halfSquareLength) {
oS = distBound(engine);
double offset = positionX - halfSquareLength;
double desiredOffset = -(oS + offset);

if (desiredOffset < -1.0) {
double offsetFromNegUnity = desiredOffset + 1.0;
desiredOffset -= offsetFromNegUnity;
}

positionX += desiredOffset;
}

// else if the x-position of the particle is <= to negative
// half square lattice length then generate incremental random
// number (avoiding breaching the boundary)
else if (positionX <= -halfSquareLength) {
oS = distBound(engine);
double offset = std::abs(positionX + halfSquareLength);
double desiredOffset = offset+oS;

if (desiredOffset > 1.0) {
double offsetFromUnity = desiredOffset - 1.0;
desiredOffset -= offsetFromUnity;
}

positionX += desiredOffset;
}

// if the y-position of the particle is >= to positive
// half square lattice length then generate decremental
// random number (avoiding breaching the boundary)
if (positionY >= halfSquareLength) {
oS = distBound(engine);
double offset = positionY - halfSquareLength;
double desiredOffset = -(offset+oS);

if (desiredOffset < -1.0) {
double offsetFromNegUnity = desiredOffset + 1.0;
desiredOffset -= offsetFromNegUnity;
}

positionY += desiredOffset;
}

// else if the y-position of the particle is <= to negative
// half square lattice length then generate incremental
// random number (avoiding breaching the boundary)
else if (positionY <= -halfSquareLength) {
oS = distBound(engine);
double offset = std::abs(positionY + halfSquareLength);
double desiredOffset = offset+oS;

if (desiredOffset > 1.0) {
double offsetFromUnity = desiredOffset - 1.0;
desiredOffset -= offsetFromUnity;
}

positionY += desiredOffset;
}

// if an outputFile is supplied to the function, then write data to it
if (outputFile != nullptr) {
*outputFile << positionX << "\t" << positionY << std::endl;
}

}

// compute final distance of particle from origin
double endDistance = std::sqrt(positionX*positionX + positionY*positionY);

return endDistance;

}

Здесь смещение было сгенерировано случайным образом на интервале (0,1), и к этому смещению было добавлено различие от границы, по которой нарушенная позиция оси или оси y, чтобы создать двойное значение, которое будет иметь минимум этой разрыва и дополнительная вложенная условная проверка) максимум 1,0 (или -1,0 для противоположной границы).

0

По вопросам рекламы [email protected]