Selecting patch from an agentset with highest value in netlogo - netlogo

I have an agent set named "open patches", which I found using the following, in which "number_open_patches" is a specific radius depending on "length":
`ask turtles ['
let my_patch self
set number_open_patches ((50 * (length ^ 2)) / 100) / resolution
let open_patches patches in-radius number_open_patches
I found the distance of these patches to a particular turtle "my_patch" using:
let distance_patch [distance my_patch] of open_patches
I then calculate "patch attractiveness", which is just the distance of each of the patches ("distance_patch") in "open_patches" plugged into the equation below:
let patch_attractiveness ( map [[x] -> exp ((x / open_patches) * (log e (.2 / 1)))] distance_patch)
I would finally like to select the patch within "open_patches" that has the greatest value of "patch_attractiveness". I am using the code below:
let destination max-one-of open_patches [patch_attractiveness]
I get an error as it returns 'nobody'. Why would this be? How do I know that I would actually be selecting the right patch as "distance_patch" is just a list in random order?
EDIT: I also tried the code below, but am getting a "division by zero" error when I try to calculate patch attractiveness.
ask turtles [
let my_patch self
set number_open_patches ((50 * (length ^ 2)) / 100) / resolution
let open_patches patches in-radius number_open_patches
ask open_patches [
set distance_patch [distance self] of my_patch
set patch_attractiveness exp ((distance_patch / number_open_patches) * (log e (.2 / 1)))
]
]

You didn't give enough code to see what the problems are. Your line with the exponential dividing by an agent set doesn't seem syntactically correct. You don't show the code for calculating open_patches_in_radius and I suspect there are none and the rest of the line using that is just a distraction.
That said, I'd suggest going the opposite way.
let the patches own a distance and an attractiveness variable
but "distance" is a reserved word so it needs a different name.
ask the open-patches to determine their distance to your "my_patch" turtle and store that in their distance slot. ( instead of asking your patch )
compute whatever global things you need for your formula
ask open-patches to set their attractiveness based on their distance ( already computed) and some exponential decay formula that apparently includes some global factor.
then finally let your destination be the open-patch with the max attractiveness, which now has a much simpler formula using
"max-one-of agentset [reporter]" syntax, such as
let dest max-one-of open-patch [ attractiveness ]
or possibly you want only open-patches within a given radius, but again depending on the scattering of open-patches and the size of the radius, there may be none. Check for none when setting open-patches-in-radius because that's a valid subcase.

Related

Unable to generate multiple 'species' per breed in NetLogo

I'm new to NetLogo and I'm trying to create 2 sub-breeds (denoted by different shapes) within each breed for 2 breeds total (i.e. sharks and fishes). The chunks of code work as expected when ran individually, however, when running both chunks the first sub-breed of the fishes does not seem to initialise in the interface tab. For some reason the initialisation of the shark breed seems to interfere with the initiation of the fishes breed.
Any idea what i'm doing wrong? Code below.
; Create the agents
breed [sharks shark]
breed [fishes fish]
; Create the agents' variables
fishes-own
[
x0
y0
]
globals
[
species
species-f
]
to setup
; Always start with this
clear-all
reset-ticks
; Create sharks and species
create-sharks N-sharks ; N-sharks is a slider
[
set color blue
setxy random-xcor random-ycor
set species N-sharks
ask sharks
[
set shape "default"
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))]
[
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))]
[
set shape "star"
set size 3
]
] ; End create sharks and species
; Create fishes
create-fishes N-fishes
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
set species-f (N-fishes * species-ratio)
ifelse who <= species-f
[
set shape "sheep"
set size 5
]
[
set shape "cow"
set size 3
]
set color white
] ; End create fishes
end
There seem to be a number of misunderstandings about what code is run when by NetLogo, and what some pieces of code do: when you use create-turtles *number* [*commands*] (or with breeds, as in your case), commands is run once by every turtle being created (first the new turtles are created, then they run the commands in turn).
That means that every time you use ask sharks within the create-sharks' command block, every new shark will ask all other sharks to set shape and size. For example, if you create 100 sharks, instead of setting the shape and size only once you are doing it 10,000 times (100 * 100).
So you need to put all those commands out of their respective create-<breed>'s command blocks; for example:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
]
ask sharks [
set size 2.5
]
ask sharks with [who >= (species * (1 / 2))] [
set shape "square"
set size 2
]
ask sharks with [who < (species * (1 / 6))] [
set shape "star"
set size 3
]
This is still improvable code, but it shows how to achieve exactly the same thing by doing it once and not doing it N-sharks ^ 2 times.
A better way to do it is to bring those commands back inside the create-<breed>'s command block, but letting each agent carry out the task for itself only. That is, without using ask sharks but using ifelse, so that each shark will check its own condition:
create-sharks N-sharks [
set color blue
setxy random-xcor random-ycor
(ifelse
who >= (species * (1 / 2)) ; the first condition
[set shape "square" set size 2]
who < (species * (1 / 6)) ; the second condition
[set shape "star" set size 3]
; else
[set size 2.5])
]
All of this applies to the other breed too.
It is generally said that using who is a sign that the code should be improved, but let's not focus on this now.
You will have noticed that I omitted the part where you set species N-sharks. This is because I think there is another misunderstanding here and it is not clear to me what you wanted to do: species (such as species-f for the other breed) is a global variable. You are basically asking each of the 100 sharks (again, 100 for example) to do the same thing: set the value of a global variable to equal the value of another global variable. In this case, you are asking each shark to set species 100. This seems very unnecessary, especially considering that N-sharks is a slider used for setup and thus probably won't be changed during the simulation (which means that there is probably no need to store the current value of N-sharks as a separate global variable).
Why are you basing the repartition of your sub-breeds on the value of species? What do you want species to represent? Is it correct for it to be a separate variable from N-sharks? If yes, then it is not clear what is its point; if no, then it can be eliminated.
You need to make sure that whatever you wanted to do with N-sharks & species, and with N-fishes and species-f, is better reflected in your code.
Also because I think this is the reason why your first fish sub-breed isn't showing. First of all, what is species-ratio? It is not present in your example, but it seems to be relevant for your question. In any case, if your first fish sub-breed isn't showing, it means that there is no fish who satisfies the condition who <= species-f.
This doesn't surprise me. who numbers are progressive for turtles: if you create 15 sharks and later you create 10 fish...
... the oldest shark will have who = 0
... the youngest shark will have who = 14
... the oldest fish will have who = 15
... the youngest fish will have who = 24
As you can see in this example, there is no fish for which who <= N-fishes (where N-fishes = 10). Let alone that in your case you set species-f (N-fishes * species-ratio) and, although you didn't tell what species-ratio is, I imagine it is a value between 0 and 1 - thus making the value of species-f even smaller.
The problem is that you are using who to determine your fishes. To quote the Netlogo programming guide: "Who numbers are assigned irrespective of breeds. If you already have a frog 0, then the first mouse will be mouse 1, not mouse 0, since the who number 0 is already taken."
As such, you need to take the number of sharks into account for determining the cutoff point for your fish species
set species-f (N-fishes * species-ratio) + N-sharks - 1
One other comment I have on your code is that you use the following structure:
create-sharks N-shark [
ask sharks [...]
]
Every shark executes the entire command block of create-sharks. That means that every shark asks every shark to do something. Thus follows that every shark sets their shape to default N-shark times.
It is much more efficient to use one of the following constructions
create-sharks N-shark [...]
ask sharks [...]
or
create-sharks N-shark [
if <condition> [<reshape-self>]
]

Error: this isn't something you can use set on netlogo

I am trying to write a piece of code which asks some of the turtles to
calculate 2 parameters, compare them and then if one is lower than the
other, subtracts a characteristic of turtles by 1.
here is the code I wrote but I receive this error: "this isn't something you
can use set on netlogo"
set monthly-electricity-consumption random-float((monthly-electricity-demand * 1.2) - (monthly-electricity-demand * 0.8)) + (monthly-electricity-demand *
0.8)
ask turtles with [shape = "triangle"] [
if monthly-electricity-consumption > monthly-electricity-demand [
set [company-loyalty-level] of self company-loyalty-level - 1]]
Do you have any advice?
I'm assuming that the line
set [company-loyalty-level] of self company-loyalty-level - 1]]
is the line that generates the error. NetLogo does not allow one turtle to directly set the variables of another turtle by using the of construction. E.g.,
ask turtle 1 [set [company-loyalty-level] of turtle 2 (company-loyalty-level - 1)]
breaks that rule. In your case, by using self, turtle 2 and turtle 1 are the same turtle, but NetLogo will still throw that error. The line that you want is simply,
set company-loyalty-level company-loyalty-level - 1]]
Once you are within an ask, the variable is understood to be the one associated with the turtle being asked. The of self is not necessary.

Netlogo: Making a turtle interact with anotherone after evaluating similarity in a given variable

I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).

Netlogo error when using procedure from code example Many Regions Example procedure

I'm new in Netlogo . I'm trying to use the code included in the Many Regions Example of the library. But I get one error in this procedure
to keep-in-region [ which-region ]
if region != which-region [
let region-min-pxcor first item (which-region - 1) region-boundaries
let region-max-pxcor last item (which-region - 1) region-boundaries
let region-width (region-max-pxcor - region-min-pxcor) + 1
ifelse xcor < region-min-pxcor [
set xcor xcor + region-width ]
[if xcor > region-max-pxcor [
set xcor xcor - region-width
]
]
]
The error I get is .... any advices? Thanks in advance
-1 no esta mas que o iqual a cero.
error while a-seller 31 running ITEM
called by procedure KEEP-IN-REGION
called by procedure ADJUST
called by procedure GO
called by Botón 'go'
The error you are getting ("-1 isn't greater than or equal to zero.", once translated to English) is caused by passing -1 as an index for the item primitive.
There are two lines in the code that make use of item:
let region-min-pxcor first item (which-region - 1) region-boundaries
let region-max-pxcor last item (which-region - 1) region-boundaries
As you can see (which-region - 1) is the expression passed to item as index. If you are getting -1, it must be because which-region = 0.
In the "Many Regions Example" model, region 0 is reserved for the patches that are not part of any regions, namely, the patches that act as region boundaries. The regions themselves are numbered from 1.
Look in your code for the place where keep-in-region is called and make sure that you are using a region number that is between 1 and the number of regions you have (inclusively).
Disclaimer: I originally wrote the "Many Regions" code example. Maybe I could have used a value like nobody for the patches outside of any region and number the actual regions starting from 0 instead of one, but I don't remember if I actively decided against it or just didn't think of it.

netlogo: send message to all but one agent

I'm new at NetLogo. I'm not new at agent-based modeling. Now and then I see people saying NetLogo is so fun and easy that I'm giving it a try.
I'm stuck at square 1, can't figure out code for messaging between agents, scheduling actions for subsets of agents, other basic ABM things.
I'm working on a majority rule election model in which the turtles are voters with randomly placed x,y coordinates. Candidates (a new breed) make promises in x,y plane, the winning candidate is the one preferred by (closer to) more agents.
The patches play no role at all, except the spatial graph seems to require use of a grid
I'm having trouble in the updating of candidate positions. I conceived this as follows: Remove a 'winner' agent from the candidate agentset, tell the other candidates to adjust, then put the winner back in the agent list and see who wins in the next time.
I believe the following is close to minimum reproducible example. Please look at adjustOfferings. (Sorry, I left in a lot of show statements, otherwise can't tell what's going on.)
; Paul Johnson
; 20160801
breed [candidates candidate]
globals[
N
D
]
; turtles are voters, Euclidean-based preferences. Use
; built-in 2d coordinates for ideal points for now,
; need to learn how to create weighted multi-dimensional
; preferences later
turtles-own
[
name
]
to setup
ca ; clear all
reset-ticks ; time start 0
set N 100
; N voters with random x,y ideal points
create-turtles N
[
setxy random-xcor random-ycor
]
set D 2
create-candidates D
[
setxy random-xcor random-ycor
set shape "square"
set size 2
]
end
; collect up the votes. Don't worry about invading agent
; privacy, just measure for them
to-report election2 [choices]
let fave [min-one-of choices [distance myself]] of turtles
report fave
end
; Ask all non winners to adjust their offering
to adjustOfferings [winner]
show (word "in adjustOfferings, winner was: " winner)
let losers candidates with [self != winner]
show (word "adjustOfferings losers are: " losers)
ask losers
[
setxy random-xcor random-ycor
]
end
; ask each voter for its favorite,
; use modes to calculate the winner
to electionCycle
let theVotes election2 candidates
show (word "electionCycle: " theVotes)
let winner modes theVotes
show (word "electionCycle Winner: " winner)
adjustOfferings winner
end
to go
tick
if ticks > 1000
[
stop
]
electionCycle
end
The setup works fine, I see agents and candidates. When I hit the "Step button", I can see the election works, a winner is selected, but all candidates adjust (not just losers). Here's the console:
observer: "electionCycle: [(candidate 100) (candidate 101)
(candidate 101) (candidate 101) (candidate 100) (candidate 101)
[snip]
(candidate 100) (candidate 101)]"
observer: "electionCycle Winner: [(candidate 100)]"
observer: "in adjustOfferings, winner was: [(candidate 100)]"
observer: "adjustOfferings losers are: (agentset, 2 turtles)"
Appears to me this is the source of error:
let losers candidates with [self != winner]
The winner is still in losers after that.
I realize now you can't actually run this without the rest of the NetLogo file. What is your custom here for providing the fully runable example? Can I point you at a file on a website? http://pj.freefaculty.org/scraps/majority.nlogo. I could put this in GitHub or someplace else if you prefer.
I appreciate your advice.
The problem is indeed with the line you suggested. Both agents report true for the condition [self != winner], but why is it the case. Look at how you create and pass the winner variable to the function. You create it by using the modes primitive, which is a good idea. But modes will report you a list with one element. The problem is that you pass this list directly to your adjustofferings function. This means, the agents than compare [self != [(candidatexy)]]instead of [self != (candidatexy)] (mind the additional brackets in the first example, indicating the list).
To solve the problem, you have to extract the winner agent from the list by using the first primitive, which reports you the first item of a list. You only have to add this to the line, where you define the winnervariable: let winner first modes theVotes