HIV and Polygamy
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
; 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.
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.