Subtracting element of ith position from element at (i + 1)th position of any list in netlogo - netlogo

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

Related

How to find the largest network cluster?

"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.

How to create a sequential counter in NetLogo 6.2?

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.

How to fix "Nothing named ? has been defined" error in NetLogo 6.0.4

I downloaded the modified random clusters code for generating neutral landscape models using the Millington's version of the modified random clusters approach in the NetLogo modeling commons. When I click the "generate-landscape" button, the "fill-landscape" procedure in the code causes a "Nothing named ? has been defined" error.
When I created the attached interface image and attempted to run the adjoining code below. The problem seems to be related to the question mark in the "occurrences" report function. The reduce function is not working as intended. Is there a work around for this? See interface, then code below:
ifelse ( any? neighbours with [ cluster != nobody ] ) ;; check if there are any assigned patches in neighbourhood
[
let covers []
ask neighbours with [ cluster != nobody ]
[
set covers fput cover covers ;;ask neighbours to add their covers to the list
]
let unique-covers remove-duplicates covers ;;create a list of unique covers
let max-cover-count -1 ;the number of neighbours with the maximum cover
let max-cover -1 ;the maximum cover
ifelse(length unique-covers > 1)
[
;if there is more than one unique-cover
foreach unique-covers ;for each of the unique covers
[
let occ occurrences ? covers ;count how many neighbours had this cover
ifelse(occ > max-cover-count) ;if the count is greater than the current maximum count
[
set max-cover ? ;set this as the dominant cover
set max-cover-count occ ;update the current maximum count
;---------------
to-report occurrences [x the-list]
report reduce
[ifelse-value (?2 = x) [?1 + 1] [?1]] (fput 0 the-list)
end
;---------------
The code is suppose to generate a neutral landscape model using the modified random clusters approach developed by Saura and Martinez-Millan (2000). However, the error "Nothing named ? has been defined" error the code from running smoothly. Looking forward to thoughts ...
The old ? syntax from NetLogo 5.x was replaced with the new -> syntax in NetLogo 6. See https://ccl.northwestern.edu/netlogo/docs/programming.html#anonymous-procedures
So, for example, in NetLogo 5, you would write:
foreach [0 1 2 3] [
print ?
]
in NetLogo 6, you write:
foreach [0 1 2 3] [ x ->
print x
]
A combination of Bryan's answer (first procedure) and the NetLogo Dictionary (second procedure) gives you the following. The comments indicate the new bits. Not tested.
ifelse ( any? neighbours with [ cluster != nobody ] )
[ let covers []
ask neighbours with [ cluster != nobody ]
[ set covers fput cover covers
]
let unique-covers remove-duplicates covers
let max-cover-count - 1 ; added a space around subtraction
let max-cover - 1 ; more spacing
ifelse(length unique-covers > 1)
[ foreach unique-covers
[ this-cover -> ; here's the new bit, calling ? 'this-cover'
let occ occurrences this-cover covers ; passes to the occurrences procedure
ifelse(occ > max-cover-count)
[ set max-cover this-cover ; using the name this-cover again
set max-cover-count occ
And for occurrences, you can take the procedure directly from the NetLogo Dictionary reduce example
to-report occurrences [#x #the-list]
report reduce
[ [occurrence-count next-item] -> ifelse-value (next-item = #x)
[occurrence-count + 1] [occurrence-count] ] (fput 0 #the-list)
end

Netlogo: How to compute sum of items of lists within a list?

I would like to make the sum = the total of pollen recieved by a plant from other plants (Donnors) which is stored in a list of a list (own by each turtle = plant).
The following code make an error (when computing the sum):
OF expected input to be an agent or agentset but got the list
[[119.05593 50 50] [301.25853 50 50] [30.23906 50 50] [460.525845 50
50] [55.16717 50 50] [301.25853 50 50]] instead.
Does any one could help me about the mistake in the line "set Tot_pol sum ..." ?
Many thanks for your help.
to check-pol [m] ;; we check the pollen recieved by the two morphs
set Donnors [] ;; empty list of pollen donnors
ask zsps with [morph = m] ;; morph of the pollen reciever
[
set totpol 0
;; check for pollen donnors and morph for compatiblity within a radius :
ask zsps with[distance myself <= 20 and morph != m]
[
set totpol (NMaleFlowers * 100 * item round (distance myself) pollination-list) ;; the farther the less pollen
set Donnors lput [ (list totpol NMaleFlowers NFemFlowers)] of myself Donnors
]
set Tot_pol sum [ item (position 0 Donnors) Donnors ] of Donnors ;; total of pollen recieved
]
end
Luke's answer is good and should fix your problem. I suspect, however, that you are going to be doing lots of these types of sums. You may wish to set up a to-report that you can use for whichever item you want to sum over, just by passing the item number and the name of the list of lists. It would look like this:
to-report sum-item [#pos #listoflists ]
let items map [ x -> item #pos x ] #listoflists
report reduce [ [a b] -> a + b] items
end
The first line extracts the relevant item (remember index from 0) into a new list which the second line sums.
You would then use it with set Tot_pol sum-item 0 Donnors
Here's an answer that is not actually responding to your question. Instead, it is a more NetLogo-ish way of doing what I think you are trying to do with your code.
to check-pol [m]
ask zsps with [morph = m]
[ let senders zsps with [distance myself <= 20 and morph != m]
set totpol sum [NMaleFlowers * 100 * round (distance myself)] of senders
]
end
Your code gets into levels of ask that I think are unnecessary. What I think you are doing with your list is keeping track of the pollen donors. But an agentset is a cleaner approach and then you can simply pull out the information you want from the agentset using of.
Further, when you ask zsps with[distance myself <= 20 and morph != m] to set variable values in your code, then THOSE agents (not the receiving agent) are the ones having their variables changed. I think you are trying to take the perspective of the receiver of pollen, who looks around and received pollen from the other agents that are close enough. So the receiving agent should have the value changed.
This is not tested.
I'm not 100% sure what you're after here (you may want to look at the Minimum, Complete, and Verifiable Example guidelines), but if I'm reading you right you want the sum of the first item for each entry in the Donners list.
As to why your approach didn't work- NetLogo is telling you with that error that you've used of with a list, but of only works with agents or agentsets. Instead, you have to use a list processing approach. The simplest way might be to use sum in conjunction with map first in order to get what you need:
to sum-first-item
let example-list [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
let sum-of-firsts sum map first example-list
print sum-of-firsts
end
To translate to Donnors, try:
set Tot_pol sum map first Donnors
That should work, but without reproducible a code example I can't check.

read-from-string working in NetLogoWeb?

Is there any alternative to read-from-string that works in NetLogoWeb? I need to a string from an input field. The string contains some number of integers and should be converted to a list. Within NetLogo, I use this code:
to-report get-demand
report reverse sort read-from-string ( word "[" the-field-name "]")
end
However, it seems that read-from-string is not implemented yet in NetLogoWeb. Any way around?
Many thanks and best wishes,
Michal
P.S. Many thanks for developping NetLogoWeb. I really missed NetLogo plugins.
Unfortunately, we haven't yet added support for read-from-string to NetLogo Web. It probably won't be there in the near future, either.
Is the code supplied here the real code that's giving you problems? I assume that it isn't, but, if it is, you can just do this for the same effect:
to-report get-demand
report reverse sort (list the-field-name)
end
(That is, if the-field-name is what it sounds like, which would be a string containing only the name of some "field".)
I assume that your real case is more complex. I might be able to offer a better workaround if I saw the true code. Are you sure that you can't solve your problem with tasks?
I'd suggest:
to-report string-to-numbers [s]
if empty? s [ report [] ]
if first s = " " [ report string-to-numbers butfirst s ]
let pos position " " s
ifelse not is-number? pos
[ report (list string-to-number s) ]
[ report fput string-to-number substring s 0 pos
string-to-numbers substring s (pos + 1) length s ]
end
to-report string-to-number [s]
report reduce [10 * ?1 + ?2]
map [position ? "0123456789"]
explode s
end
to-report explode [s]
report map [item ? s] n-values (length s) [?]
end
Sample run:
observer> show string-to-numbers "12 345 67"
observer: [12 345 67]
I verified that this works in both desktop NetLogo and NetLogo Web.
Based on the previous answer (that the command will not be implemented soon), it seems the only solution is to implement a simple parser, i.e. something like this (works for integers separated by spaces):
to-report string-to-list [ s ]
let l []
let ss ""
let n 0
let mode "out"
repeat length s [
set ss first s
set s but-first s
if ( ( ss = " ") and ( mode = "in" ) ) [
set mode "out"
set l lput n l
set n 0
]
if ( member? ss "0123456789") [
set mode "in"
set n ( n * 10 ) + ( position ss "0123456789" )
]
]
if ( mode = "in" ) [ set l lput n l ]
report l
end
The reporter gets a string s and returns a list of integers.
Or is there any simpler way to implement it?
Just to have an up-to-date answer here, as of October 2017, NetLogo Web does support read-from-string. A case like read-from-string (word "[" the-field-name "]") should work just as in desktop and report the list value.