je code actuellement une intelligence artificielle pour un jeu d'échec, je travaille actuellement sur la partie enregistrement/génération/chargement du cerveau à base de réseau de neurones et je bloque sur une erreur à la compilation.
Je découvre les outils sur le tas donc il peut y avoir plusieurs erreur ou de maladresses de ma part.
voici l'erreur qui survient à la ligne 130: "invalid types 'int[int]' for array subscript"
voici le code:
#include <iostream>
#include <fstream>
#include <string.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
using namespace std;
typedef struct
{
int nb_layers;
int nb_neurons;
int* connections;
}_brain;
_brain loadBrain()
{
//déclaration variables
int nb_layers, nb_neurons_max;
//déclaration pointeurs pour malloc()
int* p_int;
float*** p_p_p_float = NULL;
//ouverture du fichier en lecture binaire
FILE* brain_file;
brain_file = fopen("brain_file.bin" , "rb");
assert(brain_file);
//on lit le nombre de couches de neurones et on déclare un tableau de x couches de neurones
fread(&nb_layers , sizeof(int) , 1 , brain_file);
int nb_neurons[nb_layers];
//on lit la valeur des connections entre les neurones
fread(nb_neurons , sizeof(nb_neurons[0]) , sizeof(nb_neurons)/sizeof(nb_neurons[0]) , brain_file);
nb_neurons_max = 64;
for(int cnt1 = 1; cnt1 < nb_layers - 1; cnt1++)
if(nb_neurons[cnt1] > nb_neurons_max)
nb_neurons_max = nb_neurons[cnt1];
float connections[nb_layers - 1][nb_neurons_max][nb_neurons_max];
fread(connections , sizeof(connections) , 1 , brain_file);
//on ferme le fichier
fclose(brain_file);
//on stoque ces infos dans une structure
_brain brain;
p_int = (int*)malloc(nb_layers* sizeof(int));
if (p_int == NULL)
exit(0);
p_p_p_float = (float***)malloc(nb_layers* sizeof(float**));
if (p_p_p_float == NULL)
exit(0);
for (int cnt1 = 0 ; cnt1 < nb_layers ; cnt1++)
{
p_p_p_float[cnt1] = (float**)malloc(nb_neurons_max* sizeof(float*));
if (p_p_p_float[cnt1] == NULL)
exit(0);
for (int cnt2 = 0 ; cnt2 < nb_neurons_max ; cnt2++)
{
p_p_p_float[cnt1][cnt2] = (float*)malloc(nb_neurons_max* sizeof(float));
if (p_p_p_float[cnt1][cnt2] == NULL)
exit(0);
}
}
return brain;
}
_brain generateBrain()
{
//déclaration variables
int nb_layers, nb_neurons_max;
//déclaration pointeurs pour malloc()
int* p_int;
float*** p_p_p_float = NULL;
//ouverture du fichier en ecriture binaire
FILE* brain_file;
brain_file = fopen("brain_file.bin" , "wb");
assert(brain_file);
//on demande à l'utilisateur le nombre de couches et de neurones par couches
cout << "Number of layers:";
cin >> nb_layers;
nb_layers = nb_layers +2;
int nb_neurons[nb_layers];
nb_neurons[0] = 64;
nb_neurons[nb_layers - 1] = 1;
nb_neurons_max = 64;
for(int cnt1 = 1; cnt1 < nb_layers - 1; cnt1++)
{
cout << "Number of node in layer " << cnt1 << ": ";
cin >> nb_neurons[cnt1];
if(nb_neurons[cnt1] > nb_neurons_max)
nb_neurons_max = nb_neurons[cnt1];
}
//on crée les connections avec une valeur initiale de 0
float connections[nb_layers - 1][nb_neurons_max][nb_neurons_max];
for(int cnt1 = 1; cnt1 < nb_layers - 1; cnt1++)
for(int cnt2 = 0; cnt2 < nb_neurons_max; cnt2++)
for(int cnt3 = 0; cnt3 < nb_neurons_max; cnt3++)
connections[cnt1][cnt2][cnt3] = 0;
//on modifie connections actives avec une valeur aléatoire
for(int cnt1 = 1; cnt1 < nb_layers - 1; cnt1++)
for(int cnt2 = 0; cnt2 < nb_neurons[cnt1 - 1]; cnt2++)
for(int cnt3 = 0; cnt3 < nb_neurons[cnt1]; cnt3++)
connections[cnt1][cnt2][cnt3] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
//on enregistre les valeurs dans le fichier
fwrite(&nb_layers , sizeof(int) , 1 , brain_file);
fwrite(nb_neurons , sizeof(nb_neurons[0]) , sizeof(nb_neurons)/sizeof(nb_neurons[0]) , brain_file);
fwrite(connections , sizeof(connections) , 1 , brain_file);
fclose(brain_file);
//on crée une structure
_brain brain;
p_int = (int*)malloc(nb_layers* sizeof(int));
if (p_int == NULL)
exit(0);
p_p_p_float = (float***)malloc(nb_layers* sizeof(float**));
if (p_p_p_float == NULL)
exit(0);
for (int cnt1 = 0 ; cnt1 < nb_layers ; cnt1++)
{
p_p_p_float[cnt1] = (float**)malloc(nb_neurons_max* sizeof(float*));
if (p_p_p_float[cnt1] == NULL)
exit(0);
for (int cnt2 = 0 ; cnt2 < nb_neurons_max ; cnt2++)
{
p_p_p_float[cnt1][cnt2] = (float*)malloc(nb_neurons_max* sizeof(float));
if (p_p_p_float[cnt1][cnt2] == NULL)
exit(0);
}
}
//on stocke les valeurs dans la structure
brain.nb_layers = nb_layers;
for(int cnt1 = 0; cnt1 < nb_layers; cnt1++)
brain.nb_layers[cnt1] = nb_layers[cnt1];
return brain;
}
int main()
{
srand (static_cast <unsigned> (time(0)));
char choice;
_brain brain;
cout << "[L]oad brain_file" << endl << "[G]enerate a random brain_file" << endl << "[Q]uit program" << endl;
choice = _getch();
do
{
switch(choice)
{
case 'o':
brain = loadBrain();
break;
case 'g':
brain = generateBrain();
break;
default:
break;
}
}while(choice != 'o' && choice != 'g' && choice != 'q');
cout << brain.nb_layers;
return 0;
}
Ce que tu as écris, c'est du C. En C++, on utilise pas fread ni fwrite. Les tableaux sont de type std::vector ou std::array. On évite les pointeurs nu. L'allocation dynamique ne se fait pas avec malloc, mais via les pointeurs intelligent. La génération de nombre aléatoires se fait via les objets de l'entête <random>.
Concernant ton problèmes, les indices de tableau ne peuvent être négatif, donc utilise un type non signé.
Niveau fuite de mémoire, c'est les chutes du Niagara... Ce n'est pas trop grave, ça va sûrement planter très vite. Les OS ont une fâcheuse tendance à mettre une balle dans la tête des cerveaux qui déréférencent des pointeurs non initialisés...
Quand on peut éviter la seconde méthode, on le fait. Parce qu'on n'a pas envie de se taper des heures de boulot s'il suffit d'écrire du code correct.
Si ton prof pense qu'écrire du code inutilement compliqué (inutile parce qu'on peut faire la meme chose avec du code lisible et avec moins de risque de bugs), c'est très dommage pour toi. Tu feras partie, si tu veux continuer le C++ plus tard, de ceux qui ont dû réapprendre le C++ tout seul, parce qu'ils ont eu des mauvais cours.
Honnetement, je refuse les boulots où je dois bosser sur des codes comme ca. Si je ne fais pas cela en étant payé, tu imagines bien que j'ai encore moins envie de me taper ce genre de code bénévolement, juste pour compenser les errances d'un prof. Et j'imagine qu'on va être plusieurs à ne pas vouloir lire ton code.
Au pire, si tu n'as pas d'aide ici, demande sur le forum C ou a ton prof.
En fait, j'ai l'impression que les professeur de C++ (mais pas que ce langage) sont un peu comme les personnes politiques. Ils enseignent et prennent des décisions sans jamais avoir vécu ou penser à l'utiliser dans la vraie vie (cf. l'ignorance du SMIC et les prix des pains au chocolat).
Ce code est litéralement ce qu'un babouin aurait déféqué après avoir mangé des fruits pourris.
- Edité par markand 8 janvier 2019 à 9:17:51
git is great because Linus did it, mercurial is better because he didn't.
Et encore, on peut faire mieux qu'un std::array 2D, mais on s'en contentera pour l'instant.
Petite précision, les vector servent à faire des tableaux dont on veut pouvoir modifier la taille ? c'est ce que j'ai cru comprendre, du coup je ne vois pas l'utilité d'en utiliser sur la matrice du plateau de jeu.
PS je me suis renseigné mais c'est un peu flou pour moi.
Les RdN, c'est déjà complexe en soit -- pour calibrer, architecturer, entraîner, et au final obtenir des résultats j'entends. Le C++ aussi.
Mélanger les deux (sans passer par les abstractions qui marchent (matrices et vecteurs)), cela me parait assez casse gueule. Sans parler d'utiliser des RdN pour modéliser une IA d'échec. C'est extrêmement ambitieux -- à moins d'avoir déjà un modèle entraîné qu'il suffirait juste de jouer. Et même là, j'ai comme un gros doute.
Par curiosité, pourquoi ce choix de programme? Cela vient du prof, ou c'est personnel? Sur des approches IA totalement différentes (alpha-beta & cie) on s'attaque plutôt au tic-tac-toe et autre puissance 4 d'habitude.
Oui c'est complètement personnel, et je suis un fondu d'échec alors javais envie de faire ma propre IA, Je sais Que ça va rester un peu conceptuelle et que ce serait étonnant qu'elle arrive à un bon niveau sur un jeu aussi complexe mais je veux tenter le coup.
Et même si c'est casse gueule je pense que je peux m'en sortir, j'ai du mal sur tout ce qui est syntaxe... mais je me débrouille très bien en algo donc quand j'aurais passé la gestion d'enregistrement et de chargement du cerveau (c'est la première fois que je le fais, d'où mon code un peu farfelu), je devrais pouvoir m'en sortir.
J'ai corrigé le code du mieux que j'ai pu,
void putConnectionValue(unsigned int xbrain_layer, unsigned int xbrain_line, unsigned int xbrain_column, float connection_value)
{
brain.connections[(NB_NEURONS_MAX * NB_NEURONS_MAX * xbrain_layer) + (NB_NEURONS_MAX * xbrain_line) + xbrain_column] = connection_value;
}
Oups j'avais mal lu, quel est l'avantage de 'array' sur les tableaux ?
La taille est embarquée ==> pas besoin d'un paramètre supplémentaire pour les fonctions le manipulant. On peut le donner en paramètre par référence. Il ne se dégrade pas en pointeur nu. Il est thread-safe. Il est supporté par les algorithmes de la librairie standard. Il est supporté par la boucle for...each. Il fournit de multiples constructeurs. Ect ...
wow ça en fait ! du y a-t-il un avantage aux tableaux sur les array ?
Et j'ai un problème avec le generateBrain ou le saveBrain: tout se passe bien lors de l'enregistrement dans le fichier jusqu'à ce qu'on enregistre les valeurs dans le vector 'brain.connection' il n' a qu'un 0 dans le fichier
Oups j'avais mal lu, quel est l'avantage de 'array' sur les tableaux ?
a- Il ne se dégrade pas en pointeur nu. b- Il est thread-safe. c- Il est supporté par les algorithmes de la librairie standard. d- Il est supporté par la boucle for...each. e- Il fournit de multiples constructeurs.
?? Euh...
a- Cela est vrai, et est important
b- En quoi un tableau (statique ou dynamique) est-il plus thread-safe que std::array? (Il n'y a aucune différence, ni la moindre garantie dans aucun des deux, voire dans aucun conteneur standard)
c- Un pointeur dans un buffer modélise un itérateur à accès direct -- il y a bien longtemps, on disait même qu'il était un itérateur trivial. Je crois qu'il va gagner officiellement dans la taxinomie des conteneurs et des itérateurs la propriété de contiguïté (en fait c'est la propriété qui n'existait pas et qui après moult discussions finit par arriver sous une forme un peu restreinte -- et encore, j'ai un doute)
Donc, les tableaux sont parfaitement utilisables avec les algos standards
d- tout comme les tableaux statiques directement, et même les dynamiques au travers d'une couche gratuite à la `span`
e- Pas du tout. Il en fournit justement zéro, c'est le seul moyen pour lui donner des propriétés de POD et de permettre de le construire simplement depuis des initiliazer-lists.
> mais je me débrouille très bien en algo
Le problème est que les RdN, c'est pas de l'algo, c'est des maths. La partie algorithmique est très simple. Par contre la modélisation est bien complexe. Il y a des années, le Reinforcement Learning était plus en vogue pour ce genre de jeux. Depuis, on a compris qu'on n'avait pas besoin de fonctions de transfert sigmoidales, une simple fonction affine non continue suffit, et aussi que si on rajoute assez de couches de manière pas entièrement au hasard, on arrive à faire des choses sympas (-> Deep Learning)
e- Pas du tout. Il en fournit justement zéro, c'est le seul moyen pour lui donner des propriétés de POD et de permettre de le construire simplement depuis des initiliazer-lists.
Ops, mea culpa (habitude des vectors).
Mais bon pour résumer: Avantages std::array: Plein. Avantages tableaux: 1 seul.
Mouais. Non, je n'en citerais qu'un réel en plus du non downgrade en pointeur : il est copiable et a donc la même sémantique que l'on s'attend à trouver pour tout type valeur manipulé.
Avantage des tableaux statiques: en l'absence de `make_array`, ils sont DRY, pas besoin de se mouiller (désolé!) à répéter la taille lors des définitions de constantes -- ou pourquoi je n'utilise jamais les `std::array`
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
git is great because Linus did it, mercurial is better because he didn't.
Architecte logiciel - Software craftsmanship convaincu.
Discord NaN. Mon site.
Architecte logiciel - Software craftsmanship convaincu.
git is great because Linus did it, mercurial is better because he didn't.
Architecte logiciel - Software craftsmanship convaincu.
Architecte logiciel - Software craftsmanship convaincu.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C