Welcome, guest | Sign In | My Account | Store | Cart

In his book, "More Sex Is Safer Sex: The Unconventional Wisdom of Economics, " Steven Landsburg argues that if sexual conservatives took more sexual partners it would improve everyone's chances of finding low-risk partners, thereby reducing the spread of STDs for all.

See http://www.nytimes.com/2007/07/08/books/chapters/0708-1st-land.html?_r=1&pagewanted=print .

This recipe attempts to simulate the scenario which Landsburg describes and test his claim that "More sex is safer sex."

Python, 178 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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()

When I first ran across Landsburg's More Sex/Safer Sex argument, I thought, "That can't be right." Sure, if more low-activity players engage in hook-ups, the more likely all players will find a low-activity partner instead of a riskier high-activity partner. Nonetheless, the more sexual contacts occur with some risk, even low-risk, the more infections can occur.

Or maybe there is something unexpected happening as Landsburg claims.

Anyone who has taken courses in probability and statistics -- or has read a mathematical puzzle book -- knows how often such problems can contradict one's intuition and that it is folly to believe one can verbally argue the way to the truth in these matters.

I don't have the math to tackle this problem directly, but it's not much trouble to set up a simulation for a stripped-down Landsburg scenario and run a large population through tens of thousands of sexual contacts using weighted random functions to determine which contacts occur and of those which transmit infections.

In my simulation there is a pool of 1000 players: 100 are high-activity players who have an encounter on the average of 1 per 10 days and 900 are low-activity players, who have a sexual encounter on the average of 1 per 100 days or higher. To test Landsburg's hypothesis, this low-activity value is varied upward and the resulting number of infections for different activity values compared.

Half the high-activity players are already infected when the simulation starts. Transmissibility is assumed to be 1 per 100 sexual contacts. The simulation runs for 1000 days. A trial accumulates the results from a 100 runs.

Each day of a run the simulator calls the weighted random function for each player to determine whether to add that player to the day's hookup queue. Then all the players at the queue are paired off for one sexual encounter and their possible infection randomly determined.

It's a simple model that assumes that all players are bisexual with equal odds of infection. Each player at the hookup queue is always successful in coupling with a random partner unless the number at the queue is odd, which leaves the last player out. It is further assumed that no players have potentially unsafe sex outside the hookup queue.

Using this model, which seems to satisfy Landsburg's basic requirements, the number of infections steadily climbs as the low-activity rate is increased. I've varied the other parameters with no luck in validating Landsburg's claim that "More sex is safer sex."

According to my simulation, persuading sexual conservatives to take more sexual partners will not "slow the spread of AIDS" or "save lives" as Landsburg promises. On the contrary, it will increase the spread of such diseases.

Landsburg's analysis seems to err on the following point: although the odds for a safe encounter on a single night increase when more low-activity players join the hookup scene, the low-activity players must continue to have more encounters to maintain their higher activity rate and therefore they receive more infections over time, thereby raising the infection rate for the entire population.

For high-activity players, the increased activity of the lows is a pure boon. The number of infections among high-activity players does drop with increased activity by the sexually more restrained.

It is true, however, that the individual risk per sexual encounter does drop as low-activity players increase their activity. Since Landsburg claims that sex in itself is good, perhaps he is judging that the larger increase in sex acts more than makes up for the increased number of infections among low-activity players.

It's hard to be sure exactly what Landsburg means because his essay is vague on specifics. Landsburg is more intent on speculating how to encourage sexual conservatives to loosen their morals for the greater good, even though it is not to their individual benefit.

He does mention the importance of safe sex, i.e. condoms, and the likelihood that low-activity players will use condoms while high-activity players won't. Adjusting the simulation so that the lows always use condoms while the highs, left to their own devices, won't, actually yields the result Landsburg promises. The more sex that low-activity players have, the fewer infections occur in the entire pool.

However, in this condom scenario what is really happening is that low-activity players are enforcing safe sex on the high-activity players. So the moral of that story is something of a tautology: "More safe sex is safer sex."

Although Landsburg makes only cursory arguments for his More Sex/Safer Sex claim, he does cite a paper by Michael Kremer ( http://hoohila.stanford.edu/workingpapers/getWorkingPaper.php?filename=E-95-8.pdf ) several times as an authoritative support for More Sex/Safer Sex.

The Kremer paper contains much fierce math but in the introductory section Kremer is making a somewhat different argument than Landsburg. Kremer's article is based on a game theory model which posits that as low-activity players reduce their activity, the high-activity players will have less incentive to restrain their risky behavior and therefore increase their activity, and visa-versa: if the low-activity players increase their activity, the high-activity will reduce theirs.

So, per Kremer, I tried increasing the low-activity while decreasing the high-activity in the simulation, and the result was a bumpy stability in infections. However, it was impressive how many more sexual contacts this approach allowed while keeping the infection rate steady -- much more bang for the risk, so to speak.

Lastly, I tried the commonsense approach: lowering the activity of the high-activity players. Not surprisingly, this approach had the greatest impact in reducing infections (aside from using condoms), albeit at the cost of also reducing the number of sexual contacts.

In other words, "Less sex is safer sex." Of course, that nugget of wisdom is entirely conventional and won't generate controversy or sell books.

Please check my work and assumptions or try your own simulations. It's an interesting problem in its own right, as well as being important in this age of STDs.

13 comments

Jack Trainor (author) 13 years, 7 months ago  # | flag
Landsburg: increase activity of low-activity players

Low_Activity   High_Activity  Low_Infects    High_Infects   Contacts       New_Infects    Risk           
0.01           0.10           25.61          12.81          18511.4        38.42          0.00208        
0.02           0.10           36.34          8.92           27524.9        45.26          0.00164        
0.03           0.10           40.38          7.39           36505.6        47.77          0.00131        
0.04           0.10           46.60          6.13           45476.6        52.73          0.00116        
0.05           0.10           52.11          5.45           54507.2        57.56          0.00106        


Landsburg w/ condoms: increase activity of low-activity players, use condoms

Low_Activity   High_Activity  Low_Infects    High_Infects   Contacts       New_Infects    Risk           
0.01           0.10           0.28           12.81          18495.8        13.09          0.00071        
0.02           0.10           0.38           8.68           27491.8        9.06           0.00033        
0.03           0.10           0.42           6.33           36509.9        6.75           0.00018        
0.04           0.10           0.36           4.98           45487.7        5.34           0.00012        
0.05           0.10           0.42           4.49           54551.5        4.91           0.00009        


Kremer: increase activity of low-activity players, decrease activity of high-activity players

Low_Activity   High_Activity  Low_Infects    High_Infects   Contacts       New_Infects    Risk           
0.01           0.10           26.37          12.70          18478.5        39.07          0.00211        
0.02           0.09           32.55          7.81           26495.5        40.36          0.00152        
0.03           0.08           34.67          5.16           34489.3        39.83          0.00115        
0.04           0.07           34.52          3.58           42499.5        38.10          0.00090        
0.05           0.06           33.30          2.19           50466.7        35.49          0.00070        


Commonsense: decrease activity of high-activity players

Low_Activity   High_Activity  Low_Infects    High_Infects   Contacts       New_Infects    Risk           
0.01           0.10           26.16          12.68          18510.5        38.84          0.00210        
0.01           0.09           24.91          10.55          17493.1        35.46          0.00203        
0.01           0.08           22.62          9.25           16484.6        31.87          0.00193        
0.01           0.07           20.46          7.43           15505.9        27.89          0.00180        
0.01           0.06           19.09          5.78           14474.9        24.87          0.00172
Alan Plum 13 years, 7 months ago  # | flag

An interesting modification would be to add protection as a variables (i.e. protected encounters having a lower risk of infection, with the likeliness of using protection is determined by the average of the involved parties' awareness) and check whether better sex ed could compensate the risk of an increase in the number of absolute encounters (i.e. whether the conservative fear that better sex ed promotes promiscuity is relevant to the infection rate at all).

Alan Plum 13 years, 7 months ago  # | flag

Sorry, just realised you pretty much covered this under "more safe sex is safer sex".

Barry Kelly 13 years, 6 months ago  # | flag

The key bit that you're is missing is prostitutes as the "high-activity players". If it's easier for people to get with "low-activity players", it naturally reduces the activity of the "high-activity players".

Meanwhile, trying to prevent sex (i.e. the less sex approach) is in practice completely moronic, doomed to failure for any model of humanity. It's not "common-sense" either, as common sense says that young men will get laid, one way or another; if it's not with low-activity players, then it will be with high risk, extremely high activity (as in, 10 or 20 a day, not 1 every 10 days) players; and these guys will later go on to marry the low-activity players, to tragic results.

Steven Landsburg 13 years, 6 months ago  # | flag

You seem to have misunderstood the assumptions, the logic and the conclusions of the argument to which you think you're replying. Details here:

http://www.thebigquestions.com/2010/10/04/the-python-misinterpreter/

Steven Landsburg 13 years, 6 months ago  # | flag

Executive summary of the problem with your code:

You write: <i>Nonetheless, the more sexual contacts occur with some risk, even low-risk, the more infections can occur. </i>

What you overlook --- and this is the whole point --- is that these risks are internalized. People accept them voluntarily, so they must be offset by the benefits of having sex.

By contrast, the sexual conservative who takes on another partner conveys external benefits --- benefits that accrue to someone other than him/herself. To outweigh these benefits, you'd need to point to a (non-pecuniary) external cost. But you have no candidate for what that cost might be.

Bob Marley 13 years, 6 months ago  # | flag

Steven Lansburg-

Commenting on your last comment.. that your "whole point" was that people accept risk voluntarily, "so they MUST BE offset by the benefits of having sex" (my emphasis added).

You're back-pedaling into a very odd position here, as if you realize that the fallacy of your argument has been exposed!

Now your position seems to be that people MUST make "rational" decisions to have sex - weighing the benefits vs. the costs. If you truly believe that, then you must also believe that Conservatives are weighing those choices, and determining that the benefits do not outweigh the costs.

To advocate that Sexual Conservatives have more sex, you are suggesting that people are capable of acting against their rational conclusions (You call this "the sin of self-restraint" in your book). Yet this is contrary to your position that people MUST make rational decisions! So you've created a contradictory circular argument.

You are better off arguing that "Sex should be better" so that the benefits outweigh the costs, and then more conservatives join the party, lowering the risk for the promiscuous people. At least this makes sense!

Steven Landsburg 13 years, 6 months ago  # | flag

Bob Marley:

*your "whole point" was that people accept risk voluntarily, "so they MUST BE offset by the benefits of having sex" (my emphasis added).

You're back-pedaling into a very odd position here,*

Since this was the whole argument in the first place, it seems very odd to call it a "back-pedal".

*Now your position seems to be that people MUST make "rational" decisions to have sex - weighing the benefits vs. the costs. If you truly believe that, then you must also believe that Conservatives are weighing those choices, and determining that the benefits do not outweigh the costs. *

Yes. This is in fact a key step in the argument.

To advocate that Sexual Conservatives have more sex, you are suggesting that people are capable of acting against their rational conclusions.

I have absolutely no idea where you're getting this. Current levels of pollution result from rational choices by profit maximizing firms. To advocate for lower levels of pollution, must one beleive that people are capable of "acting against their rational conclusions"?

Anand B Pillai 13 years, 5 months ago  # | flag

A nice side-effect of this recipe is that if one searches for Python and Sex on the web, you get something better than Python's laying eggs and having babies in the search results page, since this recipe has made it into the top 10 results.

I never tried the recipe, but I don't think this argument can be settled with just this experiment. There are more philosophical and intangibles in this that can't be captured in the experiment alone.

Michael 13 years, 4 months ago  # | flag

If you're running this in Windows, you get viruses before the script starts to run. Is this a concern?

Michael 13 years, 4 months ago  # | flag

By the way, the assertion "more sex is safer sex" is completely false. I don't know if it was intended to be cynical, but the notion that Joan and Martin's hookup would prevent Maxwell from giving Joan AIDS is bogus. In the next paragraph Steven mentions, "Of course we wouldn't want this to go too far...", which is absurd. One cannot correctly postulate that promiscuity will decrease STDs and be correct. Also note that in your example HighActivityPartner is infected, while LowActivityPartner is not. Did I miss the part where a low activity partner who is more active is, in reality, a high activity partner?

Dev Player 13 years, 4 months ago  # | flag

I find much missing or misleading with this simulation both with a Python perspective and a simulation perspective.

First Player objects are misnamed. Using terms like "high activity player" implies someone who does a lot of activity verse someone who is a high risk of spreading STDs. This is a key concept. High activity players also does not necessarily mean larger number of partners, so really the term should be "high risk tranmission episodes"

This causes the math to differ. I think the simulation should be using more sets(), high risk, high activity, risk modifiers, and interactions and unions used. For example a low risk low activity "player" is more likely to keep their offspring therefore growing the set of "low risk". And high activity may move to low activity due to the inability to have sex caused by infection. Infection can alone reduce likely hood of being in the "active" set. There should be the "likley to have sex" set and the "unlikely to have sex" set accounting for appearance, age, etc.

Do low activity players generally have sex with other low activity players? Is the same true for high activity players?

In the simulation the sets only have two changes, activity level and infection status. There might need to be some structural changes to the code to allow for these varibles.

Other variables not accounted for: cureable infections, infection transmission rate from unwilling or even unparticipating "players" (think illegal drug needles). Why does that matter? New infections not from sex -could- have a doping effect (doping as in silicon doping - a tiny bit makes the whole dam thing work).

Definitions need to be tighter, STD while the term is generally understood, in this simulation or the argument proposed by Steven is not faily represented. As certain STDs are very easy to transmit and others are a little tougher. (It's said you can't get AIDs or HIV from kissing, but you can get Herpies). So there are more sets(). Other sets would include more risk levels, ie kissing verse intercoarse verse multipartner(orgies), etc.

"More sex is safer sex" needs to be qualified better as previously mentioned in other posts. Safer sex for whom, the individual, the whole, the active, the inactive. As well as "more sex", with different partners or same partner(s) (think conmune or colt)?

But I do take this to be for what it is meant to be, a simplefied Python recipe. And I certainly learned from it if not challenged some of my previous notions.

Drew Wagner 12 years, 7 months ago  # | flag

Awesome! This is the first sex related story I have ever seen that came with source code! As for your result, you forgot to model premature death due to infection. At least according to the book chapter/nytimes article, this is significant:

"A cautious guy like Martin does the world a favor every time he hits the bars. In fact, he does the world two favors. First he improves the odds for everyone who's out there seeking a safe match. The second favor is more macabre, but probably also more significant: If Martin picks up a new partner tonight, he just might pick up an infection as well. That's great. Because then Martin goes home, wastes away in solitude, and eventually dies - taking the virus with him."

http://www.nytimes.com/2007/07/08/books/chapters/0708-1st-land.html?_r=1&pagewanted=print