-1

我有一个函数可以在方格上生成(伪)随机游走,其中游走不应超出该正方形的边界,完整功能如下:

/**
* @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);
}
4

2 回答 2

0

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.

于 2015-11-23T19:45:54.940 回答
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) 上随机生成一个偏移量,并将与 x 或 y 位置突破的边界的差异添加到该偏移量中,以创建一个双精度值,该值将具有该突破差异的最小值和(之后额外的嵌套条件检查)最大为 1.0(或相反边界为 -1.0)。

于 2015-11-23T19:58:24.090 回答