I have a complete directed graph with each link a weight of it's own. I've managed to select the max-out-link of every turtle. But, sometimes the max-out-link of two turtles are opposite of each other resulting in both links opposite of one another being selected. if this happens i want the link with the lower value to die.
i have created the two lists with this:
set max-end1 [[end1] of max-one-of my-out-links [trust]] of turtles
set max-end2 [[end2] of max-one-of my-out-links [trust]] of turtles
and by setting an x and y parameter like so:
ask turtles
[
set x max-one-of my-out-links [label]
set y my-in-links
]
i was hoping to compare each item of the two lists like so:
if [x] of max-end2 = any? [y] of max-end1
[
ifelse x X y
[ask x [die]]
[ask y [die]]
]
but i have no idea how to combine the foreach command with the if command
can someone help me?
I can't actually figure out how your code is supposed to work. Lists seems like an awkward way to approach this and the way you are using any? is not going to work. So, I have instead started again and written a standalone model (put it in an empty NetLogo session) to do what I think you are trying to do.
links-own [ weight ]
to testme
clear-all
create-turtles 15
ask turtles
[ create-links-to other turtles
[ set weight random 100
]
]
layout-circle turtles 10
kill-lowers
end
to kill-lowers
; first remove any that's not a max weight
ask turtles
[ let big-link max-one-of my-out-links [weight]
let dying my-out-links with [not member? self (link-set big-link)]
ask dying [die]
]
; find pairs and make lower turn red
ask links
[ let opp-links links with [end1 = [end2] of myself and end2 = [end1] of myself ]
if any? opp-links
[ ask opp-links [set color red]
]
]
end
The testme procedure just creates a complete network. It then calls the kill-lowers procedure to do the link removal. The first section has each turtle identify its out-link with the largest weight (or randomly selects one if two equally high) and then creates the link-set of all the other links and gets them to die. I think you already have that happening in your code.
So the interesting bit is the section that starts ask links. It randomly runs through all the links (think of it as a foreach except operating on a set of links rather than a list). In turn, for the particular link, the code checks if there is a link in the opposite direction and sets that to the variable named opp-links. The way it checks is to simply see if there is a link that has end2 to be its own end1 and also the other way. end1 is the source of a directed link and end2 is the target.
If there is such a link, it becomes red. That's so you can check the code is doing what you want. After you have tested it, then you have it die instead.
Related
I have a model where there are multiple animals in a den
patches-own [den-ID]
where the dens are pink and the number of dens is controlled with a slider global var
ask patches with [pcolor = pink] [set den-ID random n-dens]
Now, I want agents that spawn on that patch to set their own parameter "family" to a value equal to the den-ID that they spawn on - therefore having a group of animals that can be traced back to a den site and all share a home range.
I have tried many solutions but cant get anything to work.
basically something like
set family (family = den-id of patch-here)
thanks
The answer: ask turtles [ set family patch-here ]
Down below is how we arrived there
You seem a bit confused in your Netlogo syntax.
= is only used for logical expressions in Netlogo, not for setting variables. For that you use set.
If you want to use of to access variables of another agent, you need to encase the variable in square brackets: [den-id] of patch-here.
The solution you are looking for looks something like the following:
ask turtles [ set family [den-id] of patch-here ]
It can be made even easier. A turtle can directly access the variables of a patch that they are on without needing to name that patch.
ask turtles [ set family den-id ]
I noticed another thing in your code. Nothing in set den-ID random n-dens prevents multiple dens of having the same number. There are numerous ways of doing it, for example with a while loop where you increment the current-ID each time.
set current-ID 1
while [any? patches with [pcolor = pink and den-ID = 0]] [
ask one-of patches with [pcolor = pink and den-ID = 0] [set den-ID current-ID]
set current-ID current-ID + 1
]
You could even opt to forget about den-id and just let the turtles remember their den itself:
ask turtles [ set family patch-here ]
I am trying to get my turtles to look around themselves in netlogo and select a patch with the lowest slope variable in radius 2 - and if there isn't one to just select any patch.
I check my code, and it says everything is fine, but when I run it I keep getting this error: this code can't be run by a patch - error while patch X X running ifelse - called by procedure move - called by procedure go - called by button "go"
This is my move code:
to move
ask turtles [ask patches in-radius 2
[ifelse slope < 5
[fd 1]
[move-to one-of patches in-radius 2]
]
]
end
I have already tried downhill and downhill4 but my agents seemed to get stuck at the bottom of the slope and couldn't move anywhere.
Thank you for any help and advice!
Thank you - my code now works!
Because you are asking turtles to ask patches, the code inside the ask patches is run by the patch! A patch can’t use turtle variables, and doesn’t know that you mean to refer to the variables of the turtle that asked the patch.
This is what “of myself” is for. It lets an agent (self) talk to the agent that is telling it what to do. You’ll see stuff like “set heading [heading] of myself” But that’s not what you need here.
we could use an ask patches like you are doing here, but we really don’t want them to do anything, and it’s going to make the code much more complex looking. Anyway, We just want to find a patch that meets the turtle’s needs and move to it.
So instead. We can query the nearby patches using a WITH and store the set of patches found in a “patch set” variable.
If there are any, we can move to one of them.
Else, we can just move forward.
So
To move
Ask turtles
[
;; here the turtle tells patches to test the patch’s own slope
Let good-spots patches in-radius 2 with [ slope < 5 ]
;; are there some patches that pass the test?
If-else any? Good-spots
[ ;; Yes, pick one and go there
move-to one-of good-spots
]
[ ;; No, just move forward
Fd 1
]
]
End
Edit to add : Matteo’s answer correctly identifies the actual requirement, based on the question: move directly to the flattest patch, versus what the code above does, move to one of the flatter patches, if there is one.
Move-to min-one-of patches in-radius 2 [ slope ]
As you noted, This is similar but not identical to
Downhill slope
And neither of these may prevent turtles from getting stuck in a pit. You may need more code to detect pits and jump out of them.
The problem is not about variables but about commands: you are asking patches to run forward or to run move-to, while these are turtles' commands.
Now, for the purpose of the question, there is another issue: you said that you want
turtles to look around themselves in netlogo and select a patch with the lowest slope variable in radius 2 - and if there isn't one to just select any patch
However, even if we ignore the problem about asking patches to run forward or move-to, the structure of your code implies something very different. Your code seems to intend:
Turtles, check if there are any nearby patches with slope lower than a specific threshold;
If there are, move forward in whatever direction you are already facing;
If there are not, move to a random nearby patch.
The solution below is based on the assumption that what you want is what you said, and not what your code seems to imply.
The solution is very simple and only needs min-one-of (check it here):
to move
ask turtles [
move-to min-one-of patches in-radius 2 [slope]
]
end
As a demonstration, consider this full example:
patches-own [
slope
]
to setup
clear-all
ask patches [
set slope random 10 + 5
set pcolor scale-color green slope 5 14
]
create-turtles 10 [
setxy random-xcor random-ycor
set color yellow
]
end
to go
ask turtles [
move-to min-one-of patches in-radius 2 [slope]
]
end
You will see that turtles tend to go to darker patches, that are those with lower slope.
I have N groups of turtles which own the variable group-id (1 to N, N is defined at setup, each group has 25 turtles).
At the beginning each group of turtles spawns on a random patch with variable patch-group-id that matches the turtle group-id, like so:
let i 0
while [ i < n_groups ] [
let x random 100
let y random 100
ask patch x y [ set patch-group-id i set pcolor gray ]
create-turtles 25 [
set group-id i
setxy x y
]
set i i + 1
]
The turtles move around but at a later step in the process I would like them to move back to their ‘home’ patch. Other turtles may also change their group-id and therefore their home patch and I would like them to move there too.
Is there any way to do a comparison along the lines of…
Ask turtles [
Let target one-of patches with [patch-group-id = group-id]
]
And then ask the turtle to move-to or jump to the target?
NetLogo doesn’t like this (‘Min-one-of expected this input to be a number block, but got a true/false block instead’) and I think there are probably other issues too.
patch-group-id is a variable owned by patches and group-id is owned by turtles. So you need to tell NetLogo which group-id the patches are trying to match to. Try this:
ask turtles
[ let target one-of patches with [patch-group-id = [group-id] of myself]
]
Another way to do this is to drop the idea of group-id and simply have each turtle remember its home patch. Conceptually, this implements the idea that a group is entirely defined by its home patch. So your setup would look something like:
turtles-own
[ my-home
]
to setup
clear-all
ask n-of n-groups patches
[ sprout turtles 25
[ set my-home patch-here
]
set pcolor gray
]
end
Then you never need to construct the target, you simply get then to go to their variable my-home.
If you went down this path, you would also need to change the code that uses group-id. For example, you said that sometimes the turtles change their group-id, instead of set group-id [group-id] of ... you would have set my-home [my-home] of ...
I'm working on a land-use model featuring a forested World where turtles (smallholders and companies) have the ability to convert forest into crop-land. I would like to introduce a feature that turtles 'own' the patches they convert and are able to revisit them later to get these patches certified. The main issue is that when turtles move-to crop-land patches to get them certified, they do not only move to those they 'own' but also jump across the world to other turtles' crop-land patches and certify those. I've tried a few different workarounds, but I seem to run into the same two issues eventually:
#1 - error: can't use who in a patch context
I wanted to use the 'who' variable to mark crop-land patches as belonging to the turtle that converted the patch, e.g., turtle 0 goes to the forest, converts it to crop-land and that patch of cropland should be 'owned' by turtle 0, i.e., the patches owned-by variable should be equivalent to the turtle's 'who'. The issue here is that 'who' is a turtles-own variable. So, when I use it in a patch-context it produces an error. For example, ask smallholders [move-to one-of patches with [[owner = who]] --> error.
#2 - can't manage to set a global variable = 'who'
Two, I tried to work around this by using a proxy variable: a globals-variable called 'owner-ID'. I would use set owner-ID who to imprint the turtles individual number to the owner-ID. This seems to work to some extent, namely that the patches' 'owner' variable corresponds to the turtle that converted the patch. It also works when counting how many patches of certified and conventional crop-land turtles own (see set-land-ownership command below). However, when the smallholders-certify-crop-land commands are triggered, turtles don't stick to the patches they own, but 'jump' across the world. When prompting turtles through the command-center ask turtles [print owner-ID] they all return the same owner-ID value. I feel there might be a mistake in my move-to command-line but I just can't find it.
Summary & Question
I want crop-land patches to be 'owned by' the turtles that converted them, and want turtles to move only to the patches they 'own' when certifying crop-land patches, not to patches they don't own. I guess my questions revolve around whether it's possible to somehow use the 'who' variable in a patch-context. And, if not, what a good workaround for the problem could look like.
Relevant code is below (I hope)!
globals [owner-ID]
turtles-own [conventional-land-ownership certified-land-ownership]
patches-own [owned-by owner certified?]
to setup [
ask patches [
set pcolor green ;; green = forest
set certified? "no"
set owner "nobody"
]
]
to go
ask turtles [set-land-ownership]
ask smallholders [check-smallholder-status]
tick
end
to set-land-ownership
ask smallholders [
set owner-ID who
set conventional-land-ownership count patches with [owner = owner-ID and certified? = "no"]
set certified-land-ownership count patches with [owner = owner-ID and certified? = "yes"]
]
end
to check-smallholder-status
if wealth >= 0 and (conventional-land-ownership + certified-land-ownership) < SH_max-land-ownership [
smallholders-choose-activity
]
if wealth < 0 [
set color red
set shape "cow skull"
]
if (conventional-land-ownership + certified-land-ownership) >= SH_max-land-ownership [
set color orange + 2
]
end
;; smallholders-choose-activities is a reporter-based command where turtles choose the most economical option available. One of the outcomes is: smallholders-certify-crop-land
to smallholders-certify-crop-land
let available-patch max-one-of patches with [owner = owner-ID and certified? = "no"] [count neighbors with [certified? = "yes"]]
ifelse not any? turtles-on available-patch [
move-to available-patch
]
[]
set wealth wealth - smallholder-certification-cost
set pcolor brown + 1
set certified? "yes"
end
Your first approach is definitely the way to go and could be fixed with one small adjustment.
ask smallholders [move-to one-of patches with [owner = who]]
should be
ask smallholders [move-to one-of patches with [owner = [who] of myself]]
Within the block after with, variables are in the context of patches, but myself refers to the agent that asked the patches to check their owner, in this case, each smallholder. The global variable owner-ID is then unnecessary. If you carry this through the rest of the code, your second problem may solve itself.
BUT, in general it is best not to use who numbers at all, but rather refer to the agent directly. (You have actually taken that approach implicitly when you initialize owner to nobody, which is "no agent".) I don't see where you ask a patch to set its owner, but if a smallholder is on a patch, the smallholder would
ask patch-here [set owner myself]
and the line above would now read
ask smallholders [move-to one-of patches with [owner = myself]]
The NetLogo gurus suggest that we use who numbers only when there is no other approach.
I have n turtles which all have links with one another. That means I posses a complete directed weighted graph. I've managed to locate the links with maximum value per each turtle, but now I want to delete all other links without maximum value, again per each turtle.
I'm using the [die] function but in order to distinguish the set of links per each turtle and then clear links from each set
This is the line of code I'm using:
> ask turtles
[
> ask my-in-links with [trust < max [trust] of links with [other-end] = ] [die]
]
However, I thought instead of using other-end function I could also use this line of code
> ask turtles [
ask my-in-links with [trust < max [trust] of links with [out-link-to] = ] [die]
]
My initial thought was by using one of the two functions (other-end/ out-link-to), I could create a common attribute between the set of links.
My main problem is
I'm not sure whether the functions (other-end/ out-link-to) are correct
I don't know what to write after the "=" expression
I don't know which turtle the ask turtle function begins to work with
Here's a complete model that does what you are trying to achieve.
links-own [trust]
to testme
clear-all
; create complete directed network
create-turtles 10
ask turtles
[ create-links-to other turtles
[ set trust random 50
]
]
; display complete network briefly
layout-circle turtles 10
type "average trust value is: " print mean [trust] of links
wait 5
; delete all except highest trust for each turtle
ask turtles
[ let keeper my-in-links with-max [trust]
ask my-in-links with [not member? self keeper][die]
]
type "average trust value is: " print mean [trust] of links
end
I have it showing the initial network and printing average trust values so you can see what's going on.
The important concept here is that my-links is an agentset (in particular, it's a linkset because the agents in the set are links). Since what you're trying to do is just look through the links that are connected to one turtle, then it doesn't matter which turtles are at the other end and you don't need to refer to the other end at all.
You can simply look at the set of links that attach to the particular turtle (my-in-links or my-links or my-out-links) and then look at the values of trust for those links. I have used with-max to find the one with the highest value and then used set membership. But you could also use
ask turtles
[ let upper max [trust] of my-in-links
ask my-in-links with [trust < upper] [die]
]
which is closest to the code you wrote in your question.