nkremerh / sugarscape

Development repository for the Digital Terraria Lab implementation of the Sugarscape agent-based societal simulation.
https://github.com/digital-terraria-lab/sugarscape
MIT License
7 stars 11 forks source link

Adds config option to make starting quadrants each have one tribe #76

Closed colinhanrahan closed 2 months ago

colinhanrahan commented 2 months ago

I didn't want to mess with the randomization code for generating tribe tags, but we might have to. Picture this: there are 2 starting quadrants (so 2 tribes with the config option turned on) and 800 agents. The quadrants are both 20x20, so there are exactly 800 spawn locations. However, the tribes will not be perfectly 50/50—there will be a few more in one and a few less in the other. We will run out of spawning locations for the tribe with more agents. We could:

Thoughts? Also, a default cell has to be generated for the initialization of agents' debug (which goes through cell.environment.debug). We could get around this by passing in debug some other way.

colinhanrahan commented 2 months ago

We'll also have to keep track of which tribe lives in which quadrant outside of configureAgents(). When agents are being replaced, the order of tribes' first appearances are random, so they are not correctly correlated with their quadrants. I'm working on changes to address this.

nkremerh commented 2 months ago

When I first thought of this (and quickly moved on to other things), I had an integer option in mind. Something like environmentTribesPerQuadrant. If the number of tribes % number of active quadrants wasn't zero, round down the number of tribes to the closest number which would result in zero (and print a warning message similar to when too many starting agents are requested).

I'm coming around to preferring this option be a Boolean like environmentTribePerQuadrant and cap it at 1 tribe in each active quadrant. If there are more tribes than active quadrants, set the number of tribes to the number of active quadrants. If there are more active quadrants than number of tribes, set the number of tribes to the number of quadrants. Always adjust the number of tribes to spatial availability, never the other way around.

From there, you could actually force the tribes per quadrant. The formula for how many 0s and 1s need to be in a tag for a specific tribe is known. For a given quadrant, force agents' tags in that quadrant to match the median number of 0s and 1s (to prevent immediate tribe flipping when interacting with other tribes). This could be done during agent creation or done after all agents are placed (walk through the list of agents, figure out their quadrant, and arbitrarily set their tags as needed).

colinhanrahan commented 2 months ago

The number of tribes is set to the number of quadrants, so we're in agreement there.

nkremerh commented 2 months ago

The hashing is used to maintain determinism. Each config option is hashed which provides a proper and consistent ordering of options. It is statistically improbable that hash conflicts will occur from this. Thanks to @WillemHueffed for that fix.

Correct on the name preference. This is setting up a property of the simulation environment, not individual agents.

If you want to permute tags for tribe members, that should be fine. By invoking the random library, this solution will consume random numbers and break from the current determinism. But, this is also a brand new (and to be rarely used) feature, so it should have a net zero impact on the main use case of the software.

colinhanrahan commented 2 months ago
nkremerh commented 2 months ago

With 10 tribes and 10 agents, I get 5 tribes present. One tribe has 4 members.

colinhanrahan commented 2 months ago

With tribe quadrants on or off? Either way, with lower numbers of agents, the perfect randomization of tags (or location if tribe quadrants are on) means that you probably won't get an even distribution. This also happens with the current repo. Do you want to guarantee that tribes are distributed evenly? I can do that for tribe quadrants fairly easily by looping through the quadrants. With tribe quadrants turned off, though, we'd need to change the tag creation logic in randomizeAgentEndowments from using random.randrange() to incrementing over the range of tribes like other endowments.

colinhanrahan commented 2 months ago

Looks like it's working pretty well now. Tribes are uniformly distributed over the number of agents at simulation start, and tags generated by tribe return the correct tribe from findTribe. The binomial distribution actually occurs pretty quickly—you'll see that with three tribes blue quickly takes over because it's the "middle" tribe for tag zeroes.

By the way, tribe 4's color #FAFA32 is indistinguishable from max sugar.

nkremerh commented 2 months ago

I will fixing GUI colors in a commit soon. That and color 5 and color 8 are remarkably similar for having what I thought were different enough hex values.

nkremerh commented 2 months ago

Also, I am fairly certain the book authors constrained their experiments to two tribes only otherwise this distribution issue would have become readily apparent.