Wednesday, September 29, 2010

Questions for the Anti-Vaccination Community

  • Sometimes adults have to get a new immune system and so they get their vaccinations again. But they never go autistic, AFAIK.
  • Pets (dogs and cats, possibly ferrets in some places) get vaccinations. How come they never turn autistic? Retarded yes, but not autistic.
  • QED, I rest my case.

More Dorkiness

I've adapted the code from the other day to use real-valued characteristics, the Euclidean distance in characteristic space representing the probability of agents interacting. And I added some histograms to the display:

Early in the simulation, few connections between sites and traits very spread out

They converge on a wishy-washy moderate consensus pretty quickly, so there's a distance threshold in there to keep everything from joining together right away:

Later in the simulation, more connections and traits clustered around 0.5

Source here.

Monday, September 27, 2010

Your Ways Are Numbered

Have been thinking lately about simulating how cultural values change in a population.1

The general approach I was considering was an agent-based model where each agent's "values" are represented by a set of n real numbers in [0,1]: basically each dimension is like one of those survey questions that's a statement like "everyone should have access to clean drinking water," with answers ranging from "strongly disagree" to "strongly agree," and "neutral" in the middle (0.5).

And when two agents had a lot in common with one another values-wise (i.e., were nearby in n-dimensional space), then they would be more likely to move closer together. So starting with a randomly generated population, you'd see different subgroups start to coalesce into one or more distinct cultures with shared values (and eventually reducing to a single consensus culture if the simulation ran long enough).

Which as I poked around looked a lot like what was done in this 1997 paper (PDF) by Robert Axelrod (nullus), The Dissemination (nullus) of Culture. He puts his agents on a grid and only lets them potentially interact with grid neighbors. It's neat.

Here's a Python implementation, with visualization in PyGame (I inverted Axelrod's color coding so more similar sites are connected by darker lines, which strikes me as more intuitive):

import random

import pygame
from pygame.locals import *

class Simulation:

    WIDTH = 640
    HEIGHT = 480

    LINE = 4

    DRAW_FRAMES = 1000

    def __init__(self, dimensions):
        self.dimensions = dimensions
        self.grid_size = min(self.WIDTH/(self.dimensions[0] + 1),
                             self.HEIGHT/(self.dimensions[1] + 1))
        self.bg_rect = pygame.Rect(max(0, (self.WIDTH - (self.dimensions[0] + 1) * self.grid_size) / 2),
                                   max(0, (self.HEIGHT - (self.dimensions[1] + 1) * self.grid_size) / 2),
                                   (self.dimensions[0] + 1) * self.grid_size,
                                   (self.dimensions[1] + 1) * self.grid_size)

        self.sites = [[[random.randint(1,10) for i in range(5)]
                       for y in range(self.dimensions[1])]
                      for x in range(self.dimensions[0])]

    def background(self, screen):
        screen.fill((255,255,255), self.bg_rect)

    def similarity(self, p1, p2):
        return sum(c1 == c2 for c1, c2 in zip(p1, p2))/float(len(p1))

    def color(self, p1, p2):
        gray = 255 - int(self.similarity(p1, p2) * 255)
        return (gray, gray, gray)

    def lines(self, screen):
        for x in range(self.dimensions[0]):
            for y in range(self.dimensions[1]):
                start = (self.bg_rect.left + (x+1) * self.grid_size,
                         self.bg_rect.top + (y+1) * self.grid_size)
                if x < self.dimensions[0] - 1:
                    end = (start[0] + self.grid_size, start[1])
                    color = self.color(self.sites[x][y], self.sites[x+1][y])
                    pygame.draw.line(screen, color, start, end, self.LINE)
                if y < self.dimensions[1] - 1:
                    end = (start[0], start[1] + self.grid_size)
                    color = self.color(self.sites[x][y], self.sites[x][y+1])
                    pygame.draw.line(screen, color, start, end, self.LINE)

    def random_site(self):
        return (random.randint(0, len(self.sites)-1),
                random.randint(0, len(self.sites[0])-1))

    def random_neighbor(self, site):
        x,y = site
        neighbors = []
        if x > 0:
            neighbors.append((x-1,y))
        if x < len(self.sites)-1:
            neighbors.append((x+1,y))
        if y > 0:
            neighbors.append((x,y-1))
        if y < len(self.sites[0])-1:
            neighbors.append((x,y+1))
        return random.sample(neighbors, 1)[0]

    def interact(self, active, neighb):
        different = [i for i in range(len(active))
                     if active[i] != neighb[i]]
        if len(different) > 0:
            i = random.sample(different, 1)[0]
            active[i] = neighb[i]

    def try_event(self):
        active = self.random_site()
        neighb = self.random_neighbor(active)
        active_site = self.sites[active[0]][active[1]]
        neighb_site = self.sites[neighb[0]][neighb[1]]
        if random.random() < self.similarity(active_site, neighb_site):
            self.interact(active_site, neighb_site)
    
    def run(self):
        pygame.init()

        screen = pygame.display.set_mode((self.WIDTH,self.HEIGHT), HWSURFACE)
        pygame.display.set_caption('Sites')

        done = False
        n = 0
        while not done:
            for event in pygame.event.get():
                if event.type == QUIT:
                    done = True
                elif event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        done = True

            self.try_event()
            n += 1
            if n > self.DRAW_FRAMES:
                
                self.background(screen)
                self.lines(screen)

                pygame.display.flip()
                
                n = 0

if __name__ == '__main__':
    Simulation((10,10)).run()

1 For extremely nerdy reasons.

Thursday, September 23, 2010

Recaps off to ya!

I thought Dave was about to go in a different direction when he cut down recapping television.

I hate to have to point this out, but while Mr. Delahaye attacks a blogger for "compar[ing] [them]sel[ves] to DERRIDA and BARTHES" (his caps), the quoted party he's rebutting actually makes a point of saying that he means "not to compare [him]self to anybody" (emphasis mine).

He rests his case, I'm sure.

But my real objection is that actually recapping is pretty interesting as a genre: it's something of such obviously little value that it only could have found a foothold in a digital context, and yet it evidently has enough appeal that there are not only sites devoted entirely to recapping that manage to scrape by, but there are more than a few non-recap sites that include recaps nonetheless to bolster their hit stats.

And from what I've seen of recaps (and as the Observer piece appeared to be arguing), the more popular ones tend to be not just plays-by-play of television episodes' plots, but rather those that delve into analysis and deconstruction of the sort which I believe Derrida would approve.

The story of television recaps on the internet is that in a medium without (as many) gatekeepers, there exists a public appetite for analyzing popular culture, an appetite that is largely unanticipated and wholly unsatisfied by the corporate producers of said culture.

Thursday, September 16, 2010

Consistency Check

One not infrequently encounters defenses of so-called "sweatshop" labor that proclaim that factories thus described are only able to find employees because they represent the "best available option" for residents of their localities.

Consequently, goes this line of argument, any bleeding-heart's personal boycott (or public campaign exhorting widespread boycott) of companies using these types of facilities is counterproductive, making the lives of the workers the would-be do-gooder claims to be looking out for worse off by hurting their employers.

It strikes me that for a moral person who truly believes this, it should not be enough to stop at "don't boycott" as a response to sweatshops: indeed, there is a moral obligation to actively seek out and prefer sweatshop products over alternatives, and to agitate for others to do the same.

The purchase of "fair trade," artisanal, or other "humanely manufactured" items takes food from the mouths of those who need it most to line the pockets of well-heeled hobbyists and lazy union "workers."

Wednesday, September 15, 2010

Prancis Weight Chart

I forgot to post this earlier, but we recorded Prancis's weight until he reached what appears to be his full size, about 70 pounds. We always wanted to know how big he was going to be based on his weight at different ages growing up, and there just wasn't a lot of data out there, so this is our contribution to the public knowledge base.



He was born in early November 2008 (we say the 4th in honor of Obama's election, but we don't really know), neutered on May 30th, 2009, and he's half Great Pyrenees and half lurcher (in his case, saluki and Bergian shepherd).

Sunday, September 5, 2010

Occam's Razor

Not sure why anyone ever thought Obama was anything other than the neo-liberal centrist he always claimed to be and acted like.

Thursday, September 2, 2010

Fat of the Land

A blogger at Feministe responds to a typical argument against the conflation of weight and poor health. Monica's position is that tracking average weight (or BMI) of populations is useful from a public health standpoint. Thus the Jezebel party line against "fat shaming" is potentially harmful to the extent that it complicates addressing the genuine public health issue regarded as an obesity epidemic.

The arguments are typical of this topic, and they go past each other. The "obesity" epidemic is actually a poverty epidemic shaded by bad food policy. Corporations, as they always do, use its prominence in the public consciousness to push their products: we all know that there is this problem called "obesity" which threatens our society, so do your part by buying our snake oil.

Jezebel is primarily concerned in this case with media and marketing messages aimed at women. They are on perfectly solid ground warning consumers off marketing narratives that conflate a public health crisis with individual morality as expressed by participation in the fitness and diet industries. And while the personal responsibility narrative hurts the middle class consumers Jezebel is looking out for, it does a further disservice by obscuring the extreme income inequality at the root of our society's obesity crisis, so perhaps they do good in that sense as well, if inadvertantly.

In any case, defending the "overweight is unhealthy" status quo is neither necessary at this point nor particularly likely to result in meaningful progress against the poverty-based obesity problem. Middle class tolerance of fatness is a project that does not in any way conflict with correcting the market and policy failures that cause and maintain massive economic inequality.