С ++ скрипт иногда запускается, а иногда зависает - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь заняться генетическим программированием на C ++. Я собрал версию этого кода на Python, и он работал нормально (это было просто слишком медленно). Основная предпосылка - просмотр программ в виде древовидных выражений и их развитие.

Вот код для создания только одного дерева кандидатов (деревья хранятся в виде векторов узлов, которые указывают на своих потомков по индексу дочернего узла в том же векторе) (см. Функцию grow_tree):

Этот код компилируется нормально :) Я компилирую, используя g ++, чтобы получить файл a.out, который я запускаю, используя ./a.out

Моя проблема в том, что иногда он работает и завершается нормально, а иногда просто зависает и ничего не делает (также не дает мне ошибки)

Любая помощь по этому вопросу будет принята с благодарностью! Спасибо!

#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <math.h>

const int MAX_TREE_DEPTH = 5;

int randint(int min, int max) {
    return (rand() % ((max - min) + 1)) + min;
}

struct node {
    int type, op, req_ch;
    std::vector<int> ch;
    std::map<std::string, float> params;
    node(int p, int rem_depth) {
        if ((p == -1) || (p == 0)) {
            req_ch = 2;
            if (rem_depth >= 2) { 
                type = randint(0, 1); 
                if (type == 0) { 
                    op = randint(0, 1); 
                } else if (type == 1) { 
                    op = randint(2, 5); 
                }
            } else { 
                type = 1; 
                op = randint(2, 5); 
            }
        } else if (p == 1) { 
            type = 2;  
            if (rem_depth >= 1) { 
                op =  randint(6, 11); 
            } else { op = 11; }
            if ((op >= 6) && (op <= 10)) { 
                req_ch = 2; 
            } else if (op >= 11) { req_ch = 0; }
        }
    }    
};

void grow_tree(std::vector<node>* func, int p, int rem_depth) {
    node n(p, rem_depth);
    func->push_back(n);
    int i = func->size() - 1;
    for (int j = 0; j < n.req_ch; j++) {
        func->at(i).ch.push_back(func->size());
        grow_tree(func, n.type, rem_depth - 1);
    }
}


struct rule {
    float score;
    bool scored;
    std::vector<node> func;
    rule(int m) {
        if (m == 0) { // Random initialisation
            int depth = randint(2, MAX_TREE_DEPTH);
            grow_tree(&func, -1, depth);
        }
    }
};


int main(void) {
    srand(time(NULL));  // Seed the random number generator
    int depth = randint(2, MAX_TREE_DEPTH);
    std::vector<node> f;
    grow_tree(&f, -1, depth);
    return 0;
}

1 Ответ

0 голосов
/ 04 июля 2018

Как указано @molbdnilo, ваш конструктор node подвержен переменным, которые неинициализируются после его возврата. Затем вы используете node переменные (и) экземпляра здесь grow_tree:

for (int j = 0; j < n.req_ch; j++) {

Если n.req_ch является неинициализированным или «диким» значением, цикл может продолжаться очень долго. Представьте, что если n.req_ch вернулось со значением, близким к (предположим, 32-разрядные целые числа), 2^32 - 1. Ваш цикл будет выполняться более 2 000 000 000 итераций.

Чтобы подтвердить это, если вы инициализировали свой член переменных node значением, вы можете легко вывести эти переменные, чтобы увидеть, было ли изменено начальное значение. Если значение не изменилось, это подтверждает, что вы используете неинициализированные значения в вашей функции grow_tree.

Пример:

node(int p, int rem_depth) :type(-100), op(-100), req_ch(-100) // Initialize everything to -100
{
   // your code
 ...
   // now check if all the variables have been initialized (values were changed from -100)
   if ( type == -100 || op == -100 || req_ch == -100 )
   {
       std::cout << "Oops.  I'm using uninitialized values for p = " << p << 
      " rem_depth = " << rem_depth << "\n";
       std::cout << type << " " << op << " " << req_ch << "\n\n";
    }   
}

Вот ваш код, модифицированный чеком.

Как вы можете видеть, ваш конструктор node не устанавливает все значения, и вы будете использовать эти значения позже в grow_tree.

Итак, ответ на ваш вопрос - вернуться и закрыть дыру в конструкторе node, чтобы ваши переменные были инициализированы.

...