Simple Quasi-Market

Simple Quasi-Market preview image

1 collaborator

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by everyone
Model was written in NetLogo 6.4.0 • Viewed 841 times • Downloaded 24 times • Run 0 times
Download the 'Simple Quasi-Market' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Info tab cannot be displayed because of an encoding error

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

globals [
  iteration-count       ; Variable pour suivre le nombre d'itérations
  duncan-index-value    ; Variable pour stocker l'indice de Duncan
  previous-schools
  longitudinal-data
  export-started?

]


breed [students student]
breed [schools school]

students-own [
  social-class    ; "favorise", "moyen", ou "defavorise"
  year           ; année scolaire (1-6)
  tolerance      ; seuil de tolérance
  my-school      ; école assignéef
  waiting        ; en attente d'une place ou non
  network-diversity  ; nouvelle variable pour la diversité du réseau
]

schools-own [
  capacity-per-year  ; capacité par année (60 places en 1ère année, etc.)
  nb-favorises
  nb-moyens
  nb-defavorises
]

; Procédure pour compter précisément les élèves par année dans chaque école

to-report count-students-in-year [school-agent year-number]
  report count students with [my-school = school-agent and year = year-number and not waiting]
end 

; Procédure pour vérifier si une école a de la place pour une année donnée

to-report has-capacity-for-year [school-agent year-number]
  let current-count count-students-in-year school-agent year-number
  let max-capacity [capacity-per-year] of school-agent
  report current-count < max-capacity
end 

to setup
  clear-all

  ; Normaliser les proportions pour qu'elles somment à 1
  let somme-proportions (proportion-favorises + proportion-moyens + proportion-defavorises)
  if somme-proportions = 0 [
    ; Si toutes les proportions sont à 0, utiliser les valeurs par défaut
    set proportion-favorises 0.33
    set proportion-moyens 0.33
    set proportion-defavorises 0.34
    set somme-proportions 1
  ]

  ; Normaliser pour que la somme soit égale à 1
  set proportion-favorises proportion-favorises / somme-proportions
  set proportion-moyens proportion-moyens / somme-proportions
  set proportion-defavorises proportion-defavorises / somme-proportions

  ; Initialiser les variables globales
  set iteration-count 0
  ;set politique-mixite-sociale false
  ;set politique-quotas false

  ; Création des écoles en nombre variable
  create-schools number-of-schools [
    set shape "house"
    set color 9.9
    set capacity-per-year school-capacity
    set nb-favorises 0
    set nb-moyens 0
    set nb-defavorises 0
    set size 3

  ; Initialiser la structure de données pour le suivi longitudinal
    set longitudinal-data []
    set export-started? false

    ; Positionnement des écoles en cercle
    let angle (360 / number-of-schools) * who
    let radius 12  ; Rayon du cercle, ajustez selon les besoins
    setxy radius * sin angle radius * cos angle
  ]

  set iteration-count 0

  ; Créer la première cohorte d'élèves immédiatement
  create-initial-students

  reset-ticks
end 

; Procédure pour créer les élèves selon les proportions définies par les sliders

to create-initial-students
  create-students total-students-per-year [
    set shape "person"
    set size 1
    set year 1
    set waiting true

    ; Distribution sociale selon les proportions définies par les sliders
    let r random-float 1
    ifelse r < proportion-favorises [
      set social-class "favorise"
    ] [
      ifelse r < (proportion-favorises + proportion-moyens) [
        set social-class "moyen"
      ] [
        set social-class "defavorise"
      ]
    ]

    ; Définir la couleur selon la classe sociale
    if social-class = "favorise" [ set color red ]
    if social-class = "moyen" [ set color green ]
    if social-class = "defavorise" [ set color blue ]

    ; Définir le seuil de tolérance selon la classe sociale
    if social-class = "favorise" [
      set tolerance tolerance-favorises
    ]
    if social-class = "moyen" [
      set tolerance tolerance-moyens
    ]
    if social-class = "defavorise" [
      set tolerance tolerance-defavorises
    ]

    ; Positionnement aléatoire initial (loin des écoles)
    setxy random-xcor random-ycor
  ]

  ; Assigner les élèves immédiatement avec la politique des quotas si elle est activée
  initial-assign-students
end 

; Procédure d'assignement initial des élèves pour respecter strictement les capacités

to initial-assign-students
  ; Répartir les élèves entre les écoles pour le premier tour
  let students-per-school floor (total-students-per-year / number-of-schools)

  ifelse politique-quotas [
    ; Avec politique de quotas
    let all-favorises students with [social-class = "favorise" and waiting = true]
    let all-moyens students with [social-class = "moyen" and waiting = true]
    let all-defavorises students with [social-class = "defavorise" and waiting = true]

    ; Pour chaque école par son index
    foreach n-values number-of-schools [i -> i] [ s-id ->
      let school-s school s-id
      let remaining-capacity [capacity-per-year] of school-s

      ; Calculer combien d'élèves de chaque groupe pour cette école
      let quota-favorises floor (remaining-capacity * proportion-favorises)
      let quota-moyens floor (remaining-capacity * proportion-moyens)
      let quota-defavorises floor (remaining-capacity * proportion-defavorises)

      ; Ajuster pour utiliser toute la capacité
      let leftover remaining-capacity - (quota-favorises + quota-moyens + quota-defavorises)

      ; Distribuer le surplus
      if leftover > 0 [
        ifelse proportion-favorises >= proportion-moyens and proportion-favorises >= proportion-defavorises [
          set quota-favorises quota-favorises + leftover
        ] [
          ifelse proportion-moyens >= proportion-favorises and proportion-moyens >= proportion-defavorises [
            set quota-moyens quota-moyens + leftover
          ] [
            set quota-defavorises quota-defavorises + leftover
          ]
        ]
      ]

      ; Assigner les élèves favorisés
      if quota-favorises > 0 and any? all-favorises [
        let favorises-to-assign min list quota-favorises count all-favorises
        ask n-of favorises-to-assign all-favorises [
          move-to school-s
          set my-school school-s
          set waiting false
          fd 3
          rt random 360
        ]
      ]

      ; Assigner les élèves moyens
      if quota-moyens > 0 and any? all-moyens [
        let moyens-to-assign min list quota-moyens count all-moyens
        ask n-of moyens-to-assign all-moyens [
          move-to school-s
          set my-school school-s
          set waiting false
          fd 3
          rt random 360
        ]
      ]

      ; Assigner les élèves défavorisés
      if quota-defavorises > 0 and any? all-defavorises [
        let defavorises-to-assign min list quota-defavorises count all-defavorises
        ask n-of defavorises-to-assign all-defavorises [
          move-to school-s
          set my-school school-s
          set waiting false
          fd 3
          rt random 360
        ]
      ]
    ]
  ][
    ; Sans politique de quotas - assignation aléatoire avec respect de la capacité
    foreach n-values number-of-schools [i -> i] [ s-id ->
      let school-s school s-id
      let remaining-capacity [capacity-per-year] of school-s
      let eligible-students students with [waiting = true]

      if remaining-capacity > 0 and any? eligible-students [
        let students-to-assign min list remaining-capacity count eligible-students
        ask n-of students-to-assign eligible-students [
          move-to school-s
          set my-school school-s
          set waiting false
          fd 3
          rt random 360
        ]
      ]
    ]
  ]

  ; Mettre à jour les statistiques des écoles
  update-school-stats
end 

; Commencer l'enregistrement des données longitudinales

to start-longitudinal-export
  set export-started? true
  set longitudinal-data []
  print "Enregistrement des données longitudinales démarré."
end 

; Arrêter l'enregistrement des données longitudinales

to stop-longitudinal-export
  set export-started? false
  print "Enregistrement des données longitudinales arrêté."
end 

; Choisir l'école préférée, avec prise en compte de la capacité

to choose-preferred-school
  ; Ne considérer que les écoles qui ont de la place
  let available-schools schools with [has-capacity-for-year self 1]

  ; S'il n'y a pas d'écoles disponibles, rester en attente
  if not any? available-schools [
    stop
  ]

  ; Vérifier si tolérance maximale ou premiers élèves
  if tolerance >= 0.99 or count students with [not waiting] = 0 [
    ; Attribution aléatoire parmi les écoles disponibles
    move-to one-of available-schools
    stop
  ]

  ; Sinon, utiliser le système de préférences parmi les écoles disponibles
  let min-discomfort 1
  let best-school nobody

  ask available-schools [
    let current-discomfort calculate-discomfort myself self
    if current-discomfort < min-discomfort [
      set min-discomfort current-discomfort
      set best-school self
    ]
  ]

  ; Aller à la meilleure école disponible
  if best-school != nobody [
    move-to best-school
  ]
end 

; Calcul de l'inconfort avec la nouvelle logique de tolérance

to-report calculate-discomfort [student-agent school-agent]
  let my-tolerance [tolerance] of student-agent
  let my-class [social-class] of student-agent

  ; Si tolérance est 0, aucun inconfort (accepte n'importe quelle école)
  if my-tolerance <= 0 [report 0]

  ; Compter le nombre total d'élèves dans l'école et par classe sociale
  let total-students ([nb-favorises + nb-moyens + nb-defavorises] of school-agent)
  if total-students = 0 [ report 0 ] ; Si école vide, pas d'inconfort

  ; Calculer la proportion d'élèves similaires dans l'école
  let proportion-similar 0

  if my-class = "favorise" [
    set proportion-similar ([nb-favorises] of school-agent / total-students)
  ]
  if my-class = "moyen" [
    set proportion-similar ([nb-moyens] of school-agent / total-students)
  ]
  if my-class = "defavorise" [
    set proportion-similar ([nb-defavorises] of school-agent / total-students)
  ]

  ; Calculer l'inconfort: plus il y a d'élèves similaires au-delà du seuil de tolérance,
  ; moins il y a d'inconfort
  let discomfort 0

  ifelse proportion-similar >= my-tolerance
  [
    ; Si la proportion d'élèves similaires est suffisante, l'inconfort est inversement
    ; proportionnel à cette proportion
    set discomfort 1 - (proportion-similar / 1) ; 1 est le maximum théorique (100%)
  ]
  [
    ; Si la proportion est insuffisante, l'inconfort est maximal
    set discomfort 1
  ]

  report discomfort
end 

; Procédure de sélection des étudiants par les écoles avec respect strict de la capacité

to select-students
  ; Ne considérer que les élèves en attente qui ont choisi cette école
  let year1-students students with [xcor = [xcor] of myself and ycor = [ycor] of myself and waiting = true and year = 1]

  ; Calculer la capacité restante pour cette année
  let current-count count-students-in-year self 1
  let remaining-capacity capacity-per-year - current-count

  ; S'il n'y a plus de places ou pas d'élèves, terminer
  if remaining-capacity <= 0 or not any? year1-students [
    stop
  ]

  ; Limiter le nombre d'élèves à la capacité restante
  let nb-to-select min list remaining-capacity count year1-students

  ; Selon la politique active, sélectionner les élèves
  let selected-students nobody

  ifelse politique-quotas [
    ; Politique des quotas

    ; Compter les élèves actuels par classe sociale
    let school-favorises count students with [my-school = myself and social-class = "favorise" and not waiting]
    let school-moyens count students with [my-school = myself and social-class = "moyen" and not waiting]
    let school-defavorises count students with [my-school = myself and social-class = "defavorise" and not waiting]
    let total-in-school school-favorises + school-moyens + school-defavorises

    ; Calculer les ratios actuels
    let ratio-favorises ifelse-value (total-in-school > 0) [school-favorises / total-in-school][0]
    let ratio-moyens ifelse-value (total-in-school > 0) [school-moyens / total-in-school][0]
    let ratio-defavorises ifelse-value (total-in-school > 0) [school-defavorises / total-in-school][0]

    ; Facteur de correction pour accélérer le rééquilibrage
    let adjustment-factor 2  ; Peut être ajusté selon l'intensité souhaitée

    ; Calculer les proportions cibles ajustées
    let adjusted-prop-favorises ifelse-value (ratio-favorises < proportion-favorises)
    [proportion-favorises * adjustment-factor]
    [proportion-favorises]

    let adjusted-prop-moyens ifelse-value (ratio-moyens < proportion-moyens)
    [proportion-moyens * adjustment-factor]
    [proportion-moyens]

    let adjusted-prop-defavorises ifelse-value (ratio-defavorises < proportion-defavorises)
    [proportion-defavorises * adjustment-factor]
    [proportion-defavorises]

    ; Normaliser les proportions ajustées pour qu'elles somment à 1
    let sum-adjusted-props (adjusted-prop-favorises + adjusted-prop-moyens + adjusted-prop-defavorises)
    set adjusted-prop-favorises adjusted-prop-favorises / sum-adjusted-props
    set adjusted-prop-moyens adjusted-prop-moyens / sum-adjusted-props
    set adjusted-prop-defavorises adjusted-prop-defavorises / sum-adjusted-props

    ; Calculer les cibles avec les proportions ajustées
    let target-favorises ceiling (nb-to-select * adjusted-prop-favorises)
    let target-moyens ceiling (nb-to-select * adjusted-prop-moyens)
    let target-defavorises ceiling (nb-to-select * adjusted-prop-defavorises)

    ; Ajuster pour ne pas dépasser la capacité totale
    let ajustement-termine? false
    while [target-favorises + target-moyens + target-defavorises > nb-to-select and not ajustement-termine?] [
      if target-favorises > 0 [
        set target-favorises target-favorises - 1
        if target-favorises + target-moyens + target-defavorises <= nb-to-select [
          set ajustement-termine? true
        ]
      ]
      if not ajustement-termine? and target-moyens > 0 [
        set target-moyens target-moyens - 1
        if target-favorises + target-moyens + target-defavorises <= nb-to-select [
          set ajustement-termine? true
        ]
      ]
      if not ajustement-termine? and target-defavorises > 0 [
        set target-defavorises target-defavorises - 1
      ]
    ]

    ; Sélectionner les élèves par groupe social
    let favorises-to-admit year1-students with [social-class = "favorise"]
    let moyens-to-admit year1-students with [social-class = "moyen"]
    let defavorises-to-admit year1-students with [social-class = "defavorise"]

    ; Limiter par groupe
    let favorises-limit min list target-favorises count favorises-to-admit
    let moyens-limit min list target-moyens count moyens-to-admit
    let defavorises-limit min list target-defavorises count defavorises-to-admit

    ; Sélectionner
    let selected-favorises nobody
    let selected-moyens nobody
    let selected-defavorises nobody

    if favorises-limit > 0 and any? favorises-to-admit [
      set selected-favorises n-of favorises-limit favorises-to-admit
    ]

    if moyens-limit > 0 and any? moyens-to-admit [
      set selected-moyens n-of moyens-limit moyens-to-admit
    ]

    if defavorises-limit > 0 and any? defavorises-to-admit [
      set selected-defavorises n-of defavorises-limit defavorises-to-admit
    ]

    ; Combiner
    set selected-students (turtle-set selected-favorises selected-moyens selected-defavorises)

    ; S'il reste des places, compléter avec d'autres élèves
    let remaining-spots nb-to-select - count selected-students
    let remaining-students year1-students with [not member? self selected-students]

    if remaining-spots > 0 and any? remaining-students [
      set selected-students (turtle-set selected-students
        n-of (min list remaining-spots count remaining-students) remaining-students)
    ]
  ][
    ; Pas de politique de quotas
    ifelse not politique-mixite-sociale [
      ; Sans politique de mixité
      ifelse selectivite-ecoles = 0 [
        ; Mode aléatoire pur
        set selected-students n-of nb-to-select year1-students
      ][
        ; Mode avec sélection selon composition sociale (favorise homogénéité)
        let major-type "favorise"
        if nb-moyens > nb-favorises and nb-moyens > nb-defavorises [
          set major-type "moyen"
        ]
        if nb-defavorises > nb-favorises and nb-defavorises > nb-moyens [
          set major-type "defavorise"
        ]

        ; Sélection avec priorité au groupe majoritaire
        let first-priority year1-students with [social-class = major-type]
        let nb-prioritaires floor (nb-to-select * selectivite-ecoles)
        let nb-random floor (nb-to-select * (1 - selectivite-ecoles))

        ifelse count first-priority <= nb-prioritaires [
          set selected-students first-priority
          set nb-random (nb-to-select - count first-priority)
        ][
          set selected-students n-of nb-prioritaires first-priority
        ]

        let remaining-students year1-students with [not member? self selected-students]
        if any? remaining-students and nb-random > 0 [
          set selected-students (turtle-set selected-students
            n-of (min list nb-random count remaining-students) remaining-students)
        ]
      ]
    ][
      ; AVEC politique de mixité
      let school-favorises count students with [my-school = myself and social-class = "favorise" and not waiting]
      let school-moyens count students with [my-school = myself and social-class = "moyen" and not waiting]
      let school-defavorises count students with [my-school = myself and social-class = "defavorise" and not waiting]
      let total-in-school school-favorises + school-moyens + school-defavorises

      ; Calcul des proportions
      let prop-favorises ifelse-value (total-in-school > 0) [school-favorises / total-in-school][proportion-favorises]
      let prop-moyens ifelse-value (total-in-school > 0) [school-moyens / total-in-school][proportion-moyens]
      let prop-defavorises ifelse-value (total-in-school > 0) [school-defavorises / total-in-school][proportion-defavorises]

      ; Déterminer le type sous-représenté
      let target-prop-favorises proportion-favorises
      let target-prop-moyens proportion-moyens
      let target-prop-defavorises proportion-defavorises

      let under-represented-type "favorise" ; valeur par défaut

      ; Comparer les proportions
      if (prop-favorises < target-prop-favorises) and
         ((target-prop-favorises - prop-favorises) >= (target-prop-moyens - prop-moyens)) and
         ((target-prop-favorises - prop-favorises) >= (target-prop-defavorises - prop-defavorises)) [
        set under-represented-type "favorise"
      ]

      if (prop-moyens < target-prop-moyens) and
         ((target-prop-moyens - prop-moyens) >= (target-prop-favorises - prop-favorises)) and
         ((target-prop-moyens - prop-moyens) >= (target-prop-defavorises - prop-defavorises)) [
        set under-represented-type "moyen"
      ]

      if (prop-defavorises < target-prop-defavorises) and
         ((target-prop-defavorises - prop-defavorises) >= (target-prop-favorises - prop-favorises)) and
         ((target-prop-defavorises - prop-defavorises) >= (target-prop-moyens - prop-moyens)) [
        set under-represented-type "defavorise"
      ]

      ; Sélection du groupe sous-représenté
      let first-priority year1-students with [social-class = under-represented-type]

      ifelse selectivite-ecoles = 0 [
        ; Légère mixité même avec sélectivité 0
        let nb-mix floor (nb-to-select * 0.2)
        let nb-random (nb-to-select - nb-mix)

        ifelse count first-priority <= nb-mix [
          set selected-students first-priority
          set nb-random (nb-to-select - count first-priority)
        ][
          set selected-students n-of nb-mix first-priority
        ]

        let remaining-students year1-students with [not member? self selected-students]
        if any? remaining-students and nb-random > 0 [
          set selected-students (turtle-set selected-students
            n-of (min list nb-random count remaining-students) remaining-students)
        ]
      ][
        ; Force de mixité proportionnelle à la sélectivité
        let nb-prioritaires floor (nb-to-select * selectivite-ecoles)
        let nb-random floor (nb-to-select * (1 - selectivite-ecoles))

        ifelse count first-priority <= nb-prioritaires [
          set selected-students first-priority
          set nb-random (nb-to-select - count first-priority)
        ][
          set selected-students n-of nb-prioritaires first-priority
        ]

        let remaining-students year1-students with [not member? self selected-students]
        if any? remaining-students and nb-random > 0 [
          set selected-students (turtle-set selected-students
            n-of (min list nb-random count remaining-students) remaining-students)
        ]
      ]
    ]
  ]

  ; Traiter les élèves sélectionnés
  ask selected-students [
    set waiting false
    set my-school myself
    ; Position autour de l'école
    fd 3
    rt random 360
  ]

  ; Les élèves non sélectionnés doivent choisir une autre école
  ask year1-students with [not member? self selected-students] [
    ; Remettre en attente pour qu'ils puissent choisir une autre école
    ; Important: les retirer de la position actuelle pour qu'ils ne soient pas comptés comme candidats pour cette école
    setxy random-xcor random-ycor
  ]
end 

; Procédure pour ajouter une école en cours de simulation

to add-school
  ; Créer une nouvelle école
  create-schools 1 [
    set shape "house"
    set color 9.9
    set capacity-per-year school-capacity
    set nb-favorises 0
    set nb-moyens 0
    set nb-defavorises 0
    set size 3


     ; Repositionner toutes les écoles en cercle
  reposition-schools
  ]

  ; Mettre à jour les statistiques et l'affichage
  update-school-stats

  ; Informer de l'ajout
  print (word "Nouvelle école ajoutée. Nombre total d'écoles: " count schools)
end 

to reposition-schools
  let num-schools count schools
  let i 0
  ask schools [
    let angle (360 / num-schools) * i
    let radius 12
    setxy radius * sin angle radius * cos angle
    set i i + 1
  ]
end 

to reconsider-schools
  ask students [
    ; Remettre certains élèves en attente pour qu'ils reconsidèrent leur choix
    ; Par exemple, ceux qui sont les plus "inconfortables" dans leur école actuelle
    if calculate-discomfort self my-school > 0.7 [
      set waiting true
      setxy random-xcor random-ycor
    ]
  ]
end 

to remove-smallest-school
  ; Vérifier qu'il reste au moins 2 écoles
  if count schools < 2 [
    print "Impossible de supprimer l'école - il doit rester au moins une école dans le système."
    stop
  ]

  ; Sélectionner l'école avec le moins d'élèves
  let target-school min-one-of schools [count students with [my-school = myself]]

  ; Réaffecter les élèves de cette école
  ask students with [my-school = target-school] [
    set waiting true
    setxy random-xcor random-ycor
  ]

  ; Supprimer l'école
  ask target-school [die]

  ; Repositionner les écoles restantes
  reposition-schools

  ; Mettre à jour les statistiques
  update-school-stats

  ; Informer de la suppression
  print (word "École la moins peuplée supprimée. Nombre d'écoles restantes: " count schools)
end 

; Procédure go

to go
  ; Faire avancer les élèves d'une année
  ask students with [year > 0] [
    set year year + 1
    if year > 6 [ die ]  ; Les élèves sortent du système après 6 ans
  ]

  ; Créer de nouveaux élèves selon les proportions des sliders
  create-students total-students-per-year [
    set shape "person"
    set size 1
    set year 1
    set waiting true

    ; Distribution sociale selon les proportions définies par les sliders
    let r random-float 1
    ifelse r < proportion-favorises [
      set social-class "favorise"
    ] [
      ifelse r < (proportion-favorises + proportion-moyens) [
        set social-class "moyen"
      ] [
        set social-class "defavorise"
      ]
    ]

    ; Définir la couleur selon la classe sociale
    if social-class = "favorise" [ set color red ]
    if social-class = "moyen" [ set color green ]
    if social-class = "defavorise" [ set color blue ]

    ; Définir le seuil de tolérance selon la classe sociale
    if social-class = "favorise" [
      set tolerance tolerance-favorises
    ]
    if social-class = "moyen" [
      set tolerance tolerance-moyens
    ]
    if social-class = "defavorise" [
      set tolerance tolerance-defavorises
    ]

    ; Positionnement aléatoire initial (loin des écoles)
    setxy random-xcor random-ycor
  ]

  ; Itérer le processus de choix et de sélection
  let iteration 0
  let max-iterations 100
  let previous-waiting -1
  let current-waiting count students with [waiting = true]

  ; Continuer tant qu'il y a des élèves en attente et qu'on progresse
  while [current-waiting > 0 and iteration < max-iterations and (iteration = 0 or current-waiting < previous-waiting)] [
    set previous-waiting current-waiting

    ; Phase 1 : Les élèves en attente choisissent leur école préférée
    ask students with [waiting = true] [
      choose-preferred-school
    ]

    ; Phase 2 : Les écoles sélectionnent les élèves
    ask schools [
      select-students
    ]

    set iteration iteration + 1
    set current-waiting count students with [waiting = true]
  ]

  set iteration-count iteration

  ; Si après les itérations il reste des élèves en attente, les placer dans les écoles qui ont de la place
  if any? students with [waiting = true] [
    ask students with [waiting = true] [
      let available-schools schools with [has-capacity-for-year self 1]

      ifelse any? available-schools [
        ; Choisir l'école avec le moins d'inconfort parmi celles disponibles
        let best-school min-one-of available-schools [calculate-discomfort myself self]
        move-to best-school
        set waiting false
        set my-school best-school
        fd 3
        rt random 360
      ][
        ; Si vraiment aucune place, placer autour d'une école aléatoire sans l'assigner
        ; (cela indique une erreur de capacité dans le modèle)
        move-to one-of schools
        fd 3
        rt random 360
        ; Garder waiting = true pour les identifier facilement
      ]
    ]
  ]

  ; Mettre à jour les statistiques des écoles
  update-school-stats

  ; Mettre à jour les réseaux sociaux
  update-networks

  ; Après avoir mis à jour toutes les statistiques, enregistrer les données si l'export est activé
  if export-started? [
    collect-longitudinal-data
  ]

  tick
end 

; Procédure pour collecter les données à chaque tick

to collect-longitudinal-data
  ; Créer une entrée pour le tick actuel
  let tick-data (list ticks)

  ; Ajouter l'indice de ségrégation global
  set tick-data lput duncan-index-value tick-data

  ; Ajouter la diversité moyenne des réseaux
  set tick-data lput moyenne-diversite-reseaux tick-data

  ; Ajouter des données pour chaque école
  ask schools [
    let school-id who
    let total-students count students with [my-school = myself and not waiting]
    let pct-favorises (nb-favorises / total-students) * 100
    let pct-moyens (nb-moyens / total-students) * 100
    let pct-defavorises (nb-defavorises / total-students) * 100

    ; Ajouter les données de cette école
    set tick-data lput (list school-id total-students pct-favorises pct-moyens pct-defavorises) tick-data
  ]

  ; Ajouter ces données à notre collection
  set longitudinal-data lput tick-data longitudinal-data
end 


; Procédure pour vérifier les capacités des écoles

to display-stats
  print "===== Capacités des écoles ====="
  ask schools [
    let total-students count students with [my-school = myself and not waiting]
    let year1-students count students with [my-school = myself and year = 1 and not waiting]
    let year2-students count students with [my-school = myself and year = 2 and not waiting]
    let year3-students count students with [my-school = myself and year = 3 and not waiting]
    let year4-students count students with [my-school = myself and year = 4 and not waiting]
    let year5-students count students with [my-school = myself and year = 5 and not waiting]
    let year6-students count students with [my-school = myself and year = 6 and not waiting]

    ; Calculer les pourcentages par classe sociale
    let pct-favorises 0
    let pct-moyens 0
    let pct-defavorises 0

    if total-students > 0 [
      set pct-favorises (nb-favorises / total-students) * 100
      set pct-moyens (nb-moyens / total-students) * 100
      set pct-defavorises (nb-defavorises / total-students) * 100
    ]

    print (word "École " who ": " total-students " élèves au total (capacité: " (capacity-per-year * 6) ")")
    print (word "  Année 1: " year1-students " / " capacity-per-year)
    print (word "  Année 2: " year2-students " / " capacity-per-year)
    print (word "  Année 3: " year3-students " / " capacity-per-year)
    print (word "  Année 4: " year4-students " / " capacity-per-year)
    print (word "  Année 5: " year5-students " / " capacity-per-year)
    print (word "  Année 6: " year6-students " / " capacity-per-year)
    print (word "  Composition: " nb-favorises " favorisés (" precision pct-favorises 1 "%), "
                             nb-moyens " moyens (" precision pct-moyens 1 "%), "
                             nb-defavorises " défavorisés (" precision pct-defavorises 1 "%)")
    print (word "  Proportions cibles: favorisés: " precision (proportion-favorises * 100) 1 "%, "
                              "moyens: " precision (proportion-moyens * 100) 1 "%, "
                              "défavorisés: " precision (proportion-defavorises * 100) 1 "%")
  ]

  let waiting-students count students with [waiting = true]
  if waiting-students > 0 [
    print (word "ATTENTION: " waiting-students " élèves sont encore en attente!")
  ]

  ; Ajouter un résumé global
  let total-all-schools count students with [not waiting]
  if total-all-schools > 0 [
    let global-favorises count students with [social-class = "favorise" and not waiting]
    let global-moyens count students with [social-class = "moyen" and not waiting]
    let global-defavorises count students with [social-class = "defavorise" and not waiting]

    let global-pct-favorises (global-favorises / total-all-schools) * 100
    let global-pct-moyens (global-moyens / total-all-schools) * 100
    let global-pct-defavorises (global-defavorises / total-all-schools) * 100

    print "===== Résumé global du système ====="
    print (word "Total élèves: " total-all-schools)
    print (word "Composition globale: " global-favorises " favorisés (" precision global-pct-favorises 1 "%), "
                               global-moyens " moyens (" precision global-pct-moyens 1 "%), "
                               global-defavorises " défavorisés (" precision global-pct-defavorises 1 "%)")
    print (word "Indice de ségrégation (Duncan): " precision duncan-index-value 3)
    print (word "Diversité moyenne des réseaux: " precision moyenne-diversite-reseaux 3)
  ]
end 

to update-networks
  ; Supprimer tous les liens existants
  ask links [die]

  ; Créer des liens entre élèves de la même école
  ask students [
    ; Trouver les autres élèves de la même école
    let schoolmates other students with [my-school = [my-school] of myself]

    ; Créer des liens avec un échantillon aléatoire (ou tous si peu nombreux)
    let sample-size min list 20 count schoolmates
    if sample-size > 0 [
      create-links-with n-of sample-size schoolmates [
        ; Liens très fins et transparents pour ne pas encombrer la visualisation
        set thickness 0.2
        set color [185 185 185 50]  ; Gris très transparent
      ]
    ]

    ; Rendre les liens visibles ou non selon le switch
    ask my-links [
      ifelse show-links [
        show-link
      ][
        hide-link
      ]
    ]

    ; Calculer la diversité du réseau
    calculate-network-diversity
  ]

  ; Tracer la diversité des réseaux après avoir recalculé toutes les diversités
set-current-plot "Diversité des réseaux"
plot moyenne-diversite-reseaux
end 

to calculate-network-diversity
  ; Si pas de liens, diversité = 0
  if not any? link-neighbors [
    set network-diversity 0
    stop
  ]

  ; Compter les différents types dans le réseau
  let nb-linked-favorises count link-neighbors with [social-class = "favorise"]
  let nb-linked-moyens count link-neighbors with [social-class = "moyen"]
  let nb-linked-defavorises count link-neighbors with [social-class = "defavorise"]
  let total-links count link-neighbors

  ; Calculer l'indice de diversité (indice de Shannon)
  let p-favorises ifelse-value (total-links > 0) [nb-linked-favorises / total-links][0]
  let p-moyens ifelse-value (total-links > 0) [nb-linked-moyens / total-links][0]
  let p-defavorises ifelse-value (total-links > 0) [nb-linked-defavorises / total-links][0]

  ; Éviter log(0)
  let h-favorises ifelse-value (p-favorises > 0) [p-favorises * ln p-favorises][0]
  let h-moyens ifelse-value (p-moyens > 0) [p-moyens * ln p-moyens][0]
  let h-defavorises ifelse-value (p-defavorises > 0) [p-defavorises * ln p-defavorises][0]

  ; Indice de Shannon (normalisé entre 0 et 1)
  set network-diversity (- (h-favorises + h-moyens + h-defavorises)) / ln 3
end 

to-report moyenne-diversite-reseaux
  ifelse any? students [
    report mean [network-diversity] of students
  ][
    report 0
  ]
end 

to update-school-stats
 ask schools [
    set nb-favorises count students with [my-school = myself and social-class = "favorise" and waiting = false]
    set nb-moyens count students with [my-school = myself and social-class = "moyen" and waiting = false]
    set nb-defavorises count students with [my-school = myself and social-class = "defavorise" and waiting = false]
  ]

  ; Calcul de l'indice de Duncan pour les défavorisés
  let total-defavorises sum [nb-defavorises] of schools
  let total-autres sum [nb-favorises + nb-moyens] of schools

  set duncan-index-value 0 ; Initialiser à 0

  if total-defavorises > 0 and total-autres > 0 [
    set duncan-index-value 0.5 * sum [
      abs(
        (nb-defavorises / total-defavorises) -
        ((nb-favorises + nb-moyens) / total-autres)
      )
    ] of schools
  ]

  ; Mise à jour des graphiques
  set-current-plot "Indice de ségrégation (défavorisés)"
  plot duncan-index-value
end 

to check-quota-policy
  print word "Politique de quotas activée? " politique-quotas

  if politique-quotas [
    print "Quotas par école:"
    foreach [0 1 2 3] [ s-id ->
      let school-s school s-id
      let total-students count students with [my-school = school-s and not waiting]
      if total-students > 0 [
        let pct-favorises (count students with [my-school = school-s and social-class = "favorise" and not waiting]) / total-students
        let pct-moyens (count students with [my-school = school-s and social-class = "moyen" and not waiting]) / total-students
        let pct-defavorises (count students with [my-school = school-s and social-class = "defavorise" and not waiting]) / total-students

        print (word "École " s-id ": favorisés=" (precision (pct-favorises * 100) 1) "%, moyens="
               (precision (pct-moyens * 100) 1) "%, défavorisés=" (precision (pct-defavorises * 100) 1) "%")
      ]
    ]

    print (word "Cibles: favorisés=" (precision (proportion-favorises * 100) 1) "%, moyens="
           (precision (proportion-moyens * 100) 1) "%, défavorisés=" (precision (proportion-defavorises * 100) 1) "%")
  ]
end 

to export-student-data
  ; Créer un fichier CSV pour les données individuelles des élèves
  carefully [
    file-delete "student_data.csv"
  ]
  [
    ; Si le fichier n'existe pas, ignore l'erreur
  ]

  ; Créer l'en-tête du fichier
  file-open "student_data.csv"
  file-print "id,social_class,year,school_id,network_size,network_diversity,network_favorises,network_moyens,network_defavorises"

  ; Ajouter les données de chaque élève
  ask students [
    let network_size count link-neighbors
    let network_favorises count link-neighbors with [social-class = "favorise"]
    let network_moyens count link-neighbors with [social-class = "moyen"]
    let network_defavorises count link-neighbors with [social-class = "defavorise"]

    file-print (word
      who ","
      social-class ","
      year ","
      [who] of my-school ","
      network_size ","
      precision network-diversity 3 ","
      network_favorises ","
      network_moyens ","
      network_defavorises)
  ]

  file-close
  print "Données des élèves exportées dans 'student_data.csv'"
end 

to export-network-data
  ; Créer un fichier CSV pour les liens du réseau
  carefully [
    file-delete "network_data.csv"
  ]
  [
    ; Si le fichier n'existe pas, ignore l'erreur
  ]

  ; Créer l'en-tête du fichier
  file-open "network_data.csv"
  file-print "source_id,source_class,target_id,target_class,same_school,same_class"

  ; Ajouter les données de chaque lien
  ask links [
    let source-agent end1
    let target-agent end2
    let same-school? [my-school] of source-agent = [my-school] of target-agent
    let same-class? [social-class] of source-agent = [social-class] of target-agent

    file-print (word
      [who] of source-agent ","
      [social-class] of source-agent ","
      [who] of target-agent ","
      [social-class] of target-agent ","
      same-school? ","
      same-class?)
  ]

  file-close
  print "Données du réseau exportées dans 'network_data.csv'"
end 

; Procédure pour exporter les données longitudinales dans un fichier CSV

to export-longitudinal-data-to-csv
  if empty? longitudinal-data [
    print "Aucune donnée longitudinale à exporter. Utilisez d'abord start-longitudinal-export."
    stop
  ]

  ; Créer un nom de fichier basé sur la date et l'heure
  let timestamp format-datetime
  let filename (word "longitudinal_data_" timestamp ".csv")

  ; Essayer de supprimer le fichier s'il existe déjà
  carefully [ file-delete filename ] [ ]

  ; Ouvrir le fichier pour écriture
  file-open filename

  ; Écrire l'en-tête
  file-print "tick,segregation_index,avg_network_diversity,school_id,total_students,pct_favorises,pct_moyens,pct_defavorises"

  ; Écrire les données
  foreach longitudinal-data [ tick-info ->
    let current-tick item 0 tick-info
    let segregation-index item 1 tick-info
    let avg-diversity item 2 tick-info

    ; Pour chaque école dans ce tick
    foreach sublist tick-info 3 (length tick-info) [ school-info ->
      let school-id item 0 school-info
      let total-students item 1 school-info
      let pct-favorises item 2 school-info
      let pct-moyens item 3 school-info
      let pct-defavorises item 4 school-info

      ; Écrire une ligne pour cette école à ce tick
      file-print (word
        current-tick ","
        segregation-index ","
        avg-diversity ","
        school-id ","
        total-students ","
        pct-favorises ","
        pct-moyens ","
        pct-defavorises)
    ]
  ]

  file-close
  print (word "Données longitudinales exportées dans " filename)
end 

; Helper function for timestamp

to-report format-datetime
  let current-datetime date-and-time
  let date substring current-datetime 0 10
  let time substring current-datetime 11 19
  ; Remove colons from time for filename
  set time remove ":" time
  report (word date "_" time)
end 

There are 3 versions of this model.

Uploaded by When Description Download
Nathanaël Friant 1 day ago This model is a major update to the initial school segregation model. It simulates in a more realistic and comprehensive way the dynamics of segregation in a school system with a variable number of schools and three social categories of students, integrating new social mixing policies and improving the modeling of individual preferences Download this version
Nathanaël Friant 5 months ago Added school selectivity and made first choice random Download this version
Nathanaël Friant 5 months ago Initial upload Download this version

Attached files

File Type Description Last updated
Simple Quasi-Market.png preview Preview for 'Simple Quasi-Market' 5 months ago, by Nathanaël Friant Download

This model does not have any ancestors.

This model does not have any descendants.