HIV and Polygamy

HIV and Polygamy preview image

3 collaborators

Georges Reniers (Author)
Aaron Lucas (Author)

Tags

epidemiology 

Tagged by Benjamin Armbruster over 10 years ago

hiv 

Tagged by Benjamin Armbruster over 10 years ago

partnership concurrency 

Tagged by Benjamin Armbruster over 10 years ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 5.0.5 • Viewed 1024 times • Downloaded 79 times • Run 0 times
Download the 'HIV and Polygamy' modelDownload this modelEmbed this model

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


WHAT IS IT?

This NetLogo-based model is a microsimulation model of the relationship between HIV prevalence and sexual concurrency in a relatively small (under 15,000 people), closed population. The model is currently parameterized for a community in Zambia.

PROCEDURES

Age

All turtles age forward by one month (the equivalent of a tick), and each turtle�s age in years and in months is adjusted.

Become-infected

The turtle becomes infected with HIV. The turtle�s default color is also dimmed to indicate the infection.

Births

Both male and female turtles enter the population at a user-defined monthly birth-rate. Currently, this birth rate is not gender specific. Each turtle which enters the population has his/her age set at 15 years and is made male or female by the current ratio of males to females in the population. Number of partners are set to 0 and all turtle-own variables are instantiated.

Call-globals

Opens input files which parameterize male and female TPMs, population pyramid and distribution of time of seroconversion for the baseline turtles. Outside death rate is set as well as treatment-failure-rate and incidence counters.

Change-relationships

This procedure changes the relationship structure of the network. Each turtle can have at most one spousal relationship and three non-spousal relationships. The loaded male TPM serves as a discrete probability distribution which determines which male turtles will �request� a partner (spousal or non-spousal) or �lose� a partner during this iteration. Female turtles then fulfill each partnership request of the male turtles. The female TPM serves as a guide to determine which females in which current relationship status will fulfill these requests.

Deaths

Each turtle has an approx. probability of dying as determined by the outside death rate and a supplemental HAART death rate (if that turtle is infected with HIV and on treatment). If the turtle is infected and not on treatment, by construction, the turtle�s CD4-count declines proportionally to how many months the turtle (at the onset of infection) is given to live. When the CD4-count falls below 0, then the turtle�s life ends.

Determine-CD4-count

A turtle�s CD4-count declines according to the stage of infection and if the turtle is on treatment.

Determine-HIV-stage

Since ticks occur at the end of each iteration, acute infection of a turtle is defined as months being infected less than the acute duration. There are currently three stages of HIV infection: acute, chronic and final. The final stage is given as 15% of the total lifetime that each turtle spends infected, given that the turtle is not on treatment.

Determine-infectivity

As with Determine-HIV-stage, this procedure determines infectivity based on what the turtle�s current HIV stage is and if the turtle is on treatment. The chronic infectivity is user-inputted, and all other infectivities are defined as a proportion of this. The infectivity may be interpreted as the monthly probability of infecting one partner (both spousal and non-spousal). This incorporates coital frequency, transmission rates, etc.

Determine-supp-death-rates

Currently, the only supplement death rate (that is, the only death rate added to a turtle�s outside probability of dying each month) is a CD4-specific death rate when the turtle is on treatment. This death rate, the HAART-supp-death-rate, is based on what the turtle�s CD4-count was upon entry into treatment.

Exit-50s

Every turtle over the age of 50 and with no partners exits the population at each iteration to keep the majority of population�s age range between 15 and 50.

Initialize-HIV-population

The population of HIV-infected turtles is split up into those who are acutely infected and those who have already seroconverted. Given the percent of acutely-infected turtles in the population, we distribute uniformly (based on the acute duration) when that turtle was infected. For those who are seroconverted, we use a more involved scheme to determine when the turtle seroconverted. Since the beginning of the simulation represents an instant in time of an evolving epidemic, we cannot simply start out with everyone in one infected state. In other words, at any point in time of an epidemic, there is a distribution of when the seroconverted individuals were infected which determines the shape of the epidemic curve. Therefore, we use [1] to construct a discrete distribution of time of seroconversion for those who are not acutely infected. Since we assume original CD4-count is independent of time until death, we use the time of seroconversion to determine the current turtle�s CD4 count and months left to live. If the turtle was infected x years ago, we draw from a conditional Weibull distribution parameterized as in spread-HIV with the knowledge that the turtle has survived x years. This allows us to get close to steady-state distribution and reduce the amount of initial transient.

Progress-disease

Each infected turtle runs through a set of sub-procedures:
� Setting a new CD4-count
� Setting the current HIV stage
� Setting the current infectivity
� Setting any supplemental death rates
� Ticking months-since-infected and months-left-to-live accordingly

Put-on-treatment

If a turtle is infected with HIV and has a CD4-count that is less than a user-defined threshold, then the turtle is eligible to be put on HAART. Currently, we have a constant fraction of turtles in the population who can be on treatment. If there is an open treatment slot, then a random eligible turtle enters treatment and stays on treatment until they die.

Setup-nodes

A user-defined number of male turtles are created to initialize the population. Using the user-defined inputs of the proportion of married males and the proportion of males and females with zero, one, two or three partners, we create a logical amount of female turtles. These user-defined inputs also determine the distribution of males and females in the population who are in each relationship combination state. Females are matched to males until this discrete distribution is satisfied. Ages are also set according to the population pyramid.

INITIALIZING PARTNERSHIPS

Number-of-male-nodes are created and make-male is run for each of them.  Each of these turtles is initialized as having no partners.  We then determine how many partnership requests to add to these male turtles by splitting these turtles into three groups, those who have no partners, those who have a spouse and those who do not have a spouse.  [2] shows how to easily determine what the discrete distribution of spousal/non-spousal partnerships are for the males by the user-defined inputs of the overall partnership distribution and proportion of male spouses in the population.  Instead of assigning partnership status to these male nodes probabilitistically, we use these probabilities as proportions and divvy them up by iterating through who numbers.  
We then create female turtles.  First, we need to determine how many female turtles will be created based on the total amount of partnership requests from the males.  We then determine how many female spouses there are in the population by the simple assumption that there must be an equal number of females to satisfy the number of male spousal requests.  These relationships are all defined in [2].  We again use the same procedure as the male turtles when assigning partnership status to the female nodes.
For each partnership request of a male node, we randomly assign an �open� female with a similar request (that is, spousal/non-spousal) until all no partnerships can be formed.  This leaves at most three unmet partnership requests.  Since this is minute compared to the total number of partnership requests that were successfully fulfilled, we just downwardly adjust these turtles which could not be linked.  This has a negligible effect on the final discrete distribution of partnerships statuses of the turtles.

CHANGING PARTNERSHIPS

This procedure uses three inputs, all stored as lists in NetLogo.  The first, labeled R.txt, is just a list of the possible combinations of relationships statuses a turtle may have (e.g. (0,1) or (1,2), where the first coordinate indicates the number of spousal partners and the second indicates the number of non-spousal partners).  P_m.txt and P_f.txt are the respective TPM�s where each state is a relationship status ordered as in R.txt.  
The stochasticity of changing relationships in the model focuses on the males.  According to the discrete distribution for each state, every male turtle is assigned a partnership request, deletion, or no-change.  As we loop through the different states for the male turtles, we record the expected number of female turtles in each state shifting to each particular state according to the female TPM.  
All male turtles with a deletion of a partner are taken care of first.  Any females who are linked to these males may not fulfill a partnership request and are marked as such. 
We fulfill new spousal requests from male turtles by the following procedure.  First, we total up the amount of spousal requests from the male turtles.  We next take the expected number of new spouses added to population if we were to rely on the female TPM.  These two quantities might not be equal.  Thus, we take the proportion of new spouses responsible from each female turtle relationship status (as defined in R.txt) and divvy up the spousal requests from the males to the females according to this distribution.  By the optimization problem defined in [2], this should still allow a stable partnership distribution over time.  Non-spousal partnerships are added in a similar manner using those females who were not used in the spousal procedure.

SPREADING HIV

All link neighbors of an infected turtle may become infected at a given iteration.  Each connected turtle to an infected turtle has a certain probability of becoming infected, an attribute given to the infected turtle.  NetLogo loops through each infected turtle and randomly infects her link-neighbors according to this probability.  Once a turtle becomes newly infected, the following occurs:
� Infected? Is set to true
� Months-left-to-live is calculated from a Weibull distribution with              parameters 10.9522 and 2.25 (a median of 10 years left to live)
� An indicator for 10% of the infected lifespan is calculated, which gives            the time spent in the final stage, or AIDS
� The rate at which the turtle�s CD4 count declines is established.  This               is a constant rate which declines linearly to zero as the                   months-left-to-live variable declines to zero. 

THINGS TO NOTICE

This section could give some ideas of things for the user to notice while running the model.

THINGS TO TRY

This section could give some ideas of things for the user to try to do (move sliders, switches, etc.) with the model.

EXTENDING THE MODEL

This section could give some ideas of things to add or change in the procedures tab to make the model more complicated, detailed, accurate, etc.

NETLOGO FEATURES

This section could point out any especially interesting or unusual features of NetLogo that the model makes use of, particularly in the Procedures tab. It might also point out places where workarounds were needed because of missing features.

RELATED MODELS

This section could give the names of models in the NetLogo Models Library or elsewhere which are of related interest.

CREDITS AND REFERENCES

This section could contain a reference to the model's URL on the web if it has one, as well as any other necessary credits or references.

Comments and Questions

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

Click to Run Model

; 6/30/10 - added simple birth and death rates
; 6/30/10 - added plots
; 8/10/10 - more plots
;         - % on treatment (total; < 200;  200 - 350; 350 - 500)
;         - Incidence (total; due to acute; due to chronic)
;         - % infected (total; acute; chronic)
;         - more inputs
;         - treatment threshold (CD4 count)
;         - entry rate
;         - acute duration
;         - initial percent infected
;         - initial percent acute
;         - proportion on treatment

undirected-link-breed [
  non-spousal-links non-spousal-link
]
undirected-link-breed [
  spousal-links spousal-link
  ]

globals [
  Pyramid
  f-add-prob ; item i of f-add-prob applies when node in state item i of R
  ; item i is a list [a b c] where a is the probability of not adding any links, b of a spousal link, and c of a non-spousal link
  m-add-prob ; similar for males
  P_m ;Transition Probability Matrix
  P_f ;Transition Probability Matrix
  R ;List of possible relationship combinations
  MtoF-ratio
  male-remarry-pos-odds ;odds and ever-married? infected will have a new relationship
  female-remarry-pos-odds
  sero-sorting-odds ;odds one chooses partner with same sero-status (is everything symmetric???)
  ever-married-pos-choose-polygamous-odds   ; odds that ever-married HIV+/- women choose a husband who already has a partner
  ever-married-neg-choose-polygamous-odds
  F+M-divorce-odds ;relative risk of a discordant couple disolving
  F-M+divorce-odds
  relative-coital-freq
  number-of-female-nodes
  male-proportion-spousal 
  female-proportion-spousal
  male-proportion-0
  male-proportion-1
  male-proportion-2
  male-proportion-3
  male-proportion-4
  female-proportion-0
  female-proportion-1
  female-proportion-2
  female-proportion-3
  female-proportion-4
  entry-rate-m ;ignored here
  entry-rate-f
  spousal-change-rate
  non-spousal-change-rate
  t-hat
  t-hat-probs
  m15 m16 m17 m18 m19 m20
  m21 m22 m23 m24 m25 m26 m27 m28 m29 m30
  m31 m32 m33 m34 m35 m36 m37 m38 m39 m40
  m41 m42 m43 m44 m45 m46 m47 m48 m49
  f15 f16 f17 f18 f19 f20
  f21 f22 f23 f24 f25 f26 f27 f28 f29 f30
  f31 f32 f33 f34 f35 f36 f37 f38 f39 f40
  f41 f42 f43 f44 f45 f46 f47 f48 f49

  total-deaths
  curr-component-size ; for recursion
  component-size ; list of component sizes (one per component)
  
  outside-death-rate   
  current-yearly-incidence
  current-yearly-incidence-acute
  current-yearly-incidence-chronic
  current-yearly-incidence-final
  current-yearly-incidence->1-partner
  current-yearly-incidence-1-partner
  current-yearly-incidence-non-spousal
  current-yearly-incidence-spousal
  cum-infections
  cum-infections-acute
  
  run-number
]

to startup
    carefully [
      file-open "default.txt"
      while [not file-at-end?] [
        run file-read-line
      ]
      file-close
    ] [print error-message]
    
  set male-proportion-4 0
  set female-proportion-4 0
end 

turtles-own [
  randnum
  num-partners
  num-non-spousal-partners
  num-spousal-partners
  num-non-spousal-missing
  num-spousal-missing
  num-non-spousal-requests
  num-spousal-requests
  ever-married? ;actually both types of relationships
  age-years
  age-months
  female?
  infected?
  explored?
  
  ; HIV Variables
  stage-3-indicator
  months-since-infected
  months-left-to-live
  infectivity
  HIV-stage
  CD4-count-original
  CD4-count-present
  CD4-at-treatment
  CD4-decline-rate-no-treatment
  on-treatment?
  eligible-for-treatment?
  failed-treatment?
  time-on-treatment 
  HAART-supp-death-rate
]

to go
  age
  deaths-births
  progress-disease
  put-on-treatment
  spread-HIV
  change-relationships
  find-all-components
  plot-statistics
  tick
  ;if ticks = 120 [ stop ]
  ;if current-incidence != current-incidence-acute + current-incidence-chronic [ stop ]
end 

to setup-keep
  setup
  set run-number run-number + 1  
end 

to setup-clear
  clear-drawing
  clear-all-plots
  clear-output
  call-globals
  setup
  set run-number 1
end 

to setup
  clear-patches
  ask patches [set pcolor white] ; turns world white
  auto-plot-on
  set-default-shape turtles "person"
  
;  let tuned-prob-file (word scenario "T.txt")
;  ifelse (file-exists? tuned-prob-file) [
;    file-open tuned-prob-file
;    while [not file-at-end?] [ run file-read-line ]
;    file-close
;  ] [ ;otherwise tune probabilities and write them to file
    clear-turtles  
    reset-ticks
    setup-nodes
    initialize-HIV-population
    put-on-treatment
    ask non-spousal-links [set color black]
    ask spousal-links [set color red]
    ask turtles [set size 10 ]  
    repeat 120 [
      age
      deaths-births
      progress-disease
      put-on-treatment
      spread-HIV
      change-relationships
      tweak-probs
      tick
    ]
;    file-open tuned-prob-file
;    file-print (word "set m-add-prob " m-add-prob)
;    file-print (word "set f-add-prob " f-add-prob)
;    file-close
;  ]
  
  clear-turtles
  reset-ticks
  setup-nodes
  initialize-HIV-population
  put-on-treatment
  ask non-spousal-links [set color black]
  ask spousal-links [set color red]
  ask turtles [set size 10 ]
  set cum-infections 0
  set cum-infections-acute 0
  
  find-all-components
end 

; tweaks the new relationship probabilities to better match the desired distribution
; uses simulation optimization

to tweak-probs
  let m-props (list male-proportion-0 male-proportion-1 male-proportion-2 male-proportion-3)
  let f-props (list female-proportion-0 female-proportion-1 female-proportion-2 female-proportion-3)
  
  let f-curr-probs (n-values 4 [count turtles with [female? and num-partners = ?] / count turtles with [female?]])
  let m-curr-probs (n-values 4 [count turtles with [not female? and num-partners = ?] / count turtles with [not female?]])
  let f-ratio (map [(?2 + 1) / (?1 + 1)] f-props f-curr-probs)
  let m-ratio (map [(?2 + 1) / (?1 + 1)] m-props m-curr-probs)
  let new-m-add-prob []
  let new-f-add-prob []
  (foreach R m-add-prob f-add-prob [
    let partner-num (sum ?1)
    let f-ratio-num (item partner-num f-ratio)
    let m-ratio-num (item partner-num m-ratio)
    let m-prob-1 ((item 1 ?2) * m-ratio-num)
    let m-prob-2 ((item 2 ?2) * m-ratio-num)
    let f-prob-1 ((item 1 ?3) * f-ratio-num)
    let f-prob-2 ((item 2 ?3) * f-ratio-num)
    let m-prob (list (1 - m-prob-1 - m-prob-2) m-prob-1 m-prob-2)
    let f-prob (list (1 - f-prob-1 - f-prob-2) f-prob-1 f-prob-2)
    set new-m-add-prob (lput m-prob new-m-add-prob)
    set new-f-add-prob (lput f-prob new-f-add-prob)
  ])
  set m-add-prob new-m-add-prob
  set f-add-prob new-f-add-prob
end 

to ignore [stuff]
end 

to call-globals
  file-open (word scenario "P.txt")
  ignore file-read-line
  set P_f file-read
  ignore file-read-line
  set P_m file-read
  file-close
  
;  let Pyramid []
;  carefully [
;      file-open "default.txt"
;      while [not file-at-end?] [
;        run file-read-line
;      ]
;      file-close
;    ] [print error-message]
  file-open (word scenario ".txt")
  while [not file-at-end?] [
   run file-read-line
  ]
  file-close

  foreach Pyramid [
    let lower item 0 ?
    let upper item 1 ?
    let m item 2 ?
    let f item 3 ?
    ;show lower show upper show m show f
    (foreach (n-values (upper - lower + 1) [word "m" (? + lower)]) (n-values (upper - lower + 1) [word "f" (? + lower)]) [
        run ((word "set " ?1 word " " (m / (upper - lower + 1))))
        run ((word "set " ?2 word " " (f / (upper - lower + 1))))
    ])
  ]
  
  ; create m-add-prob and f-add-prob here (should probably be done in matlab and in the P files)
  set m-add-prob []
  set f-add-prob []
  (foreach R P_m P_f [ ; R entry is current state
    let new-state-1 (position (list ((item 0 ?1) + 1) (item 1 ?1)) R) ; index into R with extra spouse
    let new-state-2 (position (list (item 0 ?1) ((item 1 ?1) + 1)) R) ; index into R with extra non-spouse
    let m-prob-1 0
    let f-prob-1 0
    let m-prob-2 0
    let f-prob-2 0
    if new-state-1 != false [
      set m-prob-1 (item new-state-1 ?2)
      set f-prob-1 (item new-state-1 ?3)
    ]
    if new-state-2 != false [
      set m-prob-2 (item new-state-2 ?2)
      set f-prob-2 (item new-state-2 ?3)
    ]
    let m-prob (list (1 - m-prob-1 - m-prob-2) m-prob-1 m-prob-2)
    let f-prob (list (1 - f-prob-1 - f-prob-2) f-prob-1 f-prob-2)
    set m-add-prob (lput m-prob m-add-prob)
    set f-add-prob (lput f-prob f-add-prob)
  ])
  
  set current-yearly-incidence 0
  set current-yearly-incidence-acute 0
  set current-yearly-incidence-chronic 0
end 

to turtles-own-default
  set ever-married? (any? my-links)
  
  set infected? false

  ;; HIV Variables
  set months-since-infected 0
  set months-left-to-live 0
  set infectivity 0
  set HIV-stage 0
  set on-treatment? false
  set eligible-for-treatment? false
  set failed-treatment? false
  set time-on-treatment 0
  set HAART-supp-death-rate 0
  
  ;; Set CD4-count-present 
  set CD4-count-original exp ((ln 1116) + ((random-normal 0 1) * .303))
  set CD4-count-present CD4-count-original
  set CD4-decline-rate-no-treatment 0
  set stage-3-indicator 0
end 

to make-male
  setxy (random-xcor * .95) (random-ycor * .95)
  set color blue
  set female? false
end 

to make-female
  setxy (random-xcor * .95) (random-ycor * .95)
  set color pink
  set female? true
end 

to setup-nodes  
  crt number-of-male-nodes [
    make-male
  ]
  ask turtles [
      set num-partners 0
      set num-non-spousal-partners 0
      set num-spousal-partners 0
  ]
  let last-cut-off 0
  let current-cut-off round(male-proportion-0 * number-of-male-nodes)
  (foreach (list (male-proportion-1) (male-proportion-2) (male-proportion-3) (male-proportion-4)) ([1 2 3 4])  [
      set last-cut-off current-cut-off
      set current-cut-off (last-cut-off + round(number-of-male-nodes * (?1 / (1 - male-proportion-0)) * (1 - male-proportion-spousal - male-proportion-0)))  
      ;show (word last-cut-off " " current-cut-off)   
      ask turtles with [who + 1 > last-cut-off and who + 1 <= current-cut-off] [
        set num-partners ?2
        set num-non-spousal-partners ?2
        set num-spousal-partners 0
      ]
  ])
  (foreach (list (male-proportion-1) (male-proportion-2) (male-proportion-3) (male-proportion-4)) ([0 1 2 3])  [
      set last-cut-off current-cut-off
      set current-cut-off (last-cut-off + round(number-of-male-nodes * (?1 / (1 - male-proportion-0)) * male-proportion-spousal))  
      ;show (word last-cut-off " " current-cut-off)     
      ask turtles with [who + 1 > last-cut-off and who + 1 <= current-cut-off] [
        set num-partners ?2 + 1
        set num-non-spousal-partners ?2
        set num-spousal-partners 1
      ]
  ])

  ; create female turtles to match number of links of male turtles
  let number-of-male-links (count turtles with [not female? and num-partners = 1]) + 2 * (count turtles with [not female? and num-partners = 2]) + 3 * (count turtles with [not female? and num-partners = 3]) + 4 * (count turtles with [not female? and num-partners = 4])
  set number-of-female-nodes round(number-of-male-links / ((female-proportion-1 + 2 * female-proportion-2 + 3 * female-proportion-3 + 4 * female-proportion-4)))
  ; define female-proportion-spousal
  set female-proportion-spousal ((number-of-male-nodes * male-proportion-spousal) / number-of-female-nodes)
  crt number-of-female-nodes [
    make-female
  ]
  ask turtles with [female?] [
      set num-partners 0
      set num-non-spousal-partners 0
      set num-spousal-partners 0
  ]
  set last-cut-off 0
  set current-cut-off round(female-proportion-0 * number-of-female-nodes)
  (foreach (list (female-proportion-1) (female-proportion-2) (female-proportion-3) (female-proportion-4)) ([1 2 3 4])  [
      set last-cut-off current-cut-off
      set current-cut-off (last-cut-off + round(number-of-female-nodes * (?1 / (1 - female-proportion-0)) * (1 - female-proportion-spousal - female-proportion-0)))  
      ;show (word last-cut-off " " current-cut-off)   
      ask turtles with [who + 1 - number-of-male-nodes > last-cut-off and who + 1 - number-of-male-nodes <= current-cut-off] [
        set num-partners ?2
        set num-non-spousal-partners ?2
        set num-spousal-partners 0
      ]
  ])
  (foreach (list (female-proportion-1) (female-proportion-2) (female-proportion-3) (female-proportion-4)) ([0 1 2 3])  [
      set last-cut-off current-cut-off
      set current-cut-off (last-cut-off + round(number-of-female-nodes * (?1 / (1 - female-proportion-0)) * female-proportion-spousal))  
      ;show (word last-cut-off " " current-cut-off)     
      ask turtles with [who + 1 - number-of-male-nodes > last-cut-off and who + 1 - number-of-male-nodes <= current-cut-off] [
        set num-partners ?2 + 1
        set num-non-spousal-partners ?2
        set num-spousal-partners 1
      ]
  ])  
  ask turtles [
    set num-non-spousal-missing num-non-spousal-partners
    set num-spousal-missing num-spousal-partners
    set age-years -1
    set age-months -1
  ]
  
  let number-of-female-links (count turtles with [female? and num-partners = 1]) + 2 * (count turtles with [female? and num-partners = 2]) + 3 * (count turtles with [female? and num-partners = 3]) + 4 * (count turtles with [female? and num-partners = 4])
  ;show (word number-of-female-links " " number-of-male-links)
  
  ask turtles with [num-non-spousal-missing > 0 or num-spousal-missing > 0] [
    while [num-spousal-missing > 0 and (any? other turtles with [(female? = not ([female?] of myself)) and num-spousal-missing > 0 and (link-neighbor? myself = false)])] [
      ask one-of turtles with [(female? = not ([female?] of myself)) and num-spousal-missing > 0] [
        create-spousal-link-with myself [
          ask both-ends [set num-spousal-missing num-spousal-missing - 1]
        ]
      ]
    ]
    while [num-non-spousal-missing > 0 and (any? other turtles with [(female? = not ([female?] of myself)) and num-non-spousal-missing > 0 and (link-neighbor? myself = false)])] [
      ask one-of turtles with [(female? = not ([female?] of myself)) and num-non-spousal-missing > 0] [
        create-non-spousal-link-with myself [
          ask both-ends [set num-non-spousal-missing num-non-spousal-missing - 1]
        ]
      ]
    ]   
  ] 
  
  ask turtles with [num-non-spousal-missing > 0] [
    set num-partners num-partners - num-non-spousal-missing
    set num-non-spousal-partners num-non-spousal-partners - num-non-spousal-missing
    set num-spousal-missing 0
  ]
  ask turtles with [num-spousal-missing > 0] [
    set num-partners num-partners - num-spousal-missing
    set num-spousal-partners num-spousal-partners - num-spousal-missing
    set num-non-spousal-missing 0
  ]
  
  (foreach (n-values 35 [runresult (word "m" (? + 15))]) (n-values 35 [? + 15]) [
      ask n-of (min (list (round(number-of-male-nodes * ?1)) (count turtles with [age-years = -1 and not female?]))) turtles with [age-years = -1 and not female?] [
        set age-months (?2 * 12 + (random 12))
        set age-years (age-months / 12)
      ]
  ])
  (foreach (n-values 35 [runresult (word "f" (? + 15))]) (n-values 35 [? + 15]) [
      ask n-of (min (list (round(number-of-female-nodes * ?1)) (count turtles with [age-years = -1 and female?]))) turtles with [age-years = -1 and female?] [
        set age-months (?2 * 12 + (random 12))
        set age-years (age-months / 12)
      ]
  ])

  ask non-spousal-links [set color black]
  ask spousal-links [set color red]
  
  
  ;; Initialize turtles with default turtles-own values
  ask turtles [
    turtles-own-default
  ]
end 

to change-relationships
  ; setup book keeping
  ask turtles [
    set num-spousal-requests false
    set num-non-spousal-requests false
  ]
  
  ;deleting links
  ask non-spousal-links [
    let multiplier 1
    if (any? both-ends with [infected? and female?]) and (any? both-ends with [not infected? and not female?]) [
      set multiplier F+M-divorce-odds
    ]
    if (any? both-ends with [not infected? and female?]) and (any? both-ends with [infected? and not female?]) [
      set multiplier F-M+divorce-odds
    ]
    if ((random-float 1) < non-spousal-change-rate * multiplier) [
        die
    ]
  ]
  ask spousal-links [
    let multiplier 1
    if (any? both-ends with [infected? and female?]) and (any? both-ends with [not infected? and not female?]) [
      set multiplier F+M-divorce-odds
    ]
    if (any? both-ends with [not infected? and female?]) and (any? both-ends with [infected? and not female?]) [
      set multiplier F-M+divorce-odds
    ]
    if ((random-float 1) < spousal-change-rate * multiplier) [
        die
    ]
  ]
  
  ; creating requests for new links
  ask turtles [
    let rownum (position (list num-spousal-partners num-non-spousal-partners) R)
    let pmf []
    ifelse female? [
      set pmf (item rownum f-add-prob)
    ] [
      set pmf (item rownum m-add-prob)
    ]
    if ever-married? [
      let multiplier 1
      if infected? [ifelse female? [set multiplier female-remarry-pos-odds] [set multiplier male-remarry-pos-odds]]
      let p0 (item 0 pmf)
      set p0 (p0 / ((1 - p0) * multiplier + p0))
      let p1 0
      if p0 < 1 [set p1 ((1 - p0) * ((item 1 pmf) / (1 - (item 0 pmf))))]
      set pmf (list p0 p1 (1 - p0 - p1))
    ]
    let change (random-discrete pmf)
    if change = 1 [ set num-spousal-requests true ]
    if change = 2 [ set num-non-spousal-requests true ]
  ]
  
  ; create links
  ask turtles with [ num-spousal-requests or num-non-spousal-requests ] [
    if num-spousal-requests [
      set num-spousal-requests false
      let eligible turtles with [ (female? = not [female?] of myself) ; opposite gender
          and num-spousal-requests and (link-neighbor? myself = false)]
      if any? eligible [
        if female? and ever-married? [set eligible (ever-married-filter eligible)]
        set eligible (sero-sorting-filter eligible)
        ask one-of eligible [
          create-spousal-link-with myself
          set num-spousal-requests false
        ]
      ]
    ]
    if num-non-spousal-requests [
      set num-non-spousal-requests false
      let eligible turtles with [ (female? = not [female?] of myself) ; opposite gender
          and num-non-spousal-requests and (link-neighbor? myself = false)]
      if any? eligible [
        if female? and ever-married? [set eligible (ever-married-filter eligible)]
        set eligible (sero-sorting-filter eligible)
        ask one-of eligible [
          create-non-spousal-link-with myself
          set num-non-spousal-requests false
        ]
      ]
    ]
  ]
  
  ; update book keeping
  ask turtles [
    set num-partners (count my-links)
    set num-spousal-partners (count my-spousal-links)
    set num-non-spousal-partners (count my-non-spousal-links)
    set ever-married? (ever-married? or num-partners >= 1)
  ]
  
  ask non-spousal-links [set color black]
  ask spousal-links [set color red]
end 

to initialize-HIV-population
  ; This is the acute infection population
  let initial-percent-acute (item 0 t-hat-probs) * (acute-duration / 12)
  set t-hat-probs replace-item 0 t-hat-probs ((item 0 t-hat-probs) - initial-percent-acute)
  let adjustment-factor sum t-hat-probs
  
  (foreach (n-values acute-duration [?]) [
        ask n-of round ((initial-percent-acute / acute-duration) * ((initial-percent-infected) * (count turtles))) turtles [
          set months-since-infected ?1
          become-infected
          set months-left-to-live (random-weibull 10.9522 2.25) + (acute-duration - ?1)
          set stage-3-indicator (months-left-to-live - acute-duration + ?1) * .1
          set CD4-decline-rate-no-treatment (CD4-count-present * .75) / (months-left-to-live - acute-duration + ?1)
          set CD4-count-present CD4-count-present - (?1 * ((CD4-count-original * .25) / acute-duration))
        ]
  ])
  ; Now, we'll infect those in the chronic/final stages of HIV by...
  ; Determining how long ago when they seroconverted
  ; Determining how much longer they have to live
  ; Then determining the rate of CD4 decline and starting CD4 value by 
  ; how much longer they are scheduled to live 


  ask n-of ((initial-percent-infected * count turtles) - count turtles with [infected?]) turtles with [not infected?] [
    become-infected
    let lower 0
    let upper 0
    set randnum random-float adjustment-factor
    (foreach t-hat-probs t-hat [
      set lower upper
      set upper upper + ?1
      if randnum < upper and randnum >= lower [
        set months-since-infected ?2 * 12
        set months-left-to-live (12 * 10.5922 * ((((?2 / 10.5922) ^ (2.25)) - ln (1 - random-float 1)) ^ (1 / 2.25))) - (?2 * 12)
        set CD4-decline-rate-no-treatment (CD4-count-original * .75) / (months-since-infected + months-left-to-live)
        set CD4-count-present (CD4-count-original * .75) - (CD4-decline-rate-no-treatment * months-since-infected) 
        set stage-3-indicator .1 * (months-left-to-live + (?2 * 12))
      ]
    ])      
  ]
end 

to age
  ask turtles [
    set age-months age-months + 1
    set age-years age-months / 12
  ]
end 

to deaths-births
  let num-deaths 0
  ask turtles [
    ;; Note: deaths are not age/gender specific
    ; (not any? link-neighbors) and ; 
    if ((random-float 1 < outside-death-rate + HAART-supp-death-rate) or (CD4-count-present <= 0) or (age-years >= 50)) [
      ask my-links [
        die
      ]
      set num-deaths (num-deaths + 1)
      set age-months 15 * 12
      set age-years 15
      turtles-own-default
    ]
  ]
  ;; Remember to reset num-partners, etc. after links disappear (this needs to be in separate block
  ;; since (ask turtles) performs code for each turtle and not in unison
  ask turtles [
    set num-partners (count my-links)
    set num-spousal-partners (count my-spousal-links)
    set num-non-spousal-partners (count my-non-spousal-links)
  ]
  
  set total-deaths (total-deaths + num-deaths)
  set-current-plot "births and deaths"
  plot num-deaths
end 

to progress-disease
  ask turtles with [infected?] [
    determine-HIV-stage
    determine-CD4-count
    determine-infectivity
    determine-supp-death-rates
    set months-since-infected months-since-infected + 1
    set months-left-to-live months-left-to-live - 1
  ]
end 

to determine-HIV-stage
  if (months-since-infected < acute-duration) [
    set HIV-stage 1
  ]
  if (months-since-infected >= acute-duration) [
    if months-left-to-live < stage-3-indicator [ set HIV-stage 3 ]
    if months-left-to-live >= stage-3-indicator [ set HIV-stage 2 ]
  ]
end 

to determine-infectivity
  ifelse (on-treatment?) 
  [ 
    set infectivity chronic-infectivity * treatment-infectivity-ratio
  ]
  [ 
    if (HIV-stage = 1) [ set infectivity chronic-infectivity * acute-infectivity-ratio ]
    if (HIV-stage = 2) [ set infectivity chronic-infectivity ]
    if (HIV-stage = 3) [ set infectivity chronic-infectivity * final-infectivity-ratio ]
  ]
  if (num-partners > 1) [
    set infectivity infectivity * (item (num-partners - 2) relative-coital-freq)
  ]
  if (not female?) [
    set infectivity infectivity * MtoF-ratio
  ]
end  

to determine-supp-death-rates
  ask turtles with [infected?] [
    ifelse (on-treatment?) [
      if CD4-at-treatment <= 25 [ set HAART-supp-death-rate .175 / 12 ]
      if CD4-at-treatment > 25 and CD4-at-treatment <= 50 [ set HAART-supp-death-rate .121 / 12 ]
      if CD4-at-treatment > 50 and CD4-at-treatment <= 100 [ set HAART-supp-death-rate .738 / 12 ]
      if CD4-at-treatment > 100 and CD4-at-treatment <= 200 [ set HAART-supp-death-rate .483 / 12 ]
      if CD4-at-treatment > 200 and CD4-at-treatment <= 250 [ set HAART-supp-death-rate .05 / 12 ]
      if CD4-at-treatment > 250 and CD4-at-treatment <= 350 [ set HAART-supp-death-rate .05 / 12 ]
      if CD4-at-treatment > 350 and CD4-at-treatment <= 500 [ set HAART-supp-death-rate .03 / 12 ]
      if CD4-at-treatment > 500 [ set HAART-supp-death-rate .015 / 12 ]
    ]
    [
      set HAART-supp-death-rate 0
    ]
  ]
end 

to determine-CD4-count
  ifelse (on-treatment?) [
    ifelse (failed-treatment?) 
    [ set CD4-count-present CD4-count-present - CD4-decline-rate-no-treatment ]
    [ set CD4-count-present CD4-count-present ]
  ]
  [ 
    ifelse (HIV-stage = 1)
      [ set CD4-count-present CD4-count-present - ((CD4-count-original * .25) / acute-duration) ]
      [ set CD4-count-present CD4-count-present - CD4-decline-rate-no-treatment ]
  ]
end 

to spread-HIV
  if ((ticks mod 12) = 0) [
    set current-yearly-incidence-acute 0
    set current-yearly-incidence-chronic 0
    set current-yearly-incidence-final 0
    set current-yearly-incidence->1-partner 0    
    set current-yearly-incidence-1-partner 0
    set current-yearly-incidence-non-spousal 0
    set current-yearly-incidence-spousal 0
    set current-yearly-incidence 0
  ]
  
  ask turtles with [infected? = true] [
    ask link-neighbors with [infected? = false] [
      if random-float 1 < ([infectivity] of myself) [
        become-infected
        set months-left-to-live (random-weibull 10.9522 2.25) + acute-duration
        set stage-3-indicator (months-left-to-live - acute-duration) * .1
        set CD4-decline-rate-no-treatment (CD4-count-present * .75) / (months-left-to-live - acute-duration)
        set cum-infections cum-infections + 1
        if (([HIV-stage] of myself) = 1) [
          set current-yearly-incidence-acute current-yearly-incidence-acute + 1
          set cum-infections-acute cum-infections-acute + 1
          ]
        if (([HIV-stage] of myself) = 2) [
          set current-yearly-incidence-chronic current-yearly-incidence-chronic + 1
          ]
        if (([HIV-stage] of myself) = 3) [
          set current-yearly-incidence-final current-yearly-incidence-final + 1
        ]
        if (([num-partners] of myself) > 1) [
          set current-yearly-incidence->1-partner current-yearly-incidence->1-partner + 1
          ]
        if (([num-partners] of myself) = 1) [
          set current-yearly-incidence-1-partner current-yearly-incidence-1-partner + 1
          ]
        if (non-spousal-link-neighbor? myself) [
          set current-yearly-incidence-non-spousal current-yearly-incidence-non-spousal + 1 
        ]      
        if (spousal-link-neighbor? myself) [
          set current-yearly-incidence-spousal current-yearly-incidence-spousal + 1  
        ]
      ]
    ]
  ]
  
  ;; Calculate Incidence
  set current-yearly-incidence current-yearly-incidence + (count turtles with [infected? and months-since-infected = 0])
end 

to become-infected
  set infected? true
  if female? = true [set color pink - 2]
  if female? = false [set color blue - 2]
end 

to put-on-treatment
  ; tick time-on-treatment variable for those on treatment
  ask turtles with [on-treatment?] [
    set time-on-treatment time-on-treatment + 1
    ; determine if the treatment has failed
    ;if (not failed-treatment?) [
     ; if (random-float 1 < treatment-failure-rate) [
     ;   set failed-treatment? true
     ;   set months-left-to-live CD4-count-present / CD4-decline-rate-no-treatment
     ; ]
    ;]
  ]
  
  ask turtles with [infected? and months-left-to-live > 0 and (CD4-count-present < treatment-threshold) and (not failed-treatment?)] [
    set eligible-for-treatment? true
  ]
  
  ;; a constant (maximum) fraction of the population will be on treatment
  if (any? turtles with [eligible-for-treatment?]) [
  while [(count turtles with [on-treatment?] / count turtles with [eligible-for-treatment?]) < (proportion-on-treatment)] [
    ask one-of turtles with [eligible-for-treatment? and (not on-treatment?)] [
      set on-treatment? true
      set CD4-at-treatment CD4-count-present
    ]
  ]
  ]
end 

to make-prettier
  ask links [set color white]
  ask turtles [set size 3]
  repeat 10
  [
    layout-spring turtles links .8 (world-width / (sqrt count turtles)) 4
  ]
end 

to set-plot-pen [plot-pen keep?]
  if keep? [
  create-temporary-plot-pen word plot-pen run-number
  set-plot-pen-color black
  ]
  if (not keep?) [
    set-current-plot-pen plot-pen
    if ticks = 0 [ plot-pen-reset ]
  ]
end 

to plot-statistics
  set-current-plot "Women / Men"
  set-current-plot-pen "overall"
  plot count turtles with [female?] / count turtles with [not female?]
  set-current-plot-pen "prevalence"
  plot count turtles with [female? and infected?] / count turtles with [not female? and infected?]
  
  set-current-plot "Prevalence"
  set-plot-pen "All-HIV-Positive" true
  ;set-current-plot-pen "All-HIV-Positive"
  if (not draw-all-HIV-positives?) [ plot-pen-up ]
  if any? turtles with [infected?] [
    plot count turtles with [infected?] / count turtles
  ]
  set-plot-pen "Acute" false
  if (not draw-acute?) [ plot-pen-up ]
  ifelse any? turtles with [HIV-stage = 1 and infected?] [
    plot count turtles with [HIV-stage = 1 and infected?] / count turtles
  ]
  [ plot 0 ]
  set-plot-pen "Chronic" false
  if (not draw-chronic?) [ plot-pen-up ]
  ifelse any? turtles with [HIV-stage = 2 and infected?] [
    plot count turtles with [HIV-stage = 2 and infected?] / count turtles
  ]
  [ plot 0 ]
  set-plot-pen "Final" false
  if (not draw-final?) [ plot-pen-up ]
  ifelse any? turtles with [HIV-stage = 3 and infected?] [
    plot count turtles with [HIV-stage = 3 and infected?] / count turtles
  ]
  [ plot 0 ]
  
  if (ticks mod 12 = 0) [
    set-current-plot "Incidence"
    set-plot-y-range 0 precision ((current-yearly-incidence / count turtles) + .05) 2
    set-plot-pen "Incidence" false
    plot (current-yearly-incidence / count turtles)
  
    set-current-plot "Proportion of Incidence Due to HIV Stages"
    set-plot-pen "Acute" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-acute / current-yearly-incidence]
    [plot 0]
    set-plot-pen "Chronic" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-chronic / current-yearly-incidence]
    [plot 0]
    set-plot-pen "Final" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-final / current-yearly-incidence]
    [plot 0]
    
    set-current-plot "Proporition of Incidence Due to Types of Partnerships"
    set-plot-pen "Non-Spousal" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-non-spousal / current-yearly-incidence]
    [plot 0]
    set-plot-pen "Spousal" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-spousal / current-yearly-incidence]
    [plot 0]

    set-current-plot "Proportion of Incidence Due to Concurrent Partnerships"
    set-plot-pen ">1 Partner" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence->1-partner / current-yearly-incidence]
    [plot 0]
    set-plot-pen "1 Partner" false
    ifelse current-yearly-incidence != 0
    [plot current-yearly-incidence-1-partner / current-yearly-incidence]
    [plot 0]
    
  ]

  set-current-plot "Male Partnership Distribution"
  foreach n-values 4 [?] [
    set-plot-pen (word ? " Partners") false
    plot count turtles with [(not female?) and (count my-links = ?)] / count turtles with [(not female?)]
  ]
  set-current-plot "Female Partnership Distribution"
  foreach n-values 4 [?] [
    set-plot-pen (word ? " Partners") false
    plot count turtles with [(female?) and (count my-links = ?)] / count turtles with [(female?)]
  ]
  
  set-current-plot "Histogram of Years Left to Live"
  histogram [months-left-to-live / 12] of turtles with [infected?]
  set-current-plot "Histogram of Years Since Infected"
  histogram [months-since-infected / 12] of turtles with [infected?]
  
  set-current-plot "Mean CD4 Count at Treatment Initiation"
  set-plot-pen "CD4-count" false
  ifelse not any? turtles with [infected? and on-treatment?] 
  [ plot 0 ]
  [ plot mean [CD4-at-treatment] of turtles with [infected? and on-treatment?] ]
end 

to-report random-weibull [a b]
 report (a * ((- ln (1 - random-float 1)) ^ (1 / b)) * 12)
end 

to-report random-discrete [pmf] ;returns discrete random variable with given pmf (0-based)
  let itemnum 0
  let lower 0
  let upper 0
  let randval random-float 1
  foreach pmf [
    set upper upper + ?
    if (randval < upper and randval >= lower) [
      report itemnum
    ]
    set lower upper
    set itemnum (itemnum + 1)
  ]
end 

to-report ever-married-filter [eligible]
  ;we assume eligible is a non-empty agentset
  ;guaranteed to return a non-empty subset of eligible
  let withpartner eligible with [num-partners >= 1]
  let nopartner eligible with [num-partners = 0]
  let prob 0
  ifelse infected?
     [ set prob ((count nopartner) / (ever-married-pos-choose-polygamous-odds * (count withpartner) + (count nopartner)))]
     [ set prob ((count nopartner) / (ever-married-neg-choose-polygamous-odds * (count withpartner) + (count nopartner)))]
  ifelse ((random-float 1)  >= prob) [report withpartner] [report nopartner]
end 

to-report sero-sorting-filter [eligible]
  ;we assume eligible is a non-empty agentset
  ;guaranteed to return a non-empty subset of eligible
  let same eligible with [infected? = [infected?] of myself]
  let diff eligible with [infected? = not [infected?] of myself]
  let prob ((count diff) / (sero-sorting-odds * (count same) + (count diff)))
  ifelse ((random-float 1)  >= prob) [report same] [report diff]
end 

; based on Giant Component code from model library
;; to find all the connected components in the network, their sizes and starting turtles

to find-all-components
  set component-size []
  ask turtles [ set explored? false ]
  ;; keep exploring till all turtles get explored
  loop [
    ;; pick a node that has not yet been explored
    let start one-of turtles with [ not explored? ]
    if start = nobody [ stop ]
    ;; reset the number of turtles found to 0
    ;; this variable is updated each time we explore an
    ;; unexplored node.
    set curr-component-size 0
    ask start [ explore ]
    set component-size (lput curr-component-size component-size)
  ]
end 

;; Finds all turtles reachable from this node

to explore ;; node procedure
  if explored? [ stop ]
  set explored? true
  set curr-component-size curr-component-size + 1
  ask link-neighbors [ explore ]
end 

There are 2 versions of this model.

Uploaded by When Description Download
Benjamin Armbruster over 10 years ago Now with preview image Download this version
Benjamin Armbruster over 10 years ago Initial upload Download this version

Attached files

File Type Description Last updated
default.txt data default parameters over 10 years ago, by Benjamin Armbruster Download
HIV and Polygamy.png preview Preview for 'HIV and Polygamy' over 10 years ago, by Benjamin Armbruster Download
scenarios.zip data Scenarios for paper over 10 years ago, by Benjamin Armbruster Download

This model does not have any ancestors.

This model does not have any descendants.