Générer toute les parties possibles d'un jeu de morpion.

Générer toute les parties possibles d'un jeu de morpion. - Algo - Programmation

Marsh Posté le 15-09-2011 à 08:38:26    

Bonjour, je reposte cette requête, j'aurais besoin d'un coup de main pour générer toute les partie d'un morpion.
J'ai trouvé un bout de code, mais c'est du récursif, et j'ai du mal à m'en sortir avec.
 
J'ai besoin de lister les coup qui même aux parties gagnante et partie nulle, sous forme de N-uplet de 9 réels prenant pour valeur 0.0 pour les case vides, 1.0 pour le joueur un et -1.0 pour le joueur deux.
 
Si vous aviez un tuyau ?
S'il vous plaît,
Merci.

Reply

Marsh Posté le 15-09-2011 à 08:38:26   

Reply

Marsh Posté le 15-09-2011 à 11:13:19    

Ca serait pas plutôt "qui mènent aux parties gagnantes"?
 
J'avais développé un petit soft pour jouer aux allumettes et où l'ordinateur apprenait à jouer au début. C'était basé sur l'apprentissage par renforcement et on simulait x parties pour permettre à l'ordi d'apprendre et enregistrer les coups qui menaient à la victoire. C'était très efficace, d'autant plus que x était grand (par ex 1000 parties simulées) ;) Pas de récursivité, pas trop compliqué à programmer et très efficace...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 15-09-2011 à 14:35:43    

Bonjour rufo,...  
 
Mon objectif est de produire la totalité des partie coup par coup pour donner la liste à un réseau de neurones. Pour résoudre le tic-tac-toe par RdN
Donc, je doit trouver un algo pour lister les coup des différente partie.

Reply

Marsh Posté le 15-09-2011 à 16:26:37    

C'est juste le tic-tac-toe à 9 cases que tu veux?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 15-09-2011 à 16:56:33    

gilou a écrit :

C'est juste le tic-tac-toe à 9 cases que tu veux?
A+,


 
 
Oui, effectivement... Pourquoi ? [:dawa]

Reply

Marsh Posté le 15-09-2011 à 17:18:35    

De rien


---------------
last.fm
Reply

Marsh Posté le 15-09-2011 à 19:31:21    

Parce que c'était pas explicite: morpion -> nxn cases  
Le tic tac toe est un cas très particulier du morpion.
Ça doit pas être trop dur a générer, sachant qu'il n'y a que 8 ensembles de 3 sommets gagnants et que le nombre de parties est borné par 9! = 362880.
A+,


Message édité par gilou le 15-09-2011 à 19:32:11

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 15-09-2011 à 20:21:11    

Backtracking ? C'est sympa pour bruteforcer :o


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 15-09-2011 à 23:36:21    

Tiens, en perl, un petit programme qui génère les 255168 parties possibles (j’arrête la partie dès qu'on a un gagnant).

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Algorithm::Permute;
  5. use List::MoreUtils ('uniq');
  6.  
  7. my $winning_pattern = "1.*2.*3";
  8. $winning_pattern .= "|1.*4.*7";
  9. $winning_pattern .= "|1.*5.*9";
  10. $winning_pattern .= "|2.*5.*8";
  11. $winning_pattern .= "|3.*5.*7";
  12. $winning_pattern .= "|3.*6.*9";
  13. $winning_pattern .= "|4.*5.*6";
  14. $winning_pattern .= "|7.*8.*9";
  15.  
  16. my (@array,@first, @second, @result);
  17. my $p = new Algorithm::Permute([1..9]);
  18. while (@array = $p->next) {
  19.  my $a;
  20.  $a = 0;
  21.  @first  = grep {$a^=1} @array;
  22.  $a = 1;
  23.  @second = grep {$a^=1} @array;
  24.  
  25.  $_ = join '', sort @first[0..2];
  26.  if (/$winning_pattern/) {
  27.    push @result, join(' ', @array[0..4])." +1.0";
  28.  }
  29.  else {
  30.    $_ = join '', sort @second[0..2];
  31.    if (/$winning_pattern/) {
  32.      push @result, join(' ', @array[0..5])." -1.0";
  33.    }
  34.    else {
  35.      $_ = join '', sort @first[0..3];
  36.      if (/$winning_pattern/) {
  37.     push @result, join(' ', @array[0..6])." +1.0";
  38.      }
  39.      else {
  40.     $_ = join '', sort @second;
  41.     if (/$winning_pattern/) {
  42.       push @result, join(' ', @array[0..7])." -1.0";
  43.     }
  44.     else {
  45.       $_ = join '', sort @first;
  46.       if (/$winning_pattern/) {
  47.         push @result, join(' ', @array)." +1.0";
  48.       }
  49.       else {
  50.         push @result, join(' ', @array)." 0.0";
  51.       }
  52.     }
  53.      }
  54.    }
  55.  }
  56. }
  57.  
  58.  
  59. @result = sort @result;
  60. @result = uniq @result;
  61. print join("\n", @result);


Ça prend environ 1mn sur ma vieille bécane pour faire l'ensemble des parties possibles. A rediriger dans un fichier texte (de 5 697 502 octets).
Le principe de l'algo:
Je fais un pattern des combinaisons gagnantes ordonnées (il y en a 8).
Algorithm::Permute([1..9]) va generer toutes les permutations de 1..9.
Pour chaque permutation, je chope les valeurs d'indice pair (donc les coups du premier joueur) rangées dans la liste first et les autres dans la liste second.
Ensuite je regarde:
si les 3 premiers coups du 1er joueur contienne un pattern gagnant
si les 3 premiers coups du 2eme joueur contienne un pattern gagnant
si les 4 premiers coups du 1er joueur contienne un pattern gagnant
si les 4 premiers coups du 2eme joueur contienne un pattern gagnant
si les 5 premiers coups du 1er joueur contienne un pattern gagnant
pour chercher si une liste de coups contiennent un pattern gagnant, je peux chercher sur la liste ordonnée, et donc utiliser mon pattern des combinaisons gagnantes ordonnées.
A la fin, je réordonne pour virer les doublons (l'algo est en force brute sur toutes les permutations, donc on a des doublons engendrés par des permutations ayant un même début gagnant et une suite de coups (virtuels) après que la partie ait été gagnée qui diffèrent).
A+,

Message cité 1 fois
Message édité par gilou le 15-09-2011 à 23:52:11

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 07:55:44    

Bonjour,
 

WiiDS a écrit :

Backtracking ? C'est sympa pour bruteforcer :o


C'est quoi le backtracking ?

gilou a écrit :

Tiens, en perl,
 .../...
 
A+,


 
Merci Gliou. Excuse moi, je me suis couché tôt hier, j'essuyais déjà une nuit blanche.
 

Reply

Marsh Posté le 16-09-2011 à 07:55:44   

Reply

Marsh Posté le 16-09-2011 à 08:07:07    

Arff, ton code est incomplet, il manque l'algo de Permute, il me faudrait Permute...
Ou alors, Je serais intéressé de savoir comment tu initialise un morpion, et savoir quelle permutation tu effectues.


Message édité par Profil supprimé le 16-09-2011 à 08:07:17
Reply

Marsh Posté le 16-09-2011 à 10:31:27    


http://en.wikipedia.org/wiki/Backtracking
 
Je peux essayer de t'implémenter en C si tu ne vois pas trop le concept. Par contre, ça serait probablement en récursif. (même si ça doit être jouable en itératif mais bon).
 
C'est un algo assez générique qui n'est finalement qu'un bruteforce intelligent. Après, et après réflexion, je me demande si c'est vraiment utile dans ce cas, et je pense que la solution de gilou doit être la meilleure :D


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 16-09-2011 à 10:39:28    

Ouais, te casse pas la tête, si Gilou veux bien produire l'algo de permutation.
 
 
Ou alors, il faudrais que j'arrive à dé-récursiver cet algo.
 

Code :
  1. procedure Jouer(P : in out Partie; J1 : Joueur) is
  2.      Fin : Boolean;
  3.      J2 : Joueur;
  4.   begin
  5.      Evaluer(P, Fin);
  6.  
  7.      if Fin then
  8.         return ;
  9.      end if;
  10.  
  11.      if J1 = TOTO then
  12.         J2 := TITI;
  13.      else
  14.         J2 := TOTO;
  15.      end if;
  16.  
  17.      for I in P.Grille'Range(1) loop
  18.         for J in P.Grille'Range(2) loop
  19.            if P.Grille(I,J) = VIDE then
  20.               P.Grille(I,J) := J1;
  21.               Jouer(P,J2);
  22.               P.Grille(I,J) := VIDE;
  23.            end if;
  24.         end loop;
  25.      end loop;
  26.   end Jouer;
  27.  
  28.   P : Partie := ((others => (others => VIDE)),0,0,0);
  29. begin
  30.   Jouer(P, TOTO);
  31. end;

Reply

Marsh Posté le 16-09-2011 à 11:11:10    

D'après ce que j'ai compris dans le code de Gilou, mais je peux me tromper parce que je ne connais pas le Perl, "Permutation" semble être une fonction d'une lib Perl nommée "Algorithm"


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 16-09-2011 à 11:29:39    

Ah, merci WIIDS.
 
J'ai installé la bibliothèque en question, mais rien à faire, perle ne trouve pas la bibliothèque la ou elle est pourtant, malgré la présence du chemin dans les chemins de recherche de perl.


Message édité par Profil supprimé le 16-09-2011 à 11:29:51
Reply

Marsh Posté le 16-09-2011 à 11:33:07    

permute.pm est absent en fait de Algorithm.

Reply

Marsh Posté le 16-09-2011 à 11:49:44    

Je pense que tu seras intéressé par ce lien: http://search.cpan.org/~edpratomo/ [...] Permute.pm


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 16-09-2011 à 12:41:17    

Exactement, c'est implémenté dans un mix de C et  de liaison perl.
 
Je pensais que ce qui intéressait Jovalise était juste la liste générée.
 
S'il veut un algo (plus lent) pour les permutations, voici un exemple, pas optimal, car adapté d'un algo plus générique.
 
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;
  5.  
  6. sub permute_init {
  7.  my $digits = shift;
  8.  return([ [[], $digits] ]);
  9. }
  10.  
  11. sub permute_next {
  12.  my $state = shift;
  13.  my ($left, $right);
  14.  my ($newleft, $newright);
  15.  my ($val, $item, $i, $done);
  16.  
  17.  $item = pop @$state;
  18.  
  19.  if (defined($item)) {
  20.    ($left, $right) = @$item;
  21.  
  22.     while (!$done) {
  23.       if (scalar(@$right) > 0) {
  24.      foreach $i (0 .. (scalar(@$right) - 1)) {
  25.        $newright  = [];
  26.        $newleft   = [];
  27.        @$newright = @$right;
  28.        @$newleft  = @$left;
  29.        push(@$newleft, splice(@$newright, $i, 1));
  30.        unshift(@$state, [$newleft, $newright]);
  31.      }
  32.       }
  33.  
  34.       # if(scalar(@$left) > 0){ # avec ce test ci, on a toutes les combinaisons de 1, 2, ... n chiffres
  35.       if (scalar(@$right) == 0) { # avec ce test la, on a toutes les combinaisons de n chiffres
  36.       $val = $left;
  37.       $done = 1;
  38.     }
  39.       else {
  40.      $item = pop(@$state);
  41.      ($left, $right) = @$item;
  42.       }
  43.     }
  44.  }
  45.  return ($state, $val);
  46. }
  47.  
  48. my $digits = [1..5]; #exemple sur 1..5 ici
  49. my $val;
  50. my $state  = &permute_init($digits);
  51. ($state, $val) = &permute_next($state);
  52. while (defined($val)) {
  53.  print "@$val\n";
  54.  ($state, $val) = &permute_next($state);
  55. }


 
A+,

Message cité 1 fois
Message édité par gilou le 16-09-2011 à 12:42:52

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 12:42:34    

Il suffit de l'installer avec ppm (sous active state) ou CPAN (sous un autre système).
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 12:57:50    

Merci Gilou, oui, c'est le résultat que je veux, peu importe la méthode.
 
Je suis en cours de réeinstall système, je vous dis après si mon réseau de neurones fonctionne.

Reply

Marsh Posté le 16-09-2011 à 16:53:03    

gilou a écrit :

Exactement, c'est implémenté dans un mix de C et  de liaison perl.
 
Je pensais que ce qui intéressait Jovalise était juste la liste générée.
 
 
A+,


 
Bon, c'est pas le bon résultat.  :whistle:

Reply

Marsh Posté le 16-09-2011 à 16:56:39    

A oui, et je sais pas si sa vas t'embêter, mais il me faux chaque ligne écrite en double.
Pas de signe au positifs et zero et une espace avant un positif ou zero.
 
Merci Gilou.  :jap:
 
edit  :heink:  :jap:
 
 
Du coup, je sais pas si c'est pas moi qui me suis mal exprimé....
 
Je souhaite la liste des plateau à chaque coup.
 
genre :
 
 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
-1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
-1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
 
Ah oui sauf le plateau de début qui doit être inséré simplement au début de chaque parti.
En espérant que c'est clair.

Message cité 1 fois
Message édité par Profil supprimé le 16-09-2011 à 17:05:07
Reply

Marsh Posté le 16-09-2011 à 17:27:33    

Ceci dit, si quelqu'un avais un algo en français ce serait pas mal.
 

Code :
  1. @$


C'est une nataserie...


Message édité par Profil supprimé le 16-09-2011 à 17:30:13
Reply

Marsh Posté le 16-09-2011 à 18:05:12    

Non! Les lignes 2 et 3 et 4 et 5 de ton exemple sont identiques (tu as dit que tu les voulait en double), mais pas la première, je ne comprends donc pas ta notation. Ou alors la première ligne n'est pas double, et elle seule?
Et comment explicites tu la victoire?
Chaque ligne contient la liste des cases (1) jouées dans l'ordre joué (et s’arrête des qu'un joueur a gagné) suivie de +1.0 si le 1er joueur a gagné, -1.0 si le 2e a gagné, et 0.0 si le match est nul.
C'est pas dur a transformer dans un autre format, encore faut il que tu expliques clairement quel format de sortie tu désires.
 
(1): La numérotation des cases est comme d'hab
123
456
789
A+,


Message édité par gilou le 16-09-2011 à 18:12:58

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 18:24:35    

Merci Gilou d'abord.
 
La première ligne est le plateau de départ de partie, donc il apparaît une seule fois à chaque début de partie.
Mais toute les autre doive êtres en double.
 
Ok pour le (1)
 
La notation c'est le tableau de taille (1..9) de Status_type (Empty, White, black) { " 0.0" pour Empty, "-1.0" pour black, " 1.0" pour white}.
 
la première ligne le plateau vide
à la seconde je joue au milieu
je répète la ligne
à la troisième, je joue dans un coin.
je répète la ligne

Reply

Marsh Posté le 16-09-2011 à 18:26:54    

Et même, si tu peux me mettre les partie gagné par black et white et les nulle dans trois fichiers distinc, t'est un as. [:powa]

Reply

Marsh Posté le 16-09-2011 à 18:55:49    


 

Code :
  1. import copy
  2.  
  3. def DisplayBoard( Board ):
  4.    print ":--:--:--:"
  5.    for line in Board:
  6.        s = ":"
  7.        for cell in line:
  8.            s = "{0}{1:02d}:".format(s, cell )
  9.        print s
  10.        print ":--:--:--:"
  11.  
  12.  
  13. def DisplayList( BoardList ):
  14.    for i, Board in enumerate( BoardList ):
  15.        print "Move :", i
  16.        DisplayBoard( Board )
  17.        
  18. def DisplayVictory( PlayerId, BoardList ):
  19.    print "Player {0}, won in {1} move(s) :".format( PlayerId, len( BoardList ) )
  20.    #DisplayList( BoardList )
  21.    DisplayBoard( BoardList[ -1 ] )
  22.  
  23. def DisplayDraw( BoardList ):
  24.    print "Draw in {0} move(s) :".format( len( BoardList ) )
  25.    #DisplayList( BoardList )
  26.    DisplayBoard( BoardList[ -1 ] )
  27.  
  28. def IsVictory( Board, PlayerId, i, j ):
  29.    Height = len( Board )
  30.    Width = Height
  31.    iSumHeight = 0
  32.    iSumWidth = 0
  33.    iSumDiag1 = 0
  34.    iSumDiag2 = 0
  35.    for x in xrange( Height ):
  36.        iSumHeight += Board[ x ][ j ]
  37.        iSumWidth += Board[ i ][ x ]
  38.        iSumDiag1 += Board[ x ][ x ]
  39.        iSumDiag2 += Board[ -x+1 ][ x ]
  40.    Target = ( PlayerId * Height )
  41.    if ( iSumHeight == Target ) or ( iSumWidth == Target ) or ( iSumDiag1 == Target ) or ( iSumDiag2 == Target ):
  42.        return True
  43.    return False
  44.  
  45. def IsDraw( Board ):
  46.    for line in Board:
  47.        for cell in line:
  48.            if cell == 0:
  49.                return False
  50.    return True
  51.  
  52. def NextMoves( BoardList, PlayerId ):
  53.    NextBoard = copy.deepcopy( BoardList[ -1 ] )
  54.    for i, line in enumerate( NextBoard ):
  55.        for j in xrange( len( line ) ):
  56.            if NextBoard[i][j] == 0:
  57.                NextBoard[i][j] = PlayerId
  58.                BoardList.append( NextBoard )
  59.                if IsVictory( NextBoard, PlayerId, i, j ):
  60.                    DisplayVictory( PlayerId, BoardList )
  61.                else:
  62.                    if IsDraw( NextBoard ):
  63.                        DisplayDraw( BoardList )
  64.                    else:
  65.                        NextMoves( BoardList, -PlayerId )
  66.                BoardList = BoardList[:-1]
  67.                NextBoard[i][j] = 0
  68.        
  69.  
  70. DefaultBoard = [ [0, 0, 0], [0, 0, 0], [0, 0, 0] ]
  71. NextMoves( [ DefaultBoard ], 1 )


 
vu que python, c'est lisible, tu devrais sans trop de problème pouvoir adapter ca pour que ca te sorte des fichiers distincts.
J'ai laissé en commentaire les appels à la fonction qui sort la liste de tous les coups pour arriver à la solution, le cas échéant.
 
Edit : vu que je repose entièrement sur l'état initial, tu dois pouvoir sans problème commencer par un tableau à 10 éléments si ca te chante :o


Message édité par theshockwave le 16-09-2011 à 18:57:20

---------------
last.fm
Reply

Marsh Posté le 16-09-2011 à 19:18:45    


 
Il suffit de remplacer la derniere ligne
print join("\n", @result);
par

Code :
  1. foreach (@result) {
  2.  jovalisate(\$_);
  3. }
  4.  
  5. sub jovalisate {
  6.  my $string = shift;
  7.  my @list = split /\s+/, $$string;
  8.  my $winner = pop @list;
  9.  my @display = ("0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0" );
  10.  print "@display\n";
  11.  my $coup = 1;
  12.  foreach my $i (@list) {
  13.    $display[$i - 1] = $coup++%2 ? "1.0" : "-1.0";
  14.    print "@display\n";
  15.    print "@display\n";
  16.  }
  17.  print "$winner\n"; # a virer si on veut pas la statut du gagnant.
  18. }


 
A+,


Message édité par gilou le 16-09-2011 à 19:19:11

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 19:32:56    

Yep, merci Gilouuuu !
 
theshockwave, je le prend ou l'import copy ?
 
 
J'ai lancé le réseau avec toute des combinaison je vous tien au courant.

Reply

Marsh Posté le 16-09-2011 à 19:54:25    

Bon, ça passe, j'ai 4567104 enregistrement qui point sur chaque coup en double, avec le plateux de départ en double également finalement, j'ai réfléchis un poil plus et en fait il le falait en double aussi. Bref,
Une époque toute les deux minute,
RMS_Error, l'indice d'erreur, est à 7.34923772157265640E-02, et j'ai fixé la limite de RMS_Error à 0.050.
 
Le début de la séquence et pas prometteuse cependant.
 


RMS_Error =>  7.34923772157265640E-02
RMS_Error =>  7.34896186333247645E-02
RMS_Error =>  7.34896204251504258E-02
RMS_Error =>  7.34896215082855019E-02
RMS_Error =>  7.34896223347958675E-02


 
Je vais recommencer au cas où.

Reply

Marsh Posté le 16-09-2011 à 20:01:17    

Bon, le programme en perl hacké vite fait et sans doute pas optimal

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Algorithm::Permute;
  5. use List::MoreUtils ('uniq');
  6.  
  7. my $winning_pattern = "1.*2.*3";
  8. $winning_pattern .= "|1.*4.*7";
  9. $winning_pattern .= "|1.*5.*9";
  10. $winning_pattern .= "|2.*5.*8";
  11. $winning_pattern .= "|3.*5.*7";
  12. $winning_pattern .= "|3.*6.*9";
  13. $winning_pattern .= "|4.*5.*6";
  14. $winning_pattern .= "|7.*8.*9";
  15.  
  16. my (@array,@first, @second, @winfirst, @winsecond, @winnone);
  17. my $p = new Algorithm::Permute([1..9]);
  18. while (@array = $p->next) {
  19.  my $a;
  20.  $a = 0;
  21.  @first  = grep {$a^=1} @array;
  22.  $a = 1;
  23.  @second = grep {$a^=1} @array;
  24.  
  25.  $_ = join '', sort @first[0..2];
  26.  if (/$winning_pattern/) {
  27.    push @winfirst, join(' ', @array[0..4]);
  28.  }
  29.  else {
  30.    $_ = join '', sort @second[0..2];
  31.    if (/$winning_pattern/) {
  32.      push @winsecond, join(' ', @array[0..5]);
  33.    }
  34.    else {
  35.      $_ = join '', sort @first[0..3];
  36.      if (/$winning_pattern/) {
  37.     push @winfirst, join(' ', @array[0..6]);
  38.      }
  39.      else {
  40.     $_ = join '', sort @second;
  41.     if (/$winning_pattern/) {
  42.       push @winsecond, join(' ', @array[0..7]);
  43.     }
  44.     else {
  45.       $_ = join '', sort @first;
  46.       if (/$winning_pattern/) {
  47.         push @winfirst, join(' ', @array);
  48.       }
  49.       else {
  50.         push @winnone, join(' ', @array);
  51.       }
  52.     }
  53.      }
  54.    }
  55.  }
  56. }
  57.  
  58.  
  59. @winfirst = sort @winfirst;
  60. @winfirst = uniq @winfirst;
  61. open(my $fh, '>', 'winfirst.txt') or die "cannot open winfirst.txt for writing: $!";
  62. foreach (@winfirst) {
  63.  jovalisate($fh, \$_);
  64. }
  65. close ($fh);
  66.  
  67. @winsecond = sort @winsecond;
  68. @winsecond = uniq @winsecond;
  69. open($fh, '>', 'winsecond.txt') or die "cannot open winsecond.txt for writing: $!";
  70. foreach (@winsecond) {
  71.  jovalisate($fh, \$_);
  72. }
  73. close ($fh);
  74.  
  75. @winnone = sort @winnone;
  76. @winnone = uniq @winnone;
  77. open($fh, '>', 'winnone.txt') or die "cannot open winnone.txt for writing: $!";
  78. foreach (@winnone) {
  79.  jovalisate($fh, \$_);
  80. }
  81. close ($fh);
  82.  
  83. sub jovalisate {
  84.  my $fh = shift;
  85.  my $string = shift;
  86.  my @list = split /\s+/, $$string;
  87.  my @display = ("0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "0.0" );
  88.  print $fh "@display\n";
  89.  my $coup = 1;
  90.  foreach my $i (@list) {
  91.    $display[$i - 1] = $coup++%2 ? "1.0" : "-1.0";
  92.    print $fh "@display\n";
  93.    print $fh "@display\n";
  94.  }
  95.  # print $fh "\n"; # décommenter si on veut séparer chaque partie par une ligne blanche
  96. }


En sortie
winfirst.txt 87 Mo, winsecond.txt 50 Mo et winnone.txt 33 Mo.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 16-09-2011 à 20:44:01    

Yer !
 
Merci Gilou. T'es un as.
 
J'ai lancé deux process, un avec la totalité des combinaisons avec une couche cachée de 9 neurones et un autre auquel je vais donnez la totalité mais fichier par fichier avec une couche cachés de 81 neurones.


Message édité par Profil supprimé le 16-09-2011 à 20:46:06
Reply

Marsh Posté le 17-09-2011 à 00:03:30    


copy, c'est un module standard de python.
Si tu as python d'installé, un simple "python mon_fichier.py" suffit à te fournir tous les résultats que tu veux


---------------
last.fm
Reply

Marsh Posté le 17-09-2011 à 17:32:25    

Ok merci theshockwave.
 
Je vous avais dit que je vous tiendrais au courant, ben ça fonctionne pas pour le moment.
 
Pas moyen de jouer au morpion, ne serais-ce qu'une partie, avec mon réseau de neurones.

Reply

Marsh Posté le 17-09-2011 à 18:00:12    


 
Renomme le Corky  [:mqnu:3]


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 17-09-2011 à 18:05:07    

Si vous souhaitez tester vous même le Tic-Tac-Toe contre un réseaux de neurone... Voici deux sources, Main et tictactoe qui implémente un tel processus.
Le réseau de neurones est fourni par une bibliothèque externe.
Les deux programmes dépende de la bibliothèque PragmARC (j'ai une version avec FannAda si vous souhaitez)
 
 
Main, le générateur de Réseau de neurones.

Code :
  1. with PragmARC.Ansi_Tty_Control;         use PragmARC.Ansi_Tty_Control;
  2. with PragmARC.REM_NN_Wrapper;           use PragmARC, PragmARC.REM_NN_Wrapper;
  3. with PragmARC.Math.Functions;
  4.  
  5. with Ada.Text_Io;
  6. use Ada;
  7. procedure Main is
  8.  
  9.  
  10.   package Real_Io is new Text_Io.Float_Io(Real);
  11.   use Real_Io;
  12.   package Real_Math is new PragmARC.Math.Functions (Supplied_Real => Real);
  13.  
  14.   Num_Inputs    : constant := 9;
  15.   Num_Outputs   : constant := 9;
  16.   Num_Hiddens   : constant := 9;
  17.  
  18.  
  19.   Reuse_Network : Boolean  := False;
  20.  
  21.   type Register_Type is array (1..Num_Inputs) of Float;
  22.  
  23.   type Game_Type is array (Positive range <> ) of access Register_Type;
  24.  
  25.   Games : Game_Type(1..992) := (others => new Register_Type ' (others => 0.0));
  26.  
  27.   Num_Patterns  : positive  := Games'Length/2;
  28.  
  29.  
  30.  
  31.   procedure Get_Input (Pattern : in Positive;
  32.                        Input : out Node_Set;
  33.                        Desired : out Node_Set) is
  34.   begin
  35.      for I in 1..9 loop
  36.         Input(I)  := Real(Games(Pattern*2-1)(I));
  37.         Desired(I) := Real(Games(Pattern*2)(I));
  38.      end loop;
  39.   end Get_Input;
  40.  
  41.   Char : Character;
  42.   Prob : Register_Type :=  Games(1).all;
  43.  
  44.   package My_Float_Io is new Ada.Text_Io.Float_Io(Float);
  45.   use My_Float_Io;
  46.   Game_file : Text_Io.File_Type;
  47.   Game_File_Name : constant String := "winsecond.txt";
  48.  
  49. begin
  50.   Text_Io.Open(Game_File, Text_Io.In_File, Game_File_Name);
  51.   for I in Games'Range loop
  52.      for j in 1..9 loop
  53.         My_Float_Io.Get(Game_File, games(I)(J));
  54.         --My_Float_Io.Put(Games(I)(J));
  55.      end loop;
  56.      --Text_Io.New_Line;
  57.   end loop;
  58.   Text_Io.Put_Line("Press Enter to continue" );
  59.   Text_Io.Get_Immediate(Char);
  60.   declare
  61.      package Morpion_NN is new Rem_NN(Num_Inputs,
  62.                                       Num_Hiddens,
  63.                                       Num_Outputs,
  64.                                       Num_Patterns,
  65.                                       not Reuse_Network,
  66.                                       False,
  67.                        True,
  68.                                       Get_Input => Get_input);
  69.      
  70.      
  71.      Max_Epochs : constant := 1_000_000;
  72.      RMS_Error  : Real := 1.0;
  73.      Response   : Node_Set(1..Num_Outputs);
  74.      Desired    : Node_Set(1..Num_Outputs);
  75.      Error      : Real := 0.0;
  76.      Converged  : Real := 0.055;
  77.   begin
  78.      for All_Epochs in 1..Max_Epochs loop
  79.  
  80.         for Pattern in 1..Games'length/2 loop
  81.            Morpion_NN.Train;
  82.            Morpion_NN.Respond (Pattern, Response);
  83.            for I in 1..9 loop
  84.               Desired(I) := Real(Games(Pattern*2)(I));
  85.            end loop;
  86.  
  87.            for I in Response'Range loop
  88.               Error :=
  89.                 Error + (Desired(I) - Response(i) );
  90.            end loop;
  91.            RMS_Error := RMS_Error + ((Error/Real(Response'Length)) ** 2);
  92.            Error := 0.0;
  93.         end loop;
  94.         RMS_Error :=
  95.           Real_Math.Sqrt(RMS_Error / Real (Games'length/2)) ;
  96.         exit when RMS_Error <= Converged;
  97.         Text_Io.Put("RMS_Error => " );
  98.         Real_Io.Put(RMS_Error);
  99.  
  100.         Text_Io.New_Line;
  101.      end loop;
  102.      Morpion_NN.Save_Weights;
  103.      Reuse_Network := True;
  104.  
  105.   end;
  106.  
  107. end Main;


 
 
Tictactoe, l'exploitation du réseaux de neurone, pour jouer contre la machine.

Code :
  1. with PragmARC.Ansi_Tty_Control;         use PragmARC.Ansi_Tty_Control;
  2. with PragmARC.REM_NN_Wrapper;           use PragmARC, PragmARC.REM_NN_Wrapper;
  3.  
  4. with Text_Io;
  5. use Text_Io;
  6.  
  7. procedure Tictactoe is
  8.        
  9.   task Monitor is
  10.      entry New_Game;
  11.      entry Receive(Char : in Character; Game_Over : out boolean);
  12.      entry Halt;
  13.   end Monitor;
  14.  
  15.  
  16.   Nc : constant Integer := 3;
  17.  
  18.   type Joueur is (E, X, O);
  19.   type Une_Grille is array (1..Nc,1..Nc) of Joueur;
  20.          
  21.   type Partie is record
  22.      Grille : Une_Grille;
  23.   end record;
  24.  
  25.  
  26.   function Test_Ligne(G : Une_Grille) return Joueur;
  27.   function Test_Colone(G : Une_Grille) return Joueur;
  28.   function Test_Diagonale(G : Une_Grille) return Joueur;
  29.   function Match_Nul(G : Une_Grille) return Boolean;
  30.   procedure Evaluer(P : in Partie; Fin : out Boolean; Win : out joueur);
  31.  
  32.   function Test_Ligne(G : Une_Grille) return Joueur is
  33.   begin
  34.      for N in G'Range(1) loop
  35.         if G(N,1) /= E and G(N,1) = G(N,2) and G(N,2) = G(N,3) then
  36.            return G(N,1);
  37.         end if;
  38.      end loop;
  39.      return E;
  40.   end Test_Ligne;
  41.  
  42.   function Test_Colone(G : Une_Grille) return Joueur is
  43.   begin
  44.      for N in G'Range(2) loop
  45.         if G(1,N) /= E and G(1,N) = G(2,N) and G(2,N) = G(3,N) then
  46.            return G(1,N);
  47.         end if;
  48.      end loop;
  49.      return E;
  50.   end Test_Colone;
  51.  
  52.   function Test_Diagonale(G : Une_Grille) return Joueur is
  53.      C : Joueur := G(2,2);
  54.   begin
  55.      if C /= E then
  56.         if (C = G(1,1) and C = G(3,3)) or (C = G(1,3) and C = G(3,1)) then
  57.           return C;
  58.         end if;
  59.      end if;
  60.      return E;
  61.   end Test_Diagonale;
  62.  
  63.   function Match_Nul(G : Une_Grille) return Boolean is
  64.   begin
  65.      for I in G'Range(1) loop
  66.         for J in G'Range(2) loop
  67.            if G(I,J) = E then
  68.               return FALSE;
  69.            end if;
  70.         end loop;
  71.      end loop;
  72.      return TRUE;
  73.   end Match_Nul;
  74.  
  75.   procedure Evaluer(P : in Partie; Fin : out Boolean; Win : out joueur) is
  76.      Gagnant : Joueur := E;
  77.   begin
  78.      Gagnant := Test_Ligne(P.Grille);
  79.      if (Gagnant = X) then
  80.         --P.Toto_Gagne := P.Toto_Gagne + 1;
  81.         Fin := TRUE;    
  82.      Win := X;
  83.         return;
  84.      elsif (Gagnant = O) then
  85.         --P.Titi_Gagne := P.Titi_Gagne + 1;
  86.         Fin := TRUE;
  87.      Win := O;
  88.         return ;
  89.      end if;
  90.  
  91.      Gagnant := Test_Colone(P.Grille);
  92.      if (Gagnant = X) then
  93.         --P.Toto_Gagne := P.Toto_Gagne + 1;
  94.         Fin := TRUE;
  95.      Win := X;
  96.         return ;
  97.      elsif (Gagnant = O) then
  98.         --P.Titi_Gagne := P.Titi_Gagne + 1;
  99.         Fin := TRUE;
  100.      Win := O;
  101.         return ;
  102.      end if;
  103.  
  104.      Gagnant := Test_Diagonale(P.Grille);
  105.      if (Gagnant = X) then
  106.         --P.Toto_Gagne := P.Toto_Gagne + 1;
  107.         Fin := TRUE;
  108.      Win := X;
  109.         return ;
  110.      elsif (Gagnant = O) then
  111.         --P.Titi_Gagne := P.Titi_Gagne + 1;
  112.         Fin := TRUE;
  113.      Win := O;
  114.         return ;
  115.      end if;
  116.  
  117.      Fin := Match_Nul(P.Grille);
  118.  
  119.      if Fin then
  120.         --P.Match_Nul := P.Match_Nul + 1;
  121.      Win := E;
  122.      end if;
  123.  
  124.   end Evaluer;
  125.  
  126.   Num_Inputs    : constant := 9;
  127.   Num_Outputs   : constant := 9;
  128.   Num_Hiddens   : constant := 9;
  129.  
  130.   subtype Register_Type is Node_set(1..Num_Inputs);
  131.   package My_Float_Io is new Text_Io.Float_Io(real);
  132.   use My_Float_Io;
  133.   Reuse_Network : Boolean  := True;
  134.  
  135.   procedure Self(Grille : in out Une_Grille) is
  136.      Prob : Register_Type :=  (others => 0.0);
  137.   begin
  138.      
  139.      for I in Grille'Range(1) loop
  140.      for J in Grille'range(2) loop
  141.         if Grille(I, J) = X then
  142.            prob((3*(I-1))+J) := 1.0;
  143.         elsif Grille(I, J) = O then
  144.            prob((3*(I-1))+J) := -1.0;
  145.         else
  146.            prob((3*(I-1))+J) := 0.0;
  147.         end if;
  148.      end loop;
  149.      end loop;
  150.      Put("Entree : " );
  151.      for I in Prob'Range loop
  152.      Put(Prob(I));
  153.      end loop;
  154.      New_Line;
  155.      declare
  156.               
  157.     
  158.      procedure Get_Input (Pattern : in Positive;
  159.                   Input : out Node_Set;
  160.                   Desired : out Node_Set) is
  161.      begin
  162.         for I in 1..9 loop
  163.            Input(I)  := Real(prob(I));
  164.         end loop;
  165.         Desired := (others => 0.0);
  166.      end Get_Input;
  167.     
  168.     
  169.      package Morpion_NN is new Rem_NN(Num_Inputs,
  170.                       Num_Hiddens,
  171.                       Num_Outputs,
  172.                       1,
  173.                       not Reuse_Network,
  174.                       False,
  175.                       True,
  176.                       Get_Input => Get_input);
  177.      Response : Node_Set(1..Num_Inputs);
  178.      begin
  179.      Morpion_NN.Respond (1, Response);
  180.      for K in Response'Range loop
  181.         if Response(K) >= 0.25 then
  182.            Response(K) := 1.0;
  183.         elsif Response(K) <= -0.25 then
  184.            Response(K) := -1.0;
  185.         else
  186.            Response(K) := 0.0;
  187.         end if;
  188.      end loop;    
  189.      Put("Sortie : " );
  190.      for I in response'Range loop
  191.         Put(response(I));
  192.      end loop;
  193.      for I in Grille'Range(1) loop
  194.         for J in Grille'range(2) loop
  195.            if response((3*(I-1))+J) = 1.0 then
  196.           Grille(I, J) := X;
  197.            elsif response((3*(I-1))+J) = -1.0 then
  198.           Grille(I, J) := O;
  199.            else
  200.           Grille(I, J) := E;
  201.            end if;
  202.         end loop;
  203.      end loop;    
  204.     
  205.      end;
  206.   end self;
  207.  
  208.  
  209.   task body Monitor is
  210.      Section, End_Of_Task : Boolean := False;
  211.      Game : Partie;
  212.      Line : Positive;
  213.      Col  : Positive;
  214.      Player : Joueur := X;
  215.      Winner : Joueur;
  216.      Fin    : Boolean := False;
  217.      
  218.   begin
  219.      while not End_Of_Task loop
  220.      select
  221.         accept New_Game do
  222.            Game.grille := (others => (others => E));
  223.            Section := True;
  224.            Text_Io.Put(Clear_Screen);
  225.           
  226.            for line in 1..3 loop
  227.           for col in 1..3 loop
  228.              if Game.Grille(Line, Col) = X or Game.Grille(Line, Col) = O then
  229.             Text_Io.Put(Joueur'Image(Game.Grille(Line, Col)));
  230.              else
  231.             Put(' ');
  232.              end if;
  233.           end loop;          
  234.           Text_Io.New_Line;
  235.            end loop;
  236.         end New_Game;
  237.      or
  238.         accept Halt do
  239.            End_Of_Task := True;
  240.            Section := False;
  241.         end Halt;        
  242.      end select;
  243.      while Section loop
  244.         accept Receive(Char : in Character; Game_Over : out boolean) do
  245.            case Char is
  246.           when '1' =>
  247.              Line := 3;
  248.              Col := 1;
  249.           when '2' =>
  250.              Line := 3;
  251.              Col := 2;
  252.           when '3' =>
  253.              Line := 3;
  254.              Col := 3;
  255.           when '4' =>
  256.              Line := 2;
  257.              Col := 1;
  258.           when '5' =>
  259.              Line := 2;
  260.              Col := 2;
  261.           when '6' =>
  262.              Line := 2;
  263.              Col := 3;
  264.           when '7' =>
  265.              Line := 1;
  266.              Col := 1;
  267.           when '8' =>
  268.              Line := 1;
  269.              Col := 2;
  270.           when '9' =>
  271.              Line := 1;
  272.              Col := 3;
  273.           when others =>
  274.              null;
  275.            end case;
  276.            if Game.Grille(Line, Col) /=  E then
  277.           Text_Io.Put(Character'Val(7));
  278.           delay 0.1;
  279.           Text_Io.Put(Character'Val(7));
  280.            else
  281.           Game.grille(Line, Col) := X;
  282.           
  283.           
  284.           Text_Io.Put(Clear_Screen);
  285.           
  286.           for line in 1..3 loop
  287.              for col in 1..3 loop
  288.             if Game.Grille(Line, Col) = X or Game.Grille(Line, Col) = O then
  289.                Text_Io.Put(Joueur'Image(Game.Grille(Line, Col)));
  290.             else
  291.                Put(' ');
  292.             end if;
  293.              end loop;          
  294.              Text_Io.New_Line;
  295.           end loop;
  296.           
  297.           Evaluer(game, Fin, Winner);
  298.           Game_Over := Fin;                     
  299.           New_Line;
  300.           delay 0.5;
  301.           if Game_Over then
  302.              Put_Line("Vous avez gagné, félicitations ! " );
  303.              Section := False;
  304.              Text_Io.Put(Character'Val(7));
  305.              delay 0.1;
  306.              Text_Io.Put(Character'Val(7));
  307.             
  308.           else
  309.              Self(Game.Grille);    
  310.              delay 1.0;          
  311.              Text_Io.Put(Clear_Screen);
  312.              for line in 1..3 loop
  313.             for col in 1..3 loop
  314.                if Game.Grille(Line, Col) = X or Game.Grille(Line, Col) = O then
  315.                   Text_Io.Put(Joueur'Image(Game.Grille(Line, Col)));
  316.                else
  317.                   Put(' ');
  318.                end if;
  319.             end loop;          
  320.             Text_Io.New_Line;
  321.              end loop;
  322.              Text_Io.Put(Character'Val(7));
  323.              delay 0.5;
  324.              Evaluer(game, Fin, Winner);
  325.              Game_Over := Fin;                     
  326.             
  327.              if Game_Over then
  328.             Put_Line("Vous avez perdue, domage ! " );
  329.             Section := False;            
  330.             Text_Io.Put(Character'Val(7));
  331.             delay 0.1;
  332.             Text_Io.Put(Character'Val(7));
  333.             delay 0.1;
  334.             Text_Io.Put(Character'Val(7));
  335.              end if;          
  336.           end if;
  337.            end if;
  338.         end Receive;
  339.         
  340.      end loop;
  341.      end loop;
  342.   end Monitor;
  343.  
  344.   Char : Character;
  345.   Success : Boolean := False;
  346. begin
  347.   loop
  348.      Monitor.New_Game;
  349.      loop    
  350.      Get_Immediate(Char);
  351.      Monitor.Receive(Char, success);
  352.      if Success then
  353.         exit;
  354.      end if;
  355.      end loop;
  356.      Put("Continuer ? (o/n) : " );
  357.      Get_Immediate(Char);
  358.      New_Line;
  359.      if Char = 'n' then
  360.      Monitor.Halt;
  361.      exit;
  362.      end if;
  363.   end loop;            
  364. end Tictactoe;


Vous pouvez tester des alternative des produits des code de Gilou, merci Gilou [:powa], en supprmant les plateau vide et avec un seul exemplaire du coup jouer.


Message édité par Profil supprimé le 17-09-2011 à 18:10:33
Reply

Marsh Posté le 20-09-2011 à 14:46:15    

Bonjour, bonjour Gilou ! Bonjour à tous.
 
Donc, pour le moment ça fonctionne pas. Et j'aimerais tester une autre solution.
 
J'aurais besoin d'une solution pour le même problème sauf qu'au lieu d'avoir l'état du jeu complet en seconde ligne, je souhaiterais essayer avec en une seconde ligne seulement le coup joué.
 
on part de :
état : 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
puis : (pour le premier coup ça change rien)
coup :1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
état : 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
coup: 0.0 -1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
 
Voila, si ça branche quelqu'un...
Merci.

Reply

Marsh Posté le 20-09-2011 à 15:46:25    


 
etat(0)
coup(1)
etat(1)
coup(2)
etat(2)
...
 
coup(N) = etat(N) - etat(N-1)
 
tu peux donc déduire tous les coups qui vont entre tes états, vu que tu as déjà les listes d'états


---------------
last.fm
Reply

Marsh Posté le 20-09-2011 à 16:05:28    

theshockwave a écrit :


 
etat(0)
coup(1)
etat(1)
coup(2)
etat(2)
...
 
coup(N) = etat(N) - etat(N-1)
 
tu peux donc déduire tous les coups qui vont entre tes états, vu que tu as déjà les listes d'états


 
C'est pas faux, tiens, je vais me débrouiller tout seul finalement à partir de là.
 
Merci theshockwave.

Reply

Marsh Posté le 20-09-2011 à 17:53:06    

Je viens de voir ton message, je te met ça dans 5 mn.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed