C ++ Генератор случайных чисел не действует случайным образом

0

У меня есть код C++, который вызывает другую функцию над ним. Эта функция зависит от случайности для одного из ее вариантов, но она не действует случайным образом. Он набирает одно и то же число каждый раз. Как я могу гарантировать, что это будет случайным?

Я пытался вызвать srand в начале кода, но я не помог. Возможно, я не понимаю что-то важное о сранде.

Вот код, я знаю, что это много, но самый важный материал находится на самом верху:

vector<vector<int> > Successor(vector<int> sudoku_state) {
    srand (time(NULL));
    //Core successor function logic: I choose one of the non-unchangable states at random, and change it to any of its other 3 possible values.  Eg. If a cell with a '1' is chosen at random, then I return the sudoku board with a '2' a '3' and a '4' at that location, in a vector of vectors. 
    vector<vector<int> > list_of_all_successors;
    int random_indice;
    random_indice = rand()%16;
    //make sure it is not one of the unchangable squares
    while((std::find(unchangables.begin(), unchangables.end(), random_indice) != unchangables.end())) 
    {
    random_indice = rand()%16;
    }
    if(sudoku_state[random_indice]==1) {
    sudoku_state[random_indice]=2;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=3;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=4;
    list_of_all_successors.push_back(sudoku_state);
    }
    else if(sudoku_state[random_indice]==2) {
    sudoku_state[random_indice]=1;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=3;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=4;
    list_of_all_successors.push_back(sudoku_state);
    }
    else if(sudoku_state[random_indice]==3) {
    sudoku_state[random_indice]=1;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=2;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=4;
    list_of_all_successors.push_back(sudoku_state);
    }
    else { //then we know == 4
    sudoku_state[random_indice]=2;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=3;
    list_of_all_successors.push_back(sudoku_state);
    sudoku_state[random_indice]=1;
    list_of_all_successors.push_back(sudoku_state);
    }
    return list_of_all_successors;
}

Вот вызывающий:

//The core hillclimbing functionality.  Performs the logic of the hillclimbing algorithm on the given initial sudoku board, called initial_state.  initial_state is represented as a vector of int of size 16.  The returned value called goal_state, is also a vector of int of size 16.
vector<int> hillClimber(vector<int> initial_state) {
    vector<int> goal_state; // the final goal state
    vector<int> sudoku_config_with_lowest_flaws = initial_state; //the state being worked with in each iteration
    int minimum = 500; //the current minimum amount of flaws found in a state (set to 500 initially as a max)
    int iterations = 0; //if iterations reaches a high amount, random restart.
    while(true) {
        cout << "\nBeginning of hillClimber loop reached.\n";
    vector<vector<int> > all_successors = Successor(sudoku_config_with_lowest_flaws);
    cout << "Potential Successors to beginning state determined. Now analyzing.  \n";
    //****Core hillClimber logic:
    //Loop over the successors and determine one with lowest amount of flaws.
    int j = 0;
    while(j<all_successors.size()) {
        vector<int> next_state = all_successors[j];
        int number_of_flaws = Evaluator(next_state);
        if(number_of_flaws <= minimum) {
        minimum = number_of_flaws;
        sudoku_config_with_lowest_flaws = next_state;
        }
        if(number_of_flaws==0) {
        //print the final solution
        cout << "**********A SOLUTION HAS BEEN DETERMINED**********\n";
        for(int i=0; i < sudoku_config_with_lowest_flaws.size(); i++){
            cout << sudoku_config_with_lowest_flaws[i];
            if(i==3 || i==7 || i==11)
            cout << '\n';
        }
        return sudoku_config_with_lowest_flaws;
        }
        j++;
    }
    //print the next lowest state configuration found:
    cout << "Next configuration (passed into next loop of hillClimber) shown below: (Still has " << minimum << " flaws).  \n";
    for(int i=0; i < sudoku_config_with_lowest_flaws.size(); i++){
        cout << sudoku_config_with_lowest_flaws[i];
        if(i==3 || i==7 || i==11)
        cout << '\n';
    }

    iterations++;
    if(iterations>50) {
        //randomized restart area: re-randomizes the initial_state, and runs again.
        cout << "\n ***Reached a local min -- Had to restart hillClimber with a new initial_state! *** \n";
        int i = 0;
        for(i = 0; i<initial_state.size(); i++) {
        if(!(std::find(unchangables.begin(), unchangables.end(), i) != unchangables.end())) {
            initial_state[i] = rand() % 4 + 1;
        }
        }
        cout << "New initial state: \n";
        for(int i=0; i < initial_state.size(); i++){
        cout << initial_state[i];
        if(i==3 || i==7 || i==11)
            cout << '\n';
        }
        cout << "\n Press Enter to continue \n";
        getchar();
        return hillClimber(initial_state);
    }
    }
}

В генерации случайных чисел в функции, называемой "Преемник", она всегда будет находить одно и то же число снова и снова, что разрушает его функциональность.

  • 0
    srand и rand очень просты и могут привести к ошибкам. Я бы посоветовал взглянуть на новые средства <random> , добавленные в C ++ 11, они исправляют проблемы rand и дают больше контроля.
Теги:
random

1 ответ

3
Лучший ответ

Устанавливайте генератор случайных чисел один раз в программе, а не каждый раз, когда вы хотите генерировать случайные числа!

int main()
{
    std::srand( /* some random source */ );

    run_rest_of_program();
}

Источником случайности может быть что-то наивное, как std::time(nullptr) (первое семя ребенка), или более подходящим образом, например std::random_device{}(). Для последнего, #include <random>.

В любом случае вы должны использовать C++ <random>, а не бедный C rand(). Например:

#include <iostream>
#include <random>

int main()
{
    std::mt19937 rng(std::random_device{}());   // the PRNG
    std::normal_distribution<double> dist;      // a distribution

    // Print 100 standard-normally distributed numbers.
    for (int i = 0; i != 100; ++i)
    {
        std::cout << dist(rng) << '\n';
    }
}
  • 0
    Я думаю, что это правильно. Я сделал это изменение только для того, чтобы вызывать srand один раз, и я сразу же приближаю свой алгоритм ИИ к тому, что он должен делать !!!
  • 0
    @Musicode: хорошо. Я желаю, чтобы вы имели смелость отбросить всю эту чепуху на C и использовать функции C ++ <random> , так как они намного лучше.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню