import random HIGH_ACTIVITY_RATE = 0.10 HIGH_ACTIVITY_INITIAL_INFECTION = 0.5 CONDOM_FAILURE_RATE = 0.01 class Player(object): def __init__(self, id, activity, use_condom=False): self.id = id self.activity = activity self.use_condom = use_condom self.infected = False self.history = [] self.conversion_day = None class LowActivityPlayer(Player): def __init__(self, id, activity, use_condom): Player.__init__(self, id, activity, use_condom) self.infected = False class HighActivityPlayer(Player): def __init__(self, id, activity, use_condom, infected): Player.__init__(self, id, activity, False) self.infected = infected class Manager(): def __init__(self, low_activity, high_activity, transmission, players_count, days, use_condom): self.low_activity = low_activity self.high_activity = high_activity self.transmission = transmission self.players_count = players_count self.days = days self.use_condom = use_condom random.seed() self.pool = {} self.hookup_queue = [] for id in range(self.players_count): if id < self.players_count * HIGH_ACTIVITY_RATE: infected = False if id < self.players_count * HIGH_ACTIVITY_RATE * HIGH_ACTIVITY_INITIAL_INFECTION: infected = True player = HighActivityPlayer(id, self.high_activity, use_condom, infected) else: player = LowActivityPlayer(id, self.low_activity, use_condom) self.pool[id] = player def run(self): for day in range(self.days): self.hookup_queue = [] for player in self.pool.values(): if random.random() < player.activity: self.hookup_queue.append(player) while self.hookup_queue: player_1 = player_2 = None player_1 = random.choice(self.hookup_queue) self.hookup_queue.remove(player_1) if self.hookup_queue: player_2 = random.choice(self.hookup_queue) self.hookup_queue.remove(player_2) if player_1 and player_2: self.expose(player_1, player_2, day) return self def expose(self, player_1, player_2, day): transmission = self.transmission player_1.history.append(day) player_2.history.append(day) if player_1.infected or player_2.infected: if player_1.use_condom or player_2.use_condom: transmission *= CONDOM_FAILURE_RATE infection = (random.random() < transmission) if infection: if not player_1.infected: player_1.infected = True player_1.conversion_day = day if not player_2.infected: player_2.infected = True player_2.conversion_day = day def trial(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom): new_infections = 0.0 new_low_infections = 0.0 new_high_infections = 0.0 contacts = 0.0 low_contacts = 0.0 high_contacts = 0.0 for i in range(max_runs): mgr = Manager(low_activity, high_activity, transmission, players_count, days, use_condom).run() for player in mgr.pool.values(): if isinstance(player, LowActivityPlayer): if player.conversion_day: new_low_infections += 1 low_contacts += len(player.history) elif isinstance(player, HighActivityPlayer): if player.conversion_day: new_high_infections += 1 high_contacts += len(player.history) else: raise Exception("trial: invalid player %d", player.id) contacts += len(player.history) new_infections = new_low_infections + new_high_infections avg_new_infections = new_infections/max_runs avg_new_low_infections = new_low_infections/max_runs avg_new_high_infections = new_high_infections/max_runs avg_contacts = contacts/max_runs avg_low_contacts = low_contacts/max_runs avg_high_contacts = high_contacts/max_runs risk_per_contact = avg_new_infections / avg_contacts print "\t%-15.2f%-15.2f%-15.2f%-15.2f%-15.1f%-15.2f%-15.5f" %(low_activity, high_activity, \ avg_new_low_infections, avg_new_high_infections, avg_contacts, avg_new_infections, risk_per_contact) def print_heading(): print "\t%-15s%-15s%-15s%-15s%-15s%-15s%-15s" %\ ("Low_Activity", "High_Activity", "Low_Infects", "High_Infects", "Contacts", "New_Infects", "Risk" ) def test_landsburg(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom): print "\t%s" % ("Landsburg: increase activity of low-activity players") print print_heading() for i in range(6): trial(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) low_activity += 0.01 print print def test_landsburg_condom(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom): print "\t%s" % ("Landsburg w/ condoms: increase activity of low-activity players, use condoms") print print_heading() for i in range(6): trial(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) low_activity += 0.01 print print def test_kremer(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom): print "\t%s" % ("Kremer: increase activity of low-activity players, decrease activity of high-activity players") print print_heading() for i in range(6): trial(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) low_activity += 0.01 high_activity -= 0.01 print print def test_commonsense(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom): print "\t%s" % ("Commonsense: decrease activity of high-activity players") print print_heading() for i in range(6): trial(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) high_activity -= 0.01 print print def main(): max_runs = 100 low_activity = 0.01 high_activity = 0.1 transmission = 0.01 players_count = 1000 days = 1000 use_condom = False test_landsburg(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) test_landsburg_condom(max_runs, low_activity, high_activity, transmission, players_count, days, True) test_kremer(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) test_commonsense(max_runs, low_activity, high_activity, transmission, players_count, days, use_condom) if __name__ == "__main__": main()