0

I'm trying to implement MCTS using C++, and in order to save (in a file) all the moves played by the simulations, I implemented a "arbrecontigu" class to construct a vector of element (which contain informations used in our MCTS : 'Brix' is for example the name of the pieces of our game) , from a non-complete and unbalanced binary tree.

The MC algorithm itself works fine, but when the height of my binary tree is around 30, I got an "bad allocation" error around //values.reserve(tailletab);

Meanwhile, I can initialize a vector of int size 2^100 without getting an error, so I'm a bit confused...

// arbrecontigu.h

#ifndef ARBRECONTIGU_H
#define ARBRECONTIGU_H
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <math.h>
#include "arbrebin.h"
#include "../brix.hh"

struct element{
    int value;
    int iterations;
    bool isnull;
    Brix brix;
};

class ArbreContigu
{
private:
    std::vector<element> file_to_vector(const std::string & filename);
    std::vector<std::string> explode(const std::string & str, char x);

public:
    std::vector<element> values;
    ArbreContigu(const std::string & filename);
    ArbreContigu(Binarytree const& b); // a définir (! sans recursivité)
    std::vector<element> getvalues() const {return values;}
    void to_csv(std::string const & filename);

};
#endif // ARBRECONTIGU_H

// arbrecontigu.cpp

#include "arbrecontigu.h"
#include <queue>
ArbreContigu::ArbreContigu(const std::string &filename)
{
    values = file_to_vector(filename);
}



ArbreContigu::ArbreContigu(const Binarytree &b)
{
    if (!b.isnull()) {
        std::queue<const Binarytree::Node * > qb;
        std::queue<size_t> qi;
        qi.push(1);
        qb.push(&b.getNodeConst());
        size_t tabsize = static_cast<size_t>(std::pow(2,(b.hauteur()+1)));
        //values.reserve(tailletab);
        for (size_t i = 0;i<tabsize;++i) 
        {
            values.push_back({0,0,true,Brix()});
            
        }
        while (!qb.empty()) {
            const Binarytree::Node * nodeb = qb.front();
            size_t i = qi.front();
            qb.pop();
            qi.pop();

            values[i-1] = {nodeb->getVal(),nodeb->getVal(),false,nodeb->getCoup()};
            if (!nodeb->leftIsNull()) {
                qb.push(&nodeb->getLeftConst());
                qi.push(i*2);
            }
            if (!nodeb->rightIsNull()) {
                qb.push(&nodeb->getRightConst());
                qi.push(i*2+1);
            }
        }
    }


}

std::vector<std::string> ArbreContigu::explode(const std::string &str, char x)
{
    std::vector<std::string> result;
    std::istringstream in(str);
    std::string token;
    while(getline(in, token, x))
        result.push_back(token);
    return result;
}



std::vector<element> ArbreContigu::file_to_vector(const std::string &filename)
{
    std::vector<element> values;
    std::string line;
    std::ifstream file(filename);
    if(!file){
        std::cout << "Impossible d'ouvrir le fichier !" << std::endl;}
    else {
        while(getline(file,line)){
            element elem;
            std::vector<std::string> vect_temp = explode(line,';');
            if (vect_temp.size() == 1)
                elem.isnull = true;
            else
            {
                elem.isnull = false;
                elem.value = std::stoi(vect_temp[0]);
                elem.iterations = std::stoi(vect_temp[1]);
                elem.brix.setAx(std::stoi(vect_temp[2]));
                elem.brix.setOx(std::stoi(vect_temp[3]));
                elem.brix.setAo(std::stoi(vect_temp[4]));
                elem.brix.setOo(std::stoi(vect_temp[5]));
                elem.brix.setDefinie(vect_temp[6]=="1" ? true : false);
            }
            values.push_back(elem);
       }
   }

        file.close();
        return values;
}

void ArbreContigu::to_csv(std::string const & filename){
    std::fstream file;
    file.open (filename, std::fstream::trunc | std::fstream::out );
    if(!file)
        std::cout << "Impossible d'ouvrir le fichier !" << std::endl;
    else {
        for (auto elements : values){

            if (elements.isnull)
                file << "N" << std::endl;
            else {
                file << elements.value << ";"
                << elements.iterations << ";"
                << elements.brix.getAx() << ";"
                << elements.brix.getOx() << ";"
                << elements.brix.getAo() << ";"
                << elements.brix.getOo() << ";"
                <<elements.brix.getDefinie() << std::endl;
            }

        }
    }
    file.close();


}

Exemple 1



#include <vector>
#include <math.h>
#include <iostream>

    int main (){
    
    
        std::vector<int> a;
        a.reserve(pow(2,100));
        std::cout<<"..sucess.."<<std::endl;
    
    }

yes that also very strange for the 2 ^ 100 however this code returns me well sucess without any error

however in my conversion constructor I cannot make a reserve beyond 2 ^ 20 approximately

Aiwendil
  • 1
  • 1
  • It isn't shown what `tailletab` or how it is calculated. The most likely cause of the problem is that `tailletab` is uninitialized or a negative value. – François Andrieux Mar 11 '21 at 19:04
  • 4
    *"Meanwhile, I can initialize a vector of int size 2^100 without getting an error, so I'm a bit confused..."* That value likely exceeds what can be represented by `std::size_t`. I'm not sure how you generated such a number, but the result is likely not as big as you expect. – François Andrieux Mar 11 '21 at 19:06
  • Are you building a 32-bit or 64-bit application? – 1201ProgramAlarm Mar 11 '21 at 19:17
  • yes but it seems strange to me because the reservation works for 2 ^ 0 to 2 ^ 64 at least while in my convertion function it returns me bad allocation I don't understand how to fix it – Aiwendil Mar 11 '21 at 20:05

0 Answers0