I have set decimal places in a Netlogo Monitor to 4. Numbers that end in 0's get truncated (3.4500 appears as 3.45, 3.4550 appears as 3.455). Is there some way to retain the 4 decimal appearance?
Suppose we define:
to-report zero-pad [n places]
let result (word precision n places)
if not is-number? position "." result [
set result (word result ".")
]
let padding-amount position "." result - length result + places + 1
let padding reduce word fput "" n-values padding-amount [0]
report (word result padding)
end
Let's see if it works:
observer> show zero-pad 1.2 3
observer: "1.200"
observer> show zero-pad 1.2468 2
observer: "1.25"
Looks good. So now, in the monitor, instead of just x, write e.g. zero-pad x 4 if you want four decimal places.
Related
If I have the following: set list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]. I would like to find a way to get, for example, a random item position for zero (2, 6 or 11) or for three (3, 12 or 13).
I have tried with:
let i (position (one-of list = 0) list )
print i
However, that only returns a boolean i. I know I could use position 0 list, but that gives priority to the first position (2, in the case of zero) while I would like it to randomly chosen from all values equal to zero on the list. I thought of using a while[], but I was wondering if there is a faster and simpler way.
In general, when you are working with lists, it is a good idea to familiarise yourself with anonymous procedures and some related primitives like map and filter.
I wrote a quick procedure, called positions that should be able to take care of this. First I create a list containing all the possible indexes: index-list.
Next, I use map to simultaneously go through the input-list and the index-list. It uses ifelse-value to check for each item of the input-list whether or not it corresponds to the input-item that you wanted to check it against. If they correspond, it returns the position of that item in the input-list. Otherwise it returns FALSE.
The final step is to filter out all the FALSE responses so that you are left with a list containing only the positions of your input-item in the input-list.
to-report positions [ input-item input-list ]
let index-list range length input-list
let position-list (map [ [list-item index] -> ifelse-value input-item = list-item [index][FALSE] ] input-list index-list)
report filter [index -> index != FALSE] position-list
end
Testing this gives [2 6 11] as a result, which corresponds with what you would expect
to test
let my-list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]
show positions 0 my-list ;[2 6 11]
end
"nw:weak-component-clusters" in the Networks extension will return a list of weakly connected agentsets. I would like to output the number of turtles in the biggest of these.
So
show nw:weak-component-clusters
observer: [(agentset, 15 turtles) (agentset, 20 turtles) (agentset, 16 turtles)]
would return 20.
Is there an easy way to do this please?
This isn't pretty but it will work:
to find_max
let my_list []
let my_max 0
let turt_list nw:weak-component-clusters
foreach turt_list [x -> ask x [set my_list lput count x my_list]]
set my_max max my_list
show my_max
end
There is a simpler approach using map:
to-report count-of-largest-cluster
report max (map count nw:weak-component-clusters)
end
map takes a reporter and a list as inputs, and reports a list whose items are the result of the input reporter being run for every item of the input list.
nw:weak-component-clusters is a list of agentsets, therefore map count nw:weak-component-clusters is a list of each agentset's count. Note that the parentheses in my solution are optional and only there for readability.
I would like to know if there is any way to implement a sequential counter without using a list by intervals. I'm trying to implement the following: at the end of each tick is counting the population size (NFinal). And then, we would check the constancy of the population, through a subtraction (the logical test would be the result of this subtraction is equal to zero during 3 consecutive ticks?).
For example:
NFinal of tick 0 - NFinal of tick 1 = 0
NFinal of tick 1 - NFinal of tick 2 = 0
NFinal of tick 2 - NFinal of tick 3 = 0
If this is the scenario (with 3 sequential values equal to zero), the simulation will stop.
However, if it is in the scenario:
NFinal of tick 0 - NFinal of tick 1 = 0
NFinal of tick 1 - NFinal of tick 2 = 0
NFinal of tick 2 - NFinal of tick 3 = 2
The simulation does not stop (since it did not have 3 zero values in sequence) and therefore would reset the counter to continue the simulation.
However what I managed to implement was by intervals using list. I don't know if it's the best way. Well, every time I use the list my model is getting slower. Is there a simpler way to implement this?
Thanks in advance!
Attempt below:
globals [ StabilityList ConstanceInterval ]
to go
if ConstanceInterval = 0 [ stop ]
end
to StabilityCheckerProc
set StabilityList lput 1 StabilityList ;; 1 = NFinal
let i 3 ;;
if length StabilityList >= i
[
let t1 last StabilityList
let start ( length StabilityList - i )
let t0 item start StabilityList
set ConstanceInterval abs ( t1 - t0 )
]
set StabilityList get-last i StabilityList
end
to-report get-last [ num lst ]
let b length lst
let a b - num
report sublist lst ( ifelse-value ( a < 0 ) [ 0 ] [ a ] ) b
end
You could use a counter to track the number of occurrences in a row, such that if your condition is satisfied you increase the counter, and if it is not you reset the counter. For example:
globals [ zero-tracker ]
to setup
ca
reset-ticks
end
to go
let variable-placeholder random 5
ifelse variable-placeholder = 0 [
; If a zero is recorded (eg, the result of your subtraction operation,
; increase the zero-tracker by one
set zero-tracker zero-tracker + 1
] [
; If anything BUT a zero is recorded, reset the zero-tracker
set zero-tracker 0
]
tick
if zero-tracker = 3 [
stop
]
end
Luke's answer is the answer.
But, if for any reason you did have a problem that needed to look at the last X things, and a counter was not going to work, you could use a list, but keep it at length X.
;; in setup, initialize the list with 'memory-size' items
set memory map [ -> 0] range 0 memory-size
;; in go, add a new memory to the list, and drop an old memory
set memory but-first lput value memory
;; then do what you must to examine the memories
< that code here >
Still slower than using a counter, but probably faster than accumulating and taking sections from an ever-growing list of values.
If you do need to maintain an ever-growing list of values, you might still maintain this smaller list.
Finally, even when using the ever-growing list of values, it would be fewer operations to take the sublist off the front of the list:
;; add new memory to front of list
set memory fput value memory
;; get last three memories from front of list
let last-three sublist memory 0 3 ;; no math or length needed
As always, test any assertion that something might be faster.
I hope this is a simple solution, but I'm having a difficult time with it.
Problem:
I would like to weight the probability of something occurring by an variable not a constant
Setup
My agent is a farm.
Farms own four variables that represent the
number of cows, goats, pigs, and sheep on it.
When a farm wants to
remove an animal, I'd like the likelihood to remove a member of a
particular species to be directly proportional to quantity of each
species on the farm (i.e. if there are 7 goats, 2 cows, and 1 pig,
there is a 70% probability of taking a goat and a zero percent
probability of taking a sheep)
I have found formula like this for when you know the exact numerical weight that each value will have:
to-report random-weighted [values weights]
let selector (random-float sum weights)
let running-sum 0
(foreach values weights [
set running-sum (running-sum + ?2) ; Random-Weighted Created by NickBenn
if (running-sum > selector) [
report ?1
]
])
end
and the methods described in the rnd extension. But both of these throw the "expected a constant" error when i put "Cow" in instead of a constant.
Something like:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities [2 0 7 1]
let indices n-values length values [ ? ] ; Made by Nicolas Payette
let index rnd:weighted-one-of indices [ item ? probabilities ]
let loca item index values
end
works well, but if I were to replace it with:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities [Num-Cows Num-Sheep Num-Goats Num-Pigs]
let indices n-values length values [ ? ] ; Made by Nicolas Payette
let index rnd:weighted-one-of indices [ item ? probabilities ]
let loca item index values
end
it fails.
Alan is right: you need to use the list primitive (as opposed to just brackets) when you want to construct a list from anything else than constants.
I would add two things to that:
The latest version of the rnd extension has two sets of primitives: one for agentsets, and one for lists. So you should probably update and use the rnd:weighted-one-of-list primitive.
Your code is based around using indices to pick an item. That's fine, but that's not the only way to do it.
You could also have something like:
to example1
let values ["Cow" "Sheep" "Goat" "Pig"]
let probabilities (list Num-Cows Num-Sheep Num-Goats Num-Pigs)
let loca first rnd:weighted-one-of-list (map list values probabilities) last
end
This may be a bit trickier to understand, but here is the gist of it:
The (map list values probabilities) expression takes both your values list and your probabilities list and "zips" them together using the list primitive, resulting in a list of pairs: [["Cow" 2] ["Sheep" 0] ["Goat" 7] ["Pig" 1]].
We pass the last reporter to the rnd:weighted-one-of-list primitive to tell it that the last (i.e., second) item of each of these pairs should be used as the probability.
Since rnd:weighted-one-of-list operates on a list of pairs, the item it returns will be a pair (e.g., ["Goat" 7]). We are only interested in the first item of the pair, so we extract it with the first reporter.
Note that we use the NetLogo's concise syntax for tasks when passing list as an argument to map and last as an argument to rnd:weighted-n-of. You could replace list with [ (list ?1 ?2) ] and last with [ last ? ], but it would be uglier.
I want to create a list of count values of some variable (tot-turtles) increasing with each tick. I tried the below code but all time list is having single element of length 1. neither i is getting incremented. please correct me.
set tot-turtles count turtles
to go
let mylist [ ]
set mylist lput tot-turtles mylist ; show mylist
set i 1
foreach mylist [ ; print ? ;show i
set x ? - i ; print x
set i (i + 1) ;show i
]
end
I want to subtract elements of list in the following fashion where the length of list depends on the number of simulation run or till simulation ends, then
i need subtraction of element as element at (i + 1)th - element at ith position till the end of the list.
In the above code i is 1 then increments by 1 ie 2 and then continue to 1 2 1 2 1 2. mylsit always shows single element. Confused with "?" , it gives element of current position if i am not wrong, but how we know the current position?
Please help me out of these doubts and code. thanks a lot.
Thank you sir, yes i was doing mistake with local and global variable i checkd it later. and the thing i wanted is as below.
to setup
set mylist [ 0]
set item-difference 0
end
to go
set tot-turtles count tutles set
mylist lput tot-turtles mylist
let _n (length mylist)
set item-difference (( item ( _n - 1 ) mylist - item ( _n - 2 ) mylist )
end
I hope you got Allan sir.
It's a bit difficult to tell what you are after, but it seems you are using a local variable when you want a global variable. See if this offers some help:
globals [mylist]
to setup
ca
set mylist []
crt 10
end
to go
crt 1
set mylist lput (count turtles) mylist ; show mylist
end
to test
let _n (length mylist)
(foreach mylist n-values _n [? + 1] [
print ?1 - ?2
])
end