Un embouteillage 2D


17

Le modèle de trafic Biham-Middleton-Levine est un automate cellulaire auto-organisé qui modélise le trafic simplifié.

Il se compose d'un certain nombre de voitures représentées par des points sur un réseau avec une position de départ aléatoire, où chaque voiture peut être de deux types: celles qui ne se déplacent que vers le bas (indiquées en bleu dans cet article), et celles qui se déplacent uniquement vers le à droite (représenté en rouge dans cet article). Les deux types de voitures se déplacent à tour de rôle. A chaque tour, toutes les voitures du type correspondant avancent d'un pas si elles ne sont pas bloquées par une autre voiture.

Votre tâche consiste à visualiser ce modèle sous forme d'animation. Voici quelques bonnes démonstrations.

entrez la description de l'image ici

Contribution

Un nombre à virgule flottante compris entre 0 et 1 représentant la densité et deux entiers représentant la hauteur et la largeur de la grille affichées. Supposons que les entrées sont valides et que les paramètres d'une fonction ou la lecture de l'entrée utilisateur sont tous les deux corrects.

Exemple: 0.38 144 89(correspond à l'image ci-dessus)

Production

Une grille, au moins 80x80, qui affiche l'animation de ce modèle en cours d'exécution. Au début, les voitures sont placées au hasard sur la grille jusqu'à ce que la grille atteigne la densité d'entrée, avec moitié rouge et moitié bleu (c'est-à-dire la densité multipliée par le nombre total de carrés de grille, arrondis comme vous le souhaitez). La densité doit être cette valeur, ce qui signifie que vous ne pouvez pas remplir chaque cellule de densité comme probabilité. Pour chaque étape, un type de voiture se déplace vers le bas ou vers la droite, s'enroulant autour du bord. Le type de voiture qui se déplace alterne chaque étape. Pour rendre l'animation visible, il doit y avoir au moins 10 ms entre chaque étape.

Règles

  • Les voitures peuvent être de n'importe quelle couleur ou symbole tant qu'elles peuvent être distinguées les unes des autres et de l'arrière-plan, et chaque type de voiture est de la même couleur ou du même symbole.

  • La console et la sortie graphique sont toutes deux autorisées. Pour la sortie de la console, tout symbole imprimable convient, mais la sortie doit être une grille de caractères.

  • Veuillez spécifier le type de sortie que vous avez produit si vous n'avez pas de capture d'écran ou de gif.

  • La simulation doit fonctionner pour toujours.

La sortie est un peu complexe, donc si vous avez des questions, veuillez commenter.


Y a-t-il des restrictions sur la vitesse ou la rapidité avec laquelle l'animation doit s'exécuter?
xnor

Peut-être vaut-il la peine de préciser que le type de voiture qui se déplace alterne à chaque étape.
Greg Martin

@xnor Je pensais au moins 5 ou 10 ms par boucle, mais je ne suis pas vraiment sûr que ce soit difficile à mesurer.
qwr

3
La densité signifie-t-elle que la densité doit être cette valeur, ou simplement que chaque pixel a une probabilité d d'être rempli? De plus, devons-nous attribuer la couleur des voitures au hasard ou non? Si au hasard, encore une fois, est-ce correct s'ils ont juste 50 à 50 chances d'être l'une ou l'autre couleur?
JAD

1
@JarkoDubbeldam La densité doit être cette valeur. Ils ont 50 à 50 chances d'être de chaque couleur. Cependant, j'ai répondu tard, donc les réponses peuvent être différentes. Les voitures peuvent se déplacer vers le haut ou vers la gauche.
qwr

Réponses:


5

R, 350 338 293 291 273 268 264 octets

function(d,x,y){f=function(w){v=length(w);for(j in which(w>0&!w[c(2:v,1)]))w[c(j,j%%v+1)]=0:1;w};m=matrix(sample(c(rep(1,q<-floor(d*y*x/2)),rep(-1,q),rep(0,x*y-2*q))),x);p=animation::ani.pause;o=image;a=apply;repeat{o(m<-t(a(m,1,f)));p();o(m<--1*a(-1*m,2,f));p()}}

Non golfé:

function(d,x,y){
  q=floor(d*y*x/2)

  m=matrix(sample(c(rep(1,q),rep(-1,q),rep(0,x*y-2*q))),x)

  f=function(w){
    v=length(w)
    for(j in which(w>0&!w[c(2:v,1)])){
      w[c(j,j%%v+1)]=0:1
    }
    w
  }


  library(animation)
  repeat{
    m=t(apply(m,1,f))
    image(m)
    m=-1*apply(-1*t(m),2,f))
    ani.pause()
    image(m)  
    ani.pause()
  }
}

Fonction qui prend 3 arguments: dcomme densité et dimensions x,y. qest le nombre de voitures dans chaque couleur. mest la matrice avec des voitures, qui est initialement remplie en prenant une sorte aléatoire du nombre de voitures et d'espaces vides. Les voitures sont soit 1ou -1, l'espace vide l'est 0.

fest une fonction qui déplace les voitures d'une rangée, en regardant les voitures codées comme 1. Il vérifie si la voiture peut se déplacer en vérifiant les 1s suivis de 0. Nous utilisons applypour courir fsur chaque ligne ou colonne, selon les voitures.

fgère le déplacement des 1voitures, pour déplacer les -1voitures, nous transposons la matrice, changeant la direction du mouvement, multipliant la matrice par -1, de sorte que les -1voitures deviennent des 1voitures, et vv et la matrice résultante est à nouveau transformée.

Cela permet imagede créer le tracé, en utilisant 3 couleurs par défaut pour les trois valeurs. Utilise le animationpackage pour gérer les animations en utilisant les options par défaut, qui est de 1 fps.

0.38, 144, 89:

Lien vers GIF

0.2, 144, 89:

Lien vers GIF

0.53, 144, 89:

Lien vers GIF


Votre animation est vraiment cool - quelle densité avez-vous utilisée? Il semble que le tout soit coincé assez rapidement avec beaucoup d'espace vide
qwr

@qwr c'était vraiment quelque chose qui me dérangeait. Dans mon programme, le tout se bloque à des densités plus faibles que dans l'exemple que vous avez lié. Je ne me souviens pas des paramètres exacts utilisés pour l'intrigue, mais cela pourrait très bien être celui 0.38 144 89de l'exemple.
JAD

En jouant avec des grilles carrées, j'ai obtenu une densité de 0,35 à jam jasondavies.com/bml/#0.35/100/100 mais c'est presque toujours une ligne épaisse de 45 degrés au lieu de fines lignes diagonales. Étant donné que vos lignes semblent plus verticales, je pense que quelque chose avec les deux types de voitures est désactivé
qwr

Je vois le problème maintenant. Cara ne peut avancer que si elle n'est pas bloquée par une autre voiture. Ainsi, dans les exemples Wikipedia, toutes les voitures en mouvement ont un espace devant elles. Mais dans votre animation, les voitures se déplacent en ligne. Intéressant.
qwr

Ah, ça le ferait.
JAD

5

Mathematica, 237 228 203 198 181 octets

(b=RandomSample@ArrayReshape[Table[{0,i=2},##/2],{1##2},1]~Partition~#2;Dynamic@Colorize[i=-i;b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b];If[i>0,b,2-b]])&

La sortie est une dynamique Image. L'arrière-plan est vert clair et les voitures sont noires ou magenta, selon leur direction.

Explication

b=RandomSample@ArrayReshape[Table[{i=1,2},##/2],{1##2},1]~Partition~#2

Créez le tableau initial:

Table[{0,i=2},##/2]

Réglez isur 2. Créez un Listde {0, 2}, dont la longueur est le plancher (densité * largeur * hauteur / 2) (divisé par deux car {0, 2}longueur-2).

ArrayReshape[ ... ,{1##2},1]

Remodeler le 2-D résultant List(2 x quelque chose) en 1-D List(longueur = largeur * hauteur). Remplissez 1s'il n'y a pas assez de valeurs.

RandomSample@ ...

(Pseudo) trie aléatoirement le résultat.

... ~Partition~#2

Partition qui résulte en longueur (largeur).

b= ...

Conservez-le dans b.


Dynamic@Colorize[i=-i;b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b];If[i>0,b,2-b]]

Créez un Dynamic Image:

i=-i;

Retournez le signe de i.

b=CellularAutomaton[{193973693,{3,{a=0{,,},{3,9,1},a}},{1,1}},b]

Appliquer l'automate cellulaire avec 193973693les poids de règle et de voisin {{0, 0, 0}, {3, 9, 1}, {0, 0, 0}}à btransposer. Ensembleb égal à cela.

If[i>0,b,2-b]

Si ic'est positif, laissez btranquille. Sinon, transposez le b( 2-est là parce que j'ai joué CellularAutomatonun peu au golf ). Essentiellement, cela transposeb toutes les autres itérations (pour annuler la transposition)

Colorize[ ... ]

Convertissez le tableau en un coloré Image .

Dynamic@ ...

Faites l'expression Dynamic. c'est-à-dire que les fonctions ci-dessus sont exécutées de manière répétée.

Production

Voici un exemple de sortie (entrées: 0.35, 192, 108 pour 2000 images (2x agrandies).

https://i.imgur.com/zmSyRut.mp4


Huh, utiliser le intégré est plus long que de ne pas l'utiliser?!
Adám

3

Dyalog APL , 190 108 115 112 octets

Solution

S←{⍉⍣⍺⊢d[⍺]↑d[⍺]↓⍉↑(⍺⊃'(↓+) ' '(→+) ')⎕R' \1'↓(,⍨,⊢)⍉⍣⍺⍉⎕←⍵⊣⎕DL÷4}
{1S 0S⍵}⍣≡' ↓→'[d⍴{⍵[?⍨⍴⍵]}c1 2⍴⍨⌊⎕×c←×/d←⎕]

TryAPL en ligne (légèrement modifié en raison de restrictions en ligne):

  1. Définir ⎕IO←0, définir la fonction S , puis définir et afficher une grille de 38% 14 × 29 aléatoire, G .

  2. Faites un pas vers le bas.

  3. Faites un pas vers la droite.

  4. Passez à l'étape 2.

    Circulation
    Animation de l'algorithme précédent, qui ne garantissait pas la densité.

Explication

S←{définir la fonction directe S (expliquée ici de droite à gauche):

÷4 réciproque de 4 (0,25)

⎕DL attendre autant de secondes (retourne le temps réel écoulé)

⍵⊣ jeter cela en faveur de ⍵ (le bon argument; la grille)

⎕← sortie qui

 transposer

⍉⍣⍺ transposer à nouveau si ⍺ (l'argument de gauche; 0 = bas, 1 = droit)

( appliquer le train de fonctions (expliqué ici de gauche à droite):

  ,⍨ l'argument ajouté à lui-même

  , annexé à

   lui-même

)

 diviser la matrice en liste de listes

( recherche d'expressions rationnelles (expliquées ici de gauche à droite):

  ⍺⊃ choisissez l'un des deux suivants en fonction de ⍺ (0 = bas / premier, 1 = droite / seconde)

  '(↓+) ' '(→+) ' séquences de flèches bas et gauche suivies d'un espace

)⎕R' \1' remplacer par un espace suivi de la séquence trouvée

 mélanger la liste des listes dans la matrice

 transposer

d[⍺]↓ supprimer les lignes "hauteur" si ⍺ (argument de gauche) est 0 (bas) ou les lignes "largeur" ​​si ⍺ est 1 (droite)

d[⍺]↑ puis prenez autant de lignes

 passer à travers (sert de séparateur)

⍉⍣⍺ transposer si ⍺ (l'argument de gauche; 0 = bas, 1 = droit)

}


' ↓→'[ indexez la chaîne avec (expliqué ici de droite à gauche):

 entrée numérique (dimensions)

d← attribuer cela à d

×/ multiplier les dimensions (trouve le nombre de cellules)

c← attribuer cela à c

⎕× multipliez cela avec une entrée numérique (la densité)

 arrondir vers le bas

1 2⍴⍨ répéter cycliquement un et deux jusqu'à cette longueur

c↑ étendre cela jusqu'à la longueur c , rembourrage avec des zéros

d⍴ utiliser d (les dimensions) pour remodeler

{ appliquer cette fonction anonyme à cela (expliqué ici de gauche à droite):

  ⍵[ le bon argument (la liste des zéros, des uns et des deux) indexé par

   ?⍨ les indices mélangés jusqu'à

   ⍴⍵ la longueur de l'argument

  ]

}

]

{ appliquer la fonction anonyme suivante (expliquée de droite à gauche):

0S⍵ appliquer S avec 0 (bas) comme argument de gauche et la grille comme argument de droite

1S avec cela comme bon argument, appliquer S avec 1 (droite) comme argument de gauche

}⍣≡ jusqu'à ce que deux itérations successives soient identiques (un embouteillage)

Remarques

  1. Requiert ⎕IO←0, qui est par défaut sur de nombreux systèmes.

  2. Demande pour (hauteur, largeur), puis pour la densité.

  3. N'utilise aucun automate intégré.

  4. Utilise le support regex intégré.

  5. Arrête en cas d'embouteillage (aucune voiture ne peut bouger).

  6. Produit des matrices de caractères où représentent les voitures se déplaçant vers la droite, représentent les voitures se déplaçant vers le bas et les espaces sont des routes vides.

  7. Comme ci-dessus, il émet vers la session à 4 Hz, mais la fréquence peut être ajustée en changeant ÷4; par exemple ÷3est 3 Hz et .3est ³⁄₁₀ Hz.

  8. Il est plus facile de voir ce qui se passe si vous exécutez ]Box on -s=max -f=on abord.

  9. La distribution requise est maintenant garantie, et les deux types de voitures se produisent dans exactement 50-50, sauf pour l'arrondi.


Votre génération de carte initiale ne garantit pas une carte qui a la densité d'entrée. Je suppose que c'est le choix de l'OP d'autoriser cela ou non.
JungHwan Min

Oh, @JarkoDubbeldam l'a déjà demandé.
JungHwan Min

@JungHwanMin Comment cela? Soit la densité d. Chaque poste obtient une valeur comprise entre 0 et 1. Si entre 0 et ᵈ/₂ il devient ,. Si entre ᵈ⁄₂ et d, il devient a . Si entre d et 1, il reste vide.
Adám

Eh bien, un cas extrême serait: chaque position obtient en quelque sorte la valeur 0(car elles sont (pseudo) générées de manière aléatoire (pseudo) -indépendamment; très improbable mais possible). Ensuite, votre conseil est plein de s.
JungHwan Min

@JungHwanMin Ah, je vois ce que tu veux dire.
Adám

1

Java (624 octets + 18 octets pour Java.awt. * = 642 octets)

static void k(double b,final int c,final int d){final int[][]a=new int[c+1][d+1];int i=0,j;for(;i<c;i++){for(j=0;j<d;j++){a[i][j]=Math.random()<b?Math.random()<0.5?1:2:0;}}Frame e=new Frame(){public void paint(Graphics g){setVisible(1>0);int i=0,j;for(;i<c;i++){for(j=0;j<d;j++){g.setColor(a[i][j]==2?Color.BLUE:a[i][j]==1?Color.RED:Color.WHITE);g.drawLine(i,j,i,j);}}for(i=c-1;i>=0;i--){for(j=d-1;j>=0;j--){if(a[i][j]==1&&a[i][(j+1)%d]==0){a[i][(j+1)%d]=1;a[i][j]=0;}else if(a[i][j]>1&&a[(i+1)%c][j]==0){a[(i+1)%c][j]=2;a[i][j]=0;}}}}};e.show();while(1>0){e.setSize(c,d+i++%2);try{Thread.sleep(400L);}catch(Exception f){}}}

Non golfé:

static void k(double b,final int c,final int d){
        final int[][]a=new int[c+1][d+1];
        int i=0,j;
        for(;i<c;i++) {
            for(j=0;j<d;j++) {
                a[i][j]=Math.random()<b?Math.random()<0.5?1:2:0;
            }
        }

        Frame e=new Frame(){
            public void paint(Graphics g){
                setVisible(1>0);
                int i=0,j;
                for(;i<c;i++) {
                    for(j=0;j<d;j++) {
                        g.setColor(a[i][j]==2?Color.BLUE:a[i][j]==1?Color.RED:Color.WHITE);
                        g.drawLine(i,j,i,j);
                    }
                }
                for(i=c-1;i>=0;i--) {
                    for(j=d-1;j>=0;j--) {
                        if(a[i][j]==1&&a[i][(j+1)%d]==0){
                            a[i][(j+1)%d]=1;a[i][j]=0;
                        }else if(a[i][j]>1&&a[(i+1)%c][j]==0){
                            a[(i+1)%c][j]=2;a[i][j]=0;
                        }
                    }
                }
            }
        };
        e.show();
        while(1>0){e.setSize(c,d+i++%2);try{Thread.sleep(400L);}catch(Exception f){}}
    }

Image:

entrez la description de l'image ici


Vous ne connaissez pas java, mais le rouge, le bleu et le blanc sont-ils les noms les plus courts pour les couleurs que vous pouvez utiliser? (peut-être que le gris est une option, économisant un octet par rapport au blanc)
JAD

La capture d'écran semble montrer le même problème que ce que j'ai décrit ici codegolf.stackexchange.com/questions/104742/a-2d-traffic-jam/…
qwr
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.