One of the unexpected benefits of Avian Computing and ConcX is the relative ease that simulations can be developed. ConcX is based on an asynchronous model with loosely-coupled threads, allowing the threads to dynamically adjust to their environment, the way that individual birds in a flock would dynamically adjust to their real-world situations.
I was remarking to a friend that the Dining Philosophers problem was interesting because it was a dynamic representation resource allocation much discussed and dissected by standard economics. Further, when using ConcX to solve the Dining Philosophers problem, I had noticed that it was possible to give one philosopher “competitive advantages” over the other philosophers. And that was when the Simulating Greed project was born.
The Simulating Greed project begins by increasing the number of participants and resources. And to make it a little more realistic, the philosophers were changed to Farmers and the resources changed from forks to Faucets. Every Farmer wants to water his crops. To do that, a Farmer must turn on two Faucets, one on each side of their property. See Diagram 1. Each Faucet is shared with the Farmer’s neighbors and can be set to provide water to one Farmer or the other but not both. Each Farmer, when they have control of both Faucets, can also set how long they will receive water.
Varying levels of greed can then simulated by the Farmers by how frequently they try to water their crops and how long they set the water to run. A greedy Farmer will try to water their crops very frequently and will also set the water to run a long time. A less greedy Farmer will try to water less often and for shorter durations.
In this simulation, the assumption is that greedy Farmers always want as much water as they can possibly get. More water is always assumed to be better and there is no limit to the supply of water. In real life, there is an effective limit to how much water a single farmer can use and to the amount of water available.
Another factor in the simulation is whether or not Farmer death is allowed. A Farmer can be configured to never die, regardless of the amount of water they have received, or they can be set to die if they haven’t received water within some configurable time period. This factor can have a significant impact on the results because dead Farmers no longer compete for water. If a Farmer dies early, the neighbors of that Farmer find it easier to get water.
The Farmers have properties all in a row, with Faucets between each pair of properties. The basic setup has 10 Farmers with 10 Faucets. Each neighboring pair of Farmers have to share the Faucet between them. And to make demand even, the two end neighbors have to share with each other, even though they are furthest apart. See Diagram 1. This setup makes each Faucet a shared resource for 2 Farmers.
Note that Faucet 10 is shared between Ajia1 and Jack 1. There should be a dotted line that runs between these farmers, but there wasn’t any clean way to draw this relationship without cluttering up the image. Instead of the dotted line, Faucet 10 is shown at both the top and bottom of Diagram 1with half of the valve grayed out; you’ll have to use your imagination to draw in the water line between them. Ajia 1 and Jack 1 must share a Faucet to make it a closed and equal system where they both must compete with two other Farmer, just like all the rest.
The number of Farmers is increased to 20 but the number of Faucets remains unchanged. See diagram 2. This setup makes each Faucet a shared resource for 4 Farmers.
Even More Setups
The number of Farmers is increased to 40 and 80 but the number of Faucets remains unchanged. There is no diagram for these setups because I can’t visualize a configuration of Farmers that would allow the to share the Faucets without moving their farms into satellites in outer space. With 40 Farmers, each Faucet is a shared resource for 8 Farmers. With 80 Farmers, each Faucet is a shared resource for 16 farmers.
Nap times are initially set to 300ms for each Farmer. The length of time they keep the Faucet on is initially 300ms. The amount of water delivered to a Farmer is calculated based on the number of milliseconds the Farmer keeps the water flowing and the number of times the Farmer successfully turns on the water. For example, a Farmer who successfully turns on the water 7 times for 300ms receives 2100 units of water. If the Farmer’s neighbor successfully turns on the water 7 times for 500ms receives 3500 units of water.
Each Farmer keeps track of his own results during each simulation run. When the Farmer terminates (either by early death or end of natural life), they write their individual Results to the TupleTree. A Summarizer bird is running during the run and any time a Farmer dies for any reason, the Summarizer eats their Results and adds their stats to the stats for the other users. For example, Ajia1 had 100 units of water delivered and Cate1 had 200 units of water delivered, so the Summarizer records that 300 units of water had been delivered.
When the Summarizer terminates, it writes its Summary info to the TupleTree. When the user selects the TupleTree tab and clicks the Show Tree button, all of the Food items in the tree are listed. The ResultsProcessed Food items contain summaries of the results for individual Farmers. The Summary Food item contains the totals for all Farmers as well as detailed summaries of each bird in it’s Content object. To see the SummaryDetails object contained in the Summary.Contents object, enter a filename in the field at the bottom of the TupleTree tab and the press the Save button. Any object contained in a Contents object will print the values that they hold IF that object implements the toDetailString() method. Otherwise it will print the info generated by that object’s toString() method.
All together, the new features available in the TupleTree combined with saving the results of the runs provides the ability to analyze how individual Farmers are affected by the greed of their neighboring Farmers. More about those results in the next blog.