-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 に任意精度の double 値を指定できないという問題はありますか? それとも、私が見逃している何か他のものがここにあるのでしょうか?

編集:これらは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 位置が違反した境界との差がこのオフセットに追加され、この違反差が最小になる double 値が作成され、(追加のネストされた条件チェック) 最大 1.0 (反対の境界の場合は -1.0)。

于 2015-11-23T19:58:24.090 に答える