I'm writing a NetLogo program and I'm facing an issue.
I have 'to-report' the procedure and it reports a value. In this report, I take input from the user.
But I want to use the reported value(output) in multiple other procedures.
to-report initial-goat
let goats-number read-from-string user-input "How many goats are there ?"
while [goats-number > 100] [set goats-number read-from-string user-input "Please enter a value below or equal to 100 "]
report goats-number
end
to goat-create
create-turtles initial-goat
end
to calculate
let x initial-goat
let alive count turtles
let dead (x - alive)
end
Here when I use the procedures to calculate and goat-create the program asks the user two times to give input. how to avoid this?
thanks.
best regards,
In fact, assuming that the calculate procedure runs each time step, your code will ask for the initial goats many times. As this information never changes, you should store it in a variable. There are two options.
If you want to use a question format, then:
globals [initial-goat]
to get-initial-goat
set goats-number read-from-string user-input "How many goats are there ?"
while [goats-number > 100] [set goats-number read-from-string user-input "Please enter a value below or equal to 100 "]
end
to goat-create
create-turtles initial-goat
end
to calculate
let alive count turtles
let dead (initial-goat - alive)
end
But the more usual way to do something like this is to simply have a slider on the interface rather than ask a question. You would have a slider (with upper limit 100) and then you only need:
to goat-create
create-turtles initial-goat
end
to calculate
let alive count turtles
let dead (initial-goat - alive)
end
Related
I want place 1 million fish in a lake at random to do so i have this.
ask patches[ if sum [peces] of patches < 1000000 [ask one-of patches with [mallor = 1][set peces peces + 1]]]
This is taking too long, how would you suggest to make it quicker? I know it´s the sum part as it has to always check, but i dont know how else to do it
A first thing I noticed is that you have the construction:
ask patches [ if ... [ ask one-of patches [...]]]
That first ask patches is completely redundant here. It lets each patch direct another random patch to make a fish. Since you use one-of the second time around I don't expect that the speed impact is too big but it should still help
Next, I suggest counting the fish you have already placed with a single local variable, instead of using sum [peces] of patches 1000000 times. Getting variables from an agent (with of or with) takes a lot of time if you have a lot of agents, and I remember from your previous questions that your number of patches is pretty huge.
Then thirdly, you also check for which patches the mallor = 1 condition is true 1000000 times. That one can also be grouped into a local agentset
let fish-placed 0
let mallor_patches patches with [mallor = 1 ]
while [fish-placed < 1000000] [
ask one-of mallor_patches [
set peces peces + 1
set fish-placed fish-placed + 1
]
]
Disclaimer, I haven't tested any of this code in Netlogo since I don't have the bigger model to test the code in. However I expect it will run a many times faster than what you originally wrote.
I would like to apply some process stochastically, but the order matters, or rather it should be done at random, how can I select a set of the same turtles to "treat" but to do it such that each tick, the order is random?
ask turtles [
;; apply a process to turtles, but not all turtles will get something as the pool of energy may have run out by the time they are selected.
]
Elements of agentsets (such as turtles) are always returned in a random order. Each time you use ask with an agentset, it will ask them in a new, random order. From the docs on agentsets:
An agentset is not in any particular order. In fact, it’s always in a random order. And every time you use it, the agentset is in a different random order. This helps you keep your model from treating any particular turtles, patches or links differently from any others (unless you want them to be). Since the order is random every time, no one agent always gets to go first.
And here is a quick example to demonstrate. If you run it in the Command Center you'll see the who numbers will be different each time you ask them to be shown.
to test
clear-all
create-turtles 10
show "Asking once..."
ask turtles [ show who ]
show "Asking a second time..."
ask turtles [ show who ]
end
And here is an example showing an energy pool that will be randomly used until it is gone. Note the turtles that will get to use it are whichever happen to come first out of the agentset for ask:
to test-pool
clear-all
let energy-pool 1000
create-turtles 100
ask turtles [
; can only act if some energy is left...
ifelse energy-pool > 0 [
let energy-use (min (list random 100 energy-pool))
set energy-pool (energy-pool - energy-use)
show (word "I used up " energy-use " energy points! " who " Only " energy-pool " points left")
] [
show (word "No energy left for me! " who)
]
]
end
I want to get the mean age of all dying turtles. I try to achieve that with the following code snipped:
globals [mean-death-age]
turtles-own [age prob-die?]
to-report mean-age
if (prob-die? = true) [
set mean-death-age mean [age] of turtles
]
report mean-death-age
end
Every turtle has the probability of dying (prob-die?) which should be calculated new with every time step (tick). If prob-die? is set to true mean-death-age should be updated. At the moment I have the problem that
I don't know how to initiate the variable mean-death-age. Maybe, working with an if loop would help
if (ticks >= 1) [
if (prob-die? = true) [
set mean-death-age mean [age] of turtles
]
]
I don't get an update of the already calculated mean-death-age but the variable is overwritten and the mean death age of the turtles of this tick is returned
I have problems accesing the value. When I try to call it with e.g.
print mean-age
I get the error message that mean-age is turtle-only even though I tried to save is as a global variable.
The entire code is available here.
I think you're making this more complicated than it needs to be. The easiest approach would be to just keep a list of ages at which turtles die, and then take the mean of that list:
globals [death-ages]
turtles-own [age]
to setup
clear-all
create-turtles 100 [
setxy random-xcor random-ycor
set age random 100
]
set death-ages [] ; start with an empty list
reset-ticks
end
to go
if not any? turtles [ stop ]
ask turtles [
if random 100 < age [
set death-ages lput age death-ages ; add age to our list of ages of death
die
]
]
print mean death-ages
tick
end
The only downside is that your list of death-ages is going to keep growing as your model runs. If that turns out the be a problem (though it probably won't), you will need to keep track of the current average and the current count of observations and update your average with something like set avg ((n * avg) + age) / (n + 1) set n n + 1.
As for why your current code doesn't work, there would be a lot of unpacking to do to explain it all (I'm sorry I can't now). As a general comment, I would suggest trying to take a step back when you run into difficulties like this and think about the minimum amount of information that you need to solve the problem. In this case, you need to mean age of death. What the simplest way to get that? Keep a list of ages of death and take the mean of that list when needed.
Kindly advise as to what I might be doing wrong in the following netlogo procedure for per-step mortality (I am implementing the "Pass-Away" procedure as a step in a "GO" procedure):
to Pass-Away
ask turtles [
let chances 1 - exp( -1 * mortality * ticks )
let dead-count 0
if chances >= 1 [die]
set dead-count dead-count + 1
]
end
Is the above code correct? Even if it is correct, is there a modified or better alternative means to achieve a constant (cummulative) per-time-step turtle mortality as they move through the world? Finally, how do I get the variable "dead-count" to report to a monitor on the netlogo interface?
This will mostly work, except that your dead-count will always be 1. But it will probably not work as you intend. You should embark on an exploration of what you have written. The first thing to do when you get confused is to break things into smaller pieces. The second thing is to add some helpful visuals. In this case, you will learn a lot by plotting your representation of chances. I'm going to have to guess that your mortality attribute is a random float, since you did not say so. The following is a partial fix of your code, which provides enough clues to continue. You will need to add a plot in the interface tab -- see https://subversion.american.edu/aisaac/notes/netlogo-basics.xhtml#core-concepts-plotting -- and you can add a monitor in the same way if you find monitoring with print too clunky.
globals [dead-count]
turtles-own [mortality]
to setup
ca
set dead-count 0
crt 100 [set mortality random-float 1]
reset-ticks
end
to go
ask turtles [pass-away]
print (word "dead count = " dead-count) ;easiest monitor
clear-plot ;you'll need to have added a plot
foreach sort [chances] of turtles [
[?] -> plot ?
] ;keep an eye on the largest value in this plot ... get it?
tick
end
to-report chances ;turtle proc
report 1 - exp( -1 * mortality * ticks )
end
to pass-Away ;turtle proc
if chances >= 1 [
set dead-count dead-count + 1 ;*inside* the conditional! must come first!
print (word "chances: " chances)
die
]
end
In NetLogo: suppose the model has
a turtle (0) of breed A with undirected links with 3 turtles (1, 2 and 3) of breed B;
the turtle 0 has an attribute named "number-of-links" that equals 3.
Now, let one of the 3 neighbors of 0 dies..
How can I program turtle 0 to change its number-of-links automatically to 2?
If all you want is a way of keeping track of the number links, use count my-links instead of a custom variable.
In general, the least bug prone way of having a value update when the number of links changes is to compute that value when you need it. For number of links, this is simply count my-links. For more complicated things, wrap them in a reporter:
to-report energy-of-neighbors
report sum [ energy ] of link-neighbors
end
If this doesn't work for whatever reason (agents need to react to a link disappearing or you're seeing a serious, measurable performance hit from calculating on the fly), you'll have to make the updates yourself when the number of links change. The best way to do this is to encapsulate the behavior in a command:
to update-on-link-change [ link-being-removed ] ;; turtle procedure
; update stuff
end
and then encapsulate the things that can cause the number of links to change (such as turtle death) in commands as well:
to linked-agent-death ;; turtle procedure
ask links [
ask other-end [ update-on-link-change myself ]
]
die
end