Growth rate netlogo - installation

How can I, in the setup stage, add a growth rate between 2 type of agents I have?
In other words, I have type 0 and type 1 of patches.
I want set in the setup a slider in which I can decide the growth rate percentage between type 0 and type 1.
globals[]
;patches attributes
patches-own [
id
ptype
growth
]
;turtles attributes
turtles-own [
ttype
previous-id
]
to setup
clear-all
reset-ticks
;set patch
ask patches[
set pcolor white
set ptype 0
set growth (ptype 0) + (ptype 1 * Per-Patches1 / 100) (here the problem)
]
Thank you!
I can't find the code

You only have a single turtles-own variable called ptype. That ptype is set to 0. There is no such thing as a variable called ptype 0 or a variable called ptype 1 so using that in a calculation will evidently give you errors. More specifically, what you wrote in your last line of code comes down to:
set growth (0 0) + (0 1 * Per-Patches1 / 100)
Your problem is not the slider, but rather the fact that you don't seem to define your growth rate and your different patch types well.
After you have divided the patches in two groups, you can let them choose their growth depending on which ptype they have using an ifelse function.
ask patches [
(ifelse
ptype = 0 [set growth growth-input ]
ptype = 1 [set growth growth-input * modifier-from-slider ]
)
]
I here added the ifelse function with round brackets, since this one lets you enter multiple conditions. The shorter way to write it would be the following, but I think that in this case it is good to specifically differentiate between the ptypes, just so that you see more clearly what is happening.
ask patches [ ifelse ptype = 0 [set growth growth-input ] [set growth growth-input * modifier-from-slider ] ]

Related

Generate a number within a range and considering a mean val

I want to generate a random number within a range while considering a mean value.
I have a solution for generating the range:
turtles-own [age]
to setup
crt 2 [
get-age
]
end
to get-age
let min-age 65
let max-age 105
set age ( min-age + random ( max-age - min-age ) )
end
However, if I use this approach every number can be created with the same probability, which doesn't make much sense in this case as way more people are 65 than 105 years old.
Therefore, I want to include a mean value. I found random-normal but as I don't have a standard deviation and my values are not normally distributed, I can't use this approach.
Edit:
An example: I have two agent typologies. Agent typology 1 has the mean age 79 and the age range 67-90. Agent typology 2 has the mean age 77 and the age range 67-92.
If I implement the agent typologies in NetLogo as described above, I get for agent typlogy 1 the mean age 78 and for agent typology 2 the mean age 79. The reason for that is that for every age the exact same number of agents is generated. This gives me in the end the wrong result for my artificial population.
[Editor's note: Comment from asker added here.]
I want a distribution of values with most values for the min value and fewest values for the max value. However, the curve of the distribution is not necessarily negative linear. Therefore, I need the mean value. I need this approach because there is the possibility that one agent typology has the range for age 65 - 90 and the mean age 70 and another agent typology has the same age range but the mean age is 75. So the real age distribution for the agents would look different.
This is a maths problem rather than a NetLogo problem. You haven't worked out what you want your distribution to look like (lots of different curves can have the same min, max and mean). If you don't know what your curve looks like, it's pretty hard to code it in NetLogo.
However, let's take the simplest curve. This is two uniform distributions, one from the min to the mean and the other from the mean to the max. While it's not decreasing along the length, it will give you the min, max and mean that you want and the higher values will have lower probability as long as the mean is less than the midway point from min to max (as it is if your target is decreasing). The only question is what is the probability to select from each of the two uniform distributions.
If L is your min (low value), H is your max (high value) and M for mean, then you need to find the probability P to select from the lower range, with (1-P) for the upper range. But you know that the total probability of the lower range must equal the total probability of the upper range must equal 0.5 because you want to switch ranges at the mean and the mean must also be the mean of the combined distribution. Therefore, each rectangle is the same size. That is P(M-L) = (1-P)(H-M). Solving for P gets you:
P = (H-M) / (H - L)
Put it into a function:
to-report random-tworange [#min #max #mean]
let prob (#max - #mean) / (#max - #min)
ifelse random-float 1 < prob
[ report #min + random-float (#mean - #min) ]
[ report #mean + random-float (#max - #mean) ]
end
To test this, try different values in the following code:
to testme
let testvals []
let low 77
let high 85
let target 80
repeat 10000 [set testvals lput (random-tworange low high target) testvals]
print mean testvals
end
One other thing you should think about - how much does age matter? This is a design question. You only need to include things that change an agent's behaviour. If agents with age 70 make the same decisions as those with age 80, then all you really need is that the age is in this range and not the specific value.

Random matrix with determinant not zero in Maxima

I want to generate a matrix with random entries such that the determinant of that matrix is not zero using Maxima and further down the line implement this in STACK for Moodle. I am completely new to working with Maxima (or any CAS for that matter), so I have been going through various examples I found online and have so far managed to get this:
Generating a 2x2 random matrix with 0 or 1 (for simplicity reasons) and calculating its determinant:
g[i,j]:=1-random(2);
M1:genmatrix(g,2,2);
dM1:determinant(M1);
For the next step I wanted to define a matrix M2 as follows:
M2:(if dM1#0 then M1 else ***)
If the determinant of the matrix M1 is already not zero, fine, I'll go with that, but I am struggling with the else-part. I was thinking of creating a loop that generates new random numbers g[i,j] for M1 until I get a matrix with determinant not zero, but am unsure on how to do that or if there are other options.
In addition: as I mentioned this is ultimately something I want to implement in STACK for moodle (question will be to solve a system of linear equations with the generated matrix being the matrix of this system), so I don't know if there are any limitations on using if and while loops in STACK, so if somebody is aware of known problems I would appreciate any input.
You can say for ... do ... return(something) to yield something from the for-loop, which can be assigned to a variable. In this case it looks like this works as intended:
(%i9) M2: for i thru 10
do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
if determinant(%%) # 0 then return(%%));
[ 1 0 ]
(%o9) [ ]
[ 0 1 ]
(%i10) M2: for i thru 10
do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
if determinant(%%) # 0 then return(%%));
[ 1 0 ]
(%o10) [ ]
[ 1 1 ]
(%i11) M2: for i thru 10
do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
if determinant(%%) # 0 then return(%%));
[ 1 1 ]
(%o11) [ ]
[ 0 1 ]
Note that the first argument for genmatrix is a lambda expression (i.e. unnamed function). If you put the name of an array function such as g in your example, it will not have the intended effect, because in Maxima, array functions are memoizing functions, giving a stored output for an input that has been seen before. Obviously that's not intended if the output is supposed to be random.
Note also that M2 will be assigned done if the for-loop runs to completion without finding a non-singular matrix. I think that's useful, since you can see if M2 # 'done to ensure that you did get a result.
Finally note that it makes a difference to use the "group of expressions without local variables" (...) as the body of the for-loop, instead of "group of expressions with local variables" block(...), because the effect of return is different in those two cases.

NetLogo: Assign Turtles Randomly but Equally to Different Groups

I used the code below to create 50 turtles and randomly assign them to one of four different strategies (i.e. a, b, c and d):
The problem is that when I decrease the number of created turtles or when I increase the number of strategies, I face a situation where at least one of the strategies is not taken by any turtle.
turtles-own [ my_strategy ]
to setup
;; create 50 turtles and assign them randomly
;; to one of four different strategies
create-turtles 50 [
set my_strategy one-of [ "a" "b" "c" "d" ]
]
end
I need your help here to:
1. Make sure that I do not face a situation where one or more strategies are not taken by any turtle.
2. Make sure that the number of turtles assigned to each strategy is roughly equal.
I tried to solve the problem by using the code below, but it did not work:
turtles-own [ my_strategy ]
to setup
let strategies [ "a" "b" "c" "d" ]
let turtles-num 51
let i 0
create-turtles turtles-num
while [ not any? turtles with [ my_strategy = 0 ] ] [
ifelse i < length strategies - 1 [ set i i + 1 ] [ set i 0 ]
ask n-of ceiling ( turtles-num / length strategies ) turtles with [ my_strategy = 0 ] [
set my_strategy item i strategies
]
]
Thank you for your help.
In general, you should never use who numbers for anything in NetLogo. However, this is one of the very few occasions where it's appropriate.
From comments, you actually want equal (or as close to equal as possible) numbers in each group so you don't need to calculate the number in each group. When turtles are created, they are created with sequential who numbers. So you can use the mod operator to assign them to each strategy in turn.
turtles-own [ my_strategy ]
to setup
;; create 50 turtles and assign them equally
;; to one of four different strategies
create-turtles 50 [
set my_strategy item (who mod 4) [ "a" "b" "c" "d" ]
]
end

NetLogo Efficient way to create fixed number of links

I have about 5000 agents (people) in my model. I want to give them an arbitrary number of friends and have reciprocal but random pairing. So if person A chooses person B then person B also chooses person A. My code works fine, but is fairly slow. I will likely want to increase both the number of friends and the number of people in the future. Any quicker suggestions?
ask people
[ let new-links friends - count my-links
if new-links > 0
[ let candidates other people with [ count my-links < friends ]
create-links-with n-of min (list new-links count candidates) candidates
[ hide-link ]
]
]
Note that friends is a global variable in the above code, but my eventual code will probably generalise to have wanted-number-of-friends as an attribute of people.
EDITED Added if new-links > 0 condition so that the nested ask is avoided when no candidates need to be found. This improved speed but still not really scaleable.
Great question. This is actually quite challenging to optimize. The problematic line is:
let candidates other people with [ count my-links < friends ]
This is slow because it has every agent checking with every other agent. With 5000 agents, that's 25,000,000 checks! Unfortunately, there isn't really a good way to optimize this particular line without some fancy data structures.
Fortunately, there is a solution that generalizes really well to generating any degree distribution in the network (which it sounds like that's what you ultimately want). Unfortunately, the solution doesn't translate super well to NetLogo. Here it is though:
let pairs [] ;; pairs will hold a pairs of turtles to be linked
while [ pairs = [] ] [ ;; we might mess up creating these pairs (by making self loops), so we might need to try a couple of times
let half-pairs reduce sentence [ n-values friends [ self ] ] of turtles ;; create a big list where each turtle appears once for each friend it wants to have
set pairs (map list half-pairs shuffle half-pairs) ;; pair off the items of half-pairs with a randomized version of half-pairs, so we end up with a list like: [[ turtle 0 turtle 5 ] [ turtle 0 turtle 376 ] ... [ turtle 1 turtle 18 ]]
;; make sure that no turtle is paired with itself
if not empty? filter [ first ? = last ? ] pairs [
set pairs []
]
]
;; now that we have pairs that we know work, create the links
foreach pairs [
ask first ? [
create-link-with last ?
]
]
It doesn't matter if friends here is a global or a turtle variable. The amount of time this takes depends on the number of times that it needs to try making pairs, which is random. Experimenting, I found that it was usually about 3 seconds with 5000 agents, each with degree 5. This is compared to about 60 seconds on my machine with your original way of doing this (which, for what it's worth, is the way I would recommend when using fewer agents).
After debugging (see NetLogo Efficiently create network with arbitrary degree distribution), the following version is relatively efficient. It constructs an agentset (called lonely below) for the turtles that still need links and deletes them as they get enough links. Removing individual turtles is more efficient than the nested process to create the candidate set each time.
The variable nFriends is a global (with a slider in the original model) that is the target number of links, identical for all agents.
let lonely turtles with [count my-links < nFriends]
ask turtles
[ set lonely other lonely
let new-links nFriends - count my-links
if new-links > 0
[ let chosen n-of min (list new-links count lonely) lonely
create-links-with chosen [ hide-link ]
ask chosen [ if count my-links = nFriends [ set lonely other lonely ] ]
]
]

calculate the mean over a set amount of ticks

I want the observer to calculate the mean of the number of floodings of a house (=patch) over the last 10 years (=ticks) when a certain action takes place (in this case, an insurance application by a turtle). This occurrence doesn't occur regularly, it can be regarded as a random occurrence (more or less).
So basically, I need some code that calculates the mean of floodings over the last 10 ticks when insurance application occurs.
Assuming floodings is a patch-variable and you'd like to determine the mean number of floodings for a given patch:
patches-own [
floodings
floodingsHistory
floodingsMean10
]
; At the end of each tick, patches store the current
; number of floodings in a list:
ask patches [ set floodingsHistory fput floodings floodingsHistory ]
; In case of [insurance application] patches (or a certain patch) calculate
; the mean over a sublist that only comprises the values of the latest 10 ticks:
ask patches [ set floodingsMean10 mean (sublist floodingsHistory 0 10) ]

Resources