IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Memory error sur un script de résolution de labyrinthe


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Memory error sur un script de résolution de labyrinthe
    Bien le bonjour en ce dernier jour de l'année !

    La suite des péripéties de mon labyrinthe... J'ai souhaité créé un script de résolution de labyrinthe moi-même en me basant un peu sur l'idée d'un autre script, afin de vérifier que je n'ai bien qu'un seul chemin suite aux nombreuses modifications que j'ai apporté à ce labyrinthe sidewinder.
    J'ai utilisé un système de récursion puisque c'est plus simple pour ma petite tête, mais voilà autant avec un petit labyrinthe ça marche, autant avec un gros ça plante !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    file = open("Maze.txt","r")
    area = file.read().replace(',','').splitlines()
    file.close()
    air = [[int(x) for x in line] for line in area]
     
    import sys, time
     
    sys.setrecursionlimit(10000)
     
    '''air = [[0,1,0,0,0,0,0,0,0],
            [0,1,0,0,1,1,1,1,0],
            [0,1,0,1,1,0,0,1,0],
            [0,1,1,1,0,1,1,1,0],
            [0,1,0,0,0,1,0,1,0],
            [0,1,1,1,1,1,1,1,0],
            [0,1,0,1,0,0,0,1,0],
            [0,0,0,0,0,0,0,1,0]]'''
     
    area = [l.copy() for l in air]
     
    start = (0,1)
    end = (len(area)-1,len(area[-1])-2)
     
    def print_area(tableau):
        for line in tableau:
            print(line)
        print('---------------')
        time.sleep(0.5)
     
    path = []
    def find_way(x, y):
        global path
        path.append((x, y))
        for X, Y in ((x+i, y+I) for i in range(-1,2) for I in range(-1,2) if (i,I) != (0, 0) and (not i or not I)):
            if area[X][Y]==area[x][y]-1 and X >= 0 and Y >= 0 and area[X][Y]:            
                find_way(X, Y)
                break
     
     
    def next_step(x,y,pcds,visited,k=2):
        visited_copy = visited.copy()
        for X, Y in ((x+i, y+I) for i in range(-1,2) for I in range(-1,2) if (i,I) != (0, 0) and (not i or not I)):
            if (X, Y) != pcds :
                try:
                    if area[X][Y]:
                        if (X,Y) not in visited_copy:
                            visited_copy.append(pcds)
                            area[X][Y]=k
                            #print_area(area)                    
                            next_step(X,Y,(x, y),visited_copy,k+1)                    
                except IndexError:
                    print('bug :',X,Y)
                    pass
     
     
    print(time.ctime())
    next_step(start[0], start[1], start, [])
     
    #print_area(air)
    #print_area(area)
    find_way(end[0], end[1])
    for x, y in path:
        air[x][y] = 9
    #print_area(air)
     
    with open("Maze_solved.txt","w") as file:
        for line in air:
            file.write(str(line)[1:-1].replace(',',''))
            file.write('\n')
    Voici le message d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    File "C:\Users\toto\Desktop\Scripts\K_GAME\solver.py", line 50, in next_step
        next_step(X,Y,(x, y),visited_copy,k+1)
      [Previous line repeated 1955 more times]
      File "C:\Users\toto\Desktop\Scripts\K_GAME\solver.py", line 47, in next_step
        visited_copy.append(pcds)
    MemoryError
    Que se passe-t-il avec ces listes ?
    Restent-elles en mémoire jusque la fin du programme et sature la RAM ?
    Est-ce que c'est mon code qui est mal fichu (fortement probable) ?

    Et finalement comment utiliser sa propre pile plutôt que de la récursion sans tourner en rond ? (Ce qui est peut-être déjà le cas avec mon script, j'ai fais juste quelques petits tests)

    Merci et bon réveillon ou bonne année si vous lisez ceci début 2022. 🥳
    Dernière modification par Invité ; 31/12/2021 à 14h38.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Salut,

    Citation Envoyé par LeNarvalo Voir le message
    Que se passe-t-il avec ces listes ?
    Restent-elles en mémoire jusque la fin du programme et sature la RAM ?
    Est-ce que c'est mon code qui est mal fichu (fortement probable) ?
    Si on écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def next_step(x,y,pcds,visited,k=2):
        visited_copy = visited.copy()
    chaque fois qu'on entre dans next_step on ajoute une liste qui ne sera libérée qu'en sortie (qui peut être bien plus tard car ça peut descendre en récursion).

    De toutes façons, écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sys.setrecursionlimit(10000)
    pour que Python pousse encore malgré la limite qui devrait vous inciter à réfléchir avant de la franchir...

    Il y a plein de code et de documentation sur la résolution de labyrinthes. A vous de regarder et vous inspirer de ce qu'on déjà fait les anciens plutôt que de vous lancer tout seul dans la jungle et vous retrouver coincé parce que c'est plus dur que çà!

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Invité
    Invité(e)
    Par défaut
    Merci Wiz,

    Du coup c'est bien un problème de saturation de mémoire à cause de ces fameuses listes ?
    Ca m'étonne que ça sature aussi rapidement, il faudrait que je regarde la valeur de k parce que j'ai fais un petit test :
    l = [[x for x in range(1000,10000)] for _ in range(1000)]
    300 Mo
    l = [[x for x in range(10000,100000)] for _ in range(1000)]
    3 Go


    Je me suis basé sur ce tuto :
    https://levelup.gitconnected.com/sol...n-e9f0580979a1

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Du coup c'est bien un problème de saturation de mémoire à cause de ces fameuses listes ?
    Il faudrait regarder de quoi la mémoire se remplit. Il y a des outils pour çà.

    Citation Envoyé par LeNarvalo Voir le message
    Ca m'étonne que ça sature aussi rapidement, il faudrait que je regarde la valeur de k parce que j'ai fais un petit test :
    Si vous avez augmenté la taille de la pile de récursion à 10000, ça fait un sacré facteur multiplicatif.

    Citation Envoyé par LeNarvalo Voir le message
    Il n'a pas l'air d'avoir eu besoin d'augmenter la taille de la pile... Par contre, il ne semble pas avoir finalisé son code => a vous de voir.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Bien le bonjour en ce dernier jour de l'année !
    Bonjour et bonne nouvelle année pour ce premier jour de celle-ci

    Citation Envoyé par LeNarvalo Voir le message
    J'ai souhaité créé un script de résolution de labyrinthe moi-même en me basant un peu sur l'idée d'un autre script, afin de vérifier que je n'ai bien qu'un seul chemin
    Ce n'est pas parce que tu trouves un chemin que celui-ci est unique.

    Citation Envoyé par LeNarvalo Voir le message
    J'ai utilisé un système de récursion puisque c'est plus simple pour ma petite tête,
    Oui, c'est un mécanisme généralement simple à implémenter. Mais malheureusement ça peut avoir des conséquences dramatiques en termes de capacité quand l'arbre des possibles est trop grand. Et modifier la limite de récursion n'apporte qu'un répit assez minime.
    Surtout qu'il existe un algorithme non récursif assez simple: l'algorithme de la main gauche. Tu places ta main gauche sur le mur de gauche à l'entrée du labyrinthe et ensuite tu avances en gardant toujours la main collée au mur. Fatalement tu finis par arriver à la sortie. Et (double effet), il fonctionne aussi avec la main droite...

    Citation Envoyé par LeNarvalo Voir le message
    Ca ressemble à l'algorithme de remplissage par diffusion. Mais là son but est de trouver un élément dans une carte, pas dans un labyrinthe (enfin évidemment ça marche aussi dans un labyrinthe mais le labyrinthe, avec son chemin encadrés de mur, permet lui d'appliquer l'algorithme de la main gauche, chose qui n'est pas possible sur l'exemple du site).
    Toutefois il existe une possibilité d'implémenter cet algorithme en utilisant une pile pour simuler la récursivité. Dans ce cas plus de souci de limite de récursion (cela n'enlève pas le souci du temps de recherche). Plus de détails ici: https://fr.wikipedia.org/wiki/Algori..._par_diffusion.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Invité
    Invité(e)
    Par défaut
    Salut et bonne année !

    Ce n'est pas parce que tu trouves un chemin que celui-ci est unique.
    Oui effectivement je me suis mal exprimé !
    Je connais déjà le chemin mais je voulais m'assurer qu'avec mes modifs sur le labyrinthe il n'y en a pas un plus court !

    Toutefois il existe une possibilité d'implémenter cet algorithme en utilisant une pile pour simuler la récursivité. Dans ce cas plus de souci de limite de récursion (cela n'enlève pas le souci du temps de recherche). Plus de détails ici: https://fr.wikipedia.org/wiki/Algori..._par_diffusion.
    Merci pour le lien !

    Code algo : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     remplissage4(pixel, colcible, colrep)
     début
       Soit P une pile vide
       si couleur(pixel) ≠ colcible alors sortir finsi
       Empiler pixel sur P
       Tant que P non vide
       faire
         Dépiler n de P
         couleur(n) ← colrep
         si couleur(n nord) = colcible alors Empiler n nord sur P finsi
         si couleur(n sud)  = colcible alors Empiler n sud  sur P finsi
         si couleur(n est)  = colcible alors Empiler n est  sur P finsi
         si couleur(n ouest)= colcible alors Empiler n ouest sur P finsi
       fintantque
     fin
    C'est ça en python ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def remplissage(x,y):
    	liste = []
    	if air[x][y]:
    		liste.append((x,y))
    	while liste:
    		X, Y = liste.pop()
    		air[X][Y] = 9
    		if air[X+1][Y] == 1:
    			liste.append((X+1, Y))
    		if air[X-1][Y] == 1:
    			liste.append((X-1, Y))
    		if air[X][Y+1] == 1:
    			liste.append((X, Y+1))
    		if air[X][Y-1] == 1:
    			liste.append((X, Y-1))
    Maintenant faut que je fasse comment pour connaître le bon chemin ?
    Utiliser une variable incrémentable au lieu de 9 ? Puis remonter le chemin en commençant par la fin ? Je dois prendre le chiffre le plus proche, le plus petit, ... du mal à voir.

    Je dois faire liste.pop() ou liste.pop(0) d'ailleurs ? Je dirais pop(0)...

    PS : @Wiz ou qqun d'autre, c'est étonnant que python ne soulève aucune erreur si je pousse la limite de récursion à 1 million par exemple... Il n'y a pas justement un meilleur traçage des erreurs avec la nouvelle version de python ?
    Dernière modification par Invité ; 01/01/2022 à 21h21.

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    PS : @Wiz ou qqun d'autre, c'est étonnant que python ne soulève aucune erreur si je pousse la limite de récursion à 1 million par exemple... Il n'y a pas justement un meilleur traçage des erreurs avec la nouvelle version de python ?
    Python n'est pas responsable des erreurs produites par l'individu qui est entre la chaise et le clavier: si on modifie un paramètre système, on est supposé savoir ce qu'on fait. Sinon on pourrait imaginer une sorte de décharge électrique pour motiver l'utilisateur à réfléchir avant de coder... mais c'est un peu extrême.

    Le traçage des erreurs va souligner l'élément qui a provoqué l'erreur dans une expression complexe. C'est une bonne aide à la mise au point.

    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Python n'est pas responsable des erreurs produites par l'individu qui est entre la chaise et le clavier: si on modifie un paramètre système, on est supposé savoir ce qu'on fait. Sinon on pourrait imaginer une sorte de décharge électrique pour motiver l'utilisateur à réfléchir avant de coder... mais c'est un peu extrême.

    Le traçage des erreurs va souligner l'élément qui a provoqué l'erreur dans une expression complexe. C'est une bonne aide à la mise au point.

    -W
    La vache j'adore ta pédagogie !
    John Kreese, sensei du dojo Python Kai. (Elle est bonne non ?)

    Je vais me brancher au secteur pour voir si je comprends mieux du coup !

    PS :
    Le traçage des erreurs va souligner l'élément qui a provoqué l'erreur dans une expression complexe.
    Ca n'allait pas plus loin que ça ? Je suis désapointé.

  9. #9
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Ca n'allait pas plus loin que ça ? Je suis désapointé.
    La liste est ici. Effectivement, il y en a plus qui détaillent des SyntaxError sujettes à de nombreuses discussions ouvertes par les débutants (en espérant qu'ils lisent les messages).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Maintenant faut que je fasse comment pour connaître le bon chemin ?
    Utiliser une variable incrémentable au lieu de 9 ? Puis remonter le chemin en commençant par la fin ? Je dois prendre le chiffre le plus proche, le plus petit, ... du mal à voir.
    C'est vrai que c'est un problème. L'algorithme de remplissage par diffusion est fait pour remplir une surface. Fatalement en remplissant toute la surface du labyrithe tu atteints la sortie à un moment mais effectivement une fois la sortie trouvée, ça ne te donne pas le chemin, juste le fait que la sortie a été trouvée. Et tu te retrouves avec (au pire) un labyrinthe tout rempli de points rouges (en référence aux animations de l'autre site) et pas de chemin. Désolé je n'y avais pas pensé.
    Donc retour aux bases. Algorithme de la main gauche (ou droite au choix). Avec en plus mémorisation du chemin parcouru et chaque fois que tu repasses par le même chemin dans l'autre sens (quand tu as suivi une impasse) tu effaces le chemin parcouru. Quand tu atteints la sortie tu as le chemin. Simple, sans récursivité, sans souci annexe quoi.

    Citation Envoyé par LeNarvalo Voir le message
    PS : @Wiz ou qqun d'autre, c'est étonnant que python ne soulève aucune erreur si je pousse la limite de récursion à 1 million par exemple...
    Ben... mettre une limite quelconque à 1 million en soit ce n'est pas une erreur. Et si ta machine peut assurer la charge le code fonctionnera.

    Citation Envoyé par LeNarvalo Voir le message
    John Kreese, sensei du dojo Python Kai. (Elle est bonne non ?)
    Ah? Référence à Karaté Kid 1986? Ok en voici une autre tirée du même film: le crapaud qui marche au milieu de la route, tôt ou tard, crouich. Donc tu fais du Python correctement ou tu n'en fais pas. Mais si tu fais du Python à moitié, tôt ou tard crouich comme crapaud.

    Citation Envoyé par wiztricks Voir le message
    La liste est ici
    Bigre, ils en ont fait des efforts pour aider le noob. Ca en devient presque de l'assistanat...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Invité
    Invité(e)
    Par défaut
    Lu !
    Donc retour aux bases. Algorithme de la main gauche (ou droite au choix). Avec en plus mémorisation du chemin parcouru et chaque fois que tu repasses par le même chemin dans l'autre sens (quand tu as suivi une impasse) tu effaces le chemin parcouru. Quand tu atteints la sortie tu as le chemin. Simple, sans récursivité, sans souci annexe quoi.
    Hum donc en gros je fais si Ouest aller à l'Ouest, sinon si Sud allez au Sud, sinon si Est allez à l'Est, sinon si Nord allez au Nord, dans ce sens là si j'utilise l'algo de la main droite ? (Vu que j'ai un labyrinth sidewinder je pense que c'est mieux d'utiliser la main droite)

    Nom : maze-main-droite.gif
Affichages : 455
Taille : 182,5 Ko

    Arf je suis con faut que je rajoute et si case pas connue !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Si Ouest et case pas connue aller à l'Ouest,
     sinon si Sud et case pas connue allez au Sud, 
     sinon si Est et case pas connue allez à l'Est, 
     sinon si Nord et case pas connue  allez au Nord,
    Sinon supprimer case et revenir case précédente.
    Dernière modification par Invité ; 02/01/2022 à 12h50.

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par LeNarvalo Voir le message
    Vu que j'ai un labyrinth sidewinder je pense que c'est mieux d'utiliser la main droite)
    Ben... non, t'as autant de chance d'arriver plus vite que moins vite. Les deux algos fonctionnent ok et effectivement l'un des deux ira plus vite que l'autre mais il n'y a rien qui permette de choisir (et si tu examines ton dessin, tu verras que la main gauche est ici plus rapide).

    Sur mon blog je présente un petit jeu où il faut programmer un robot pour sortir d'un mini-labyrinthe. Et je dis aussi que j'ai écrit un algo qui fonctionne dans toutes les situations possibles. Ben mon algo c'est exactement celui de la main gauche.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 19/08/2019, 17h45
  2. error message sur un script
    Par miroufsn dans le forum Langage
    Réponses: 2
    Dernier message: 18/12/2007, 08h14
  3. Script error sur envoi de formulaire sous IE
    Par loick2000 dans le forum Général JavaScript
    Réponses: 20
    Dernier message: 14/05/2007, 17h30
  4. Question sur un script
    Par Gnux dans le forum Linux
    Réponses: 8
    Dernier message: 07/07/2005, 17h03
  5. installation sur serveur + script
    Par liliprog dans le forum Langages de programmation
    Réponses: 7
    Dernier message: 18/08/2004, 15h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo