19  Implementing mechanisms

We now reach the “spicy” part of Pond Trade’s development. Until this point, settlements are entirely static, and traders are created only in setup, then travel back and forth without affecting settlements.

Remember that the core dynamics of the first-tier conceptual model was made up of two overlapping feedback loops. It could be decomposed as:

Pond Trade conceptual model at start (first tier)
The loops of the first-tier conceptual model and its key implementation points

19.1 Implementing one feedback loop - trade and economic size 🤔

First, we want to implement the general feedback loop described in the conceptual model, connecting settlement size and trade flow.

Before looking at the solution, try to write the code yourself:

  • Traders load and unload goods at the base and destination settlements (use a variable: cargoValue)
  • Settlements increase their size with goods coming by trade
  • Reorganise the behaviour of traders inside a update-traders procedure
  • Settlement size decay over time, down to a minimum size of 1 (use a parameter: settlementSizeDecayRate)

Things to consider:

  • When should traders load and unload goods?
  • How to increase settlement size based on goods?
  • How to decrease settlement size over time?

Solution:

Let us reorganise the behavioural cycle of traders into a new separate procedure, update-traders:

Notice that we refactor the previous code, splitting the former procedures into several more specialised parts.

We then define the new procedures to handle the interaction between traders and settlements:

Observe that we are defining a very simple “submodel”, where the economic size units of one settlement produce an equivalent amount of transportable value (cargoValue), which is transferred by traders to another settlement, again as economic size units. However, with this mechanism, we are increasing the economic size of settlements in every trader trip but never decreasing it. To avoid this, we must specify a second mechanism that “decays” economic size over time, up to an arbitrary baseline value (i.e., 1).

For now, we implement this mechanism directly inside the go procedure, where we also call update-traders:

We must add to the interface yet another parameter to regulate decay, settlementSizeDecayRate (from 0 to 25, by 0.01, default value of 5). This is expressed as the percentage of sizeLevel that is subtracted at each simulation step.

19.2 Visualising dynamics

To better explore the effects of this feedback loop, we should start adding plots to the interface. Select Plot in the drop-down menu and add two plot objects, as you have done with buttons, sliders, etc. Configure them as follows:

19.3 Checking the milestone File (step 8)

We can now run the model with a few settlements and repeat go many times. Explore different seed numbers. Are settlements reacting to traders’ dynamics at all? Is the value of settlementSizeDecayRate too high or low? What are we doing wrong?

Pond Trade step 8
Pond Trade step 8

19.4 Detecting and correcting mistakes 🤔

Before moving to the second feedback loop, we must solve our problem.

Use inspect and printing commands to debug the model.

Can you tell what is wrong with the model behaviour?

Solution:

If you followed any of the different approaches for debugging (e.g., inspecting agents, printing messages in mid-code), you have detected that traders are not transporting any cargo value. The problem resides in how we have scheduled the calls for unload-cargo and load-cargo. Notice that we added load-cargo to a conditional call ask (turtle-set tradersInBase tradersInDestination) with [cargoValue > 0], only relevant to traders with cargo, which is impossible for traders to fulfil initially.

We reorganise update-traders as follows:

Pond Trade step 8 (after correction)
Pond Trade step 8 (after correction)

We can now see how, quite often, one or very few hubs emerge among settlements.

19.5 Implementing two feedback loops - trade-production and trade-number of traders 🤔

We split the general positive feedback loop into two, as specified in our concept model. These represent the effects of trade flow in settlement size through change in stock of goods and the number of traders per settlement.

Before looking at the solution, try to write the code yourself (medium-to-hard challenge):

  • Settlements produce goods every tick in proportion to their size (use a parameter: productionRate; use variables: sizeLevel, stock)
  • The number of traders per settlement increases with settlement size (use variables: currentNumberOfTraders, potentialNumberOfTraders)
  • Reorganise the behaviour of settlements inside a update-settlements procedure

Things to consider:

  • How to increase the stock of settlements over time?
  • How to calculate the potential number of traders?
  • How to create new traders when needed? How to remove them?

Solution:

The key addition is that now we will have to differentiate, for each settlement, between currentNumberOfTraders and potentialNumberOfTraders, and update these according sizeLevel. To wrap up all this, we finally implement an update procedure specifically for settlements (update-settlements).

We will also need to manage the traders that are left outside the maximum value for their base settlement. We create the tag isActivated to avoid creating and deleting too many traders in the same simulation run (i.e., it might become a problem as who numbers grow).

Settlements will now calculate potentialNumberOfTraders at every simulation step as a number equal to its size and will be allowed to create/reactivate or deactivate any traders accordingly.

Add a new Plot to visualise the count of traders through time, using the update command: plot count traders with [isActivated]

Our second feedback loop is now up and running!

However, our implementation is still rough around the edges and needs some refactoring and model extensions.

The representation of the production process is overly simplistic. Since there is no separate entity for sizeLevel, production value is immediately replaced after traders load their cargo. We must introduce a new settlement variable, stock, to keep track of the flow of economic value and implement a more explicit representation of production and value decay, independent of size decay. For this, we introduce two new parameters, productionRate and stockDecayRate (use the same interface configuration as settlementSizeDecayRate).

19.6 Detecting hidden “magic numbers”

In get-potential-number-of-traders, there is a hidden magic number worth exploring. We are assuming that economic size is translated entirely in an increase in the number of traders.

Keeping our ultimate model in mind (i.e., including cultural dynamics), let us use this opportunity and expose this number (“* 1”) as a parametric aspect of our model.

We name it frequencyOverQuality and make it a “trait” of settlements, setting it in create-coastal-settlements as a random number between 0 and 1:

As its name suggests, this trait’s meaning is: “how much the frequency of trade is prioritised over the quality of the cargo”. This is because the more traders a settlement has, the less cargo each will be able to get from stock, and so each will have less time to recover. Therefore, this trait represents an interesting aspect of how different settlements could organise trade.

To test the effect of frequencyOverQuality, create a temporary parameter as a slider in the interface named frequencyOverQuality_temp. Then, use it to set up the settlement variable, replacing random-float 1. Try different values to see whether and how this value affects the model dynamics. Remember to dlete this slider and return the code to the original configuration.

19.7 Checking the milestone File (step 9)

We can now observe that the number of traders in our pond oscillates around a stable low level most of the time. We can observe some exceptions by exploring higher values of numberOfSettlements. With enough settlements, our feedback loops push the dynamics towards the emergence of hubs, boosting the overall number of traders.

Pond Trade step 9
Pond Trade step 9

19.8 Updating the conceptual model

We reach the end of the implementation steps for the first-tier Pond Trade model. Given all the changes and extensions we made, we must revisit our conceptual model and update it accordingly.

Pond Trade conceptual model revised at step 9 (first tier)
Pond Trade conceptual model revised at step 9 (first tier)

This graphical description is still far from the implementation code, as it should be. However, it is now adequate for the new conceptual changes we introduced in the code.