comparing attributes of 2 different turtles breed - netlogo

I have 2 turtles bread:
globals [ max-applicant ]
breed [ applicants applicant ]
breed [ investors investor ]
applicants-own [ ask-amount applied? industry country-of-origin funded? ]
investors-own [ allowed-industries-list allowed-countries-list no-of-applicants-funded ]
I want to perform a transaction based on whether the investor is allowed to do business with the applicant's industry and country of origin. An Investors can only perform a limited number of transactions based on the max-applicant value
In the code below, I'm trying to select an investor that hasn't reached the max transaction limit and then select an applicant that meets the conditions of the selected investor and fund that applicant:
to close-deal
let investorPerson one-of investors-here with [no-of-applicants-funded < max-applicant]
if investorPerson != nobody [
ask investorPerson [
let applicantPerson one-of applicants-here with [
industry member? [allowed-industries] and country-of-origin member? [allowed-countries] of myself
]
if applicantPerson != nobody [
ask applicantPerson [
set funded? TRUE
]
]
set no-of-applicants-funded no-of-applicants-funded + 1
]
]
end
This code doesn't run. is this the right way to design this operation?

There seem to be two problems:
See here the syntax of member?: it is member? value list, while in your code you have value member? list.
In the first of the two boolean statements where you use member?, you omitted the of myself that should address [allowed-industries].
Combining the two points above, you should have:
let applicantPerson one-of applicants-here with [
(member? industry [allowed-industries] of myself) AND (member? country-of-origin [allowed-countries] of myself)
]
The use of parentheses and the capitalisation of boolean operators are optional, just my own stylistic choice.
Side note: be aware that you are asking your investorPerson to
set no-of-applicants-funded no-of-applicants-funded + 1
outside of the command block that gets executed if there actually is an applicantPerson; i.e. your investors will increment no-of-applicants-funded even when applicantPerson = NOBODY.

Related

Linking turtles to another turtle with highest value in NetLogo. Limit the number of links

I am a beginner with NetLogo and I am trying to ask some turtles (students from different social classes) to link to other turtles (schools). What I would like is for the working class students to look for the school with the highest achievement which is at the same not expensive and has not reached the max number of links allowed. If the desired school has reached the max number of links allowed I want the student to look for the next school with the highest achievement which has not reached the max number of links allowed and so on.
This is the code. I get the following message "ANY? expected input to be an agentset but got the turtle (school 1) instead."
breed [schools school]
breed [upperclass upperclass-student]
breed [workingclass workingclass-student]
upperclass-own [achievement enrolled? target]
workingclass-own [achievement enrolled? target]
schools-own [schoolachievement expensive? ]
to setup
clear-all
set-default-shape schools "house"
set-default-shape upperclass "person"
set-default-shape workingclass "person"
ask patches [ set pcolor 8 ]
create-schools num-of-schools [ setxy random-xcor random-ycor set schoolachievement random-normal 5 1
set expensive? one-of [ true false ] ]
create-upperclass num-of-upperclass [ set color white setxy random-xcor random-ycor set achievement
random-normal 5 1 ] ;Students from upper class have higher achievement
create-workingclass num-of-workingclass [ set color red setxy random-xcor random-ycor set achievement
random-normal 4 1 ]
end
to go
ask workingclass [
choose-school ]
end
to choose-school
if breed = workingclass [
set target one-of schools with-max [ schoolachievement ] with [ expensive? = false ] ]
if any? target with [ count link-neighbors < max-link-count ] [
create-link-with target ]
set enrolled? TRUE
end
Your problem is the difference between an agent and an agentset, which is a somewhat subtle problem. The with-max returns an agentset - a set of agents (in this case turtles). That agentset can have 0 members, 1 member, 2+ members but is a set even if it is empty. However, the one-of selects one agent from the agentset and returns it as an agent, not an agentset. That is, NetLogo knows anything that is returned by one-of must be exactly one agent. At this point, primitives that are for agentsets (like any?) will throw an error unless they can also be used on individual agents.
So, back to your code. I like the readability of checking whether there are viable schools and then selecting one, which is what I think you meant to do. That would be:
to choose-school
if breed = workingclass
[ set targets schools with-max [ schoolachievement ] with [ expensive? = false ]
set candidates targets with [ count link-neighbors < max-link-count ]
if any? candidates
[ create-link-with one-of candidates
set enrolled? TRUE
]
]
end
Note that I also changed to targets instead of target, which is one way to keep track of whether something is an agent or an agentset.
The other way you could do this and keep it as an agent is:
to choose-school
if breed = workingclass [
set target one-of schools with-max [ schoolachievement ] with [ expensive? = false ] ]
if target != nobody and [count link-neighbors] of target < max-link-count [
create-link-with target ]
set enrolled? TRUE
end
So you can use nobody instead of any? but you can't also use with in that line because the with is really a filter on a set.
I also think you have a bracketing issue - I assume you want set enrolled? TRUE inside the brackets. I left it in the second fix, but changed in the first error (as well as changing bracket position convention to make the code block structure more visible)

Create links according to turtle's attributes

I have two turtle breeds (products and consumers) each with a 3-dimension list that defines their needs (consumers) and their attributes (products).
What I'd like is to have each consumer (i) look for a product that satisfies all their needs and create a link with them. If that product does not exist, I'd like them to (ii) drop the one need with the lowest value and look for a product that satisfies the other two. If that product does not exist, then I want them to (iii) look for another one that only satisfies the need with the highest value.
So say that consumer 20 has needs [0.2 0.5 0.3]. If they find a product whith exactly the same list of attributes [0.2 0.5 0.3] I want the link to take place. If there's no such product then I want the consumer to ignore the lowest value (0.2 in the example) and look for a product that has attributes [xx 0.5 0.3], where xx stands for "whatever".
Using examples from elsewhere here in SO, I have cobbled up the following code that (almost!) does the first part of the trick (i), but can't manage to do (ii) and (iii) despite multiple efforts. Would anyone have an indea on how to do this?
breed [consumers consumer]
breed [products product]
consumers-own [
needs
]
products-own [
attributes
number-buyers
]
to setup
ca
create-consumers 100 [ setxy random-xcor random-ycor]
create-products 100 [ setxy random-xcor random-ycor]
set-default-shape consumers "person"
set-default-shape products "box"
ask consumers [
set needs n-values 3 [ precision (random-float 1) 1 ]
]
ask products [
set attributes n-values 3 [ precision (random-float 1) 1 ]
]
reset-ticks
end
to go
buy
tick
end
to buy
ask links [ die ]
ask consumers [
carefully [ create-link-with one-of products with [reduce and (map = attributes [ needs ] of myself)] ] [ show "how do I find a sub-optimal product by ignoring my need with the lowest value ?" ]
]
ask products [
set number-buyers count link-neighbors
]
end
You are overthinking the full match - just check if the two lists are the same. However, the almost match is a bit more complicated. Here is a complete example model that finds the position in the list of the lowest and then checks that the other items are the same.
breed [consumers consumer]
breed [products product]
consumers-own [
needs
]
products-own [
attributes
number-buyers
]
to setup
clear-all
ask patches [set pcolor white]
create-consumers 10
[ setxy random-xcor random-ycor
set shape "person"
set color blue
set needs n-values 3 [ one-of [1 2 3] ]
]
create-products 10
[ setxy random-xcor random-ycor
set shape "box"
set color red
set attributes n-values 3 [ one-of [1 2 3] ]
]
reset-ticks
end
to go
ask consumers [buy]
tick
end
to buy ; set up as turtle procedure for testing purposes
ask my-links [ die ]
let candidates products with [attributes = [needs] of myself]
ifelse any? candidates
[ create-link-with one-of candidates ]
[ type self type " attributes: " type needs print " no matches"
let lowpoint position (min needs) needs ; note will take first if two equal min
set candidates products with
[ ((item 0 attributes = item 0 [needs] of myself) or lowpoint = 0) and
((item 1 attributes = item 1 [needs] of myself) or lowpoint = 1) and
((item 2 attributes = item 2 [needs] of myself) or lowpoint = 2)
]
ifelse any? candidates
[ create-link-with one-of candidates ]
[ print "no almost-match available" ]
]
end
I created the agentset (called candidates) of potential products to link to and then created the link. This makes the code much more readable. It also allows the if any? construction if no matches were found. And it also makes it easier to debug because you can put print statements reporting numbers of matches and similar. I recommend that you always do this if you are applying some sort of condition that restricts the choices.
Also, you have a three item list with 10 possible values for each item. This means there will be 1000 combinations. You only have 100 consumers and 100 products, so matching will be fairly rare.

Netlogo: Is there an `all-of` command, simmilar to the `one-of`?

Is there an equivalent of the command one-of that does all agents? So an all-of command? I need my agents to ask specific other agents to sum and report back a value. The one-of command will only randomly select one other agent but I need to select all agents on a list.
Details: I need my household agents to to ask other householdagents to sum and report back their HHwaterUse value. Each household agent will ask all other agents on their SocialNetwork list. The SocialNetwork list is composed of a Public_ID values, which is a value that each agent possesses.
Ex: So if household-1 posses a SocialNetwork list that looks like [9126 3495 4197 8771], I need all agents with a Public_ID value of 9126, 3495, etc to report back their HHwaterUse value.
ask households [
set NetUseSum sum [HHwaterUse] of households with [[Public_ID] of myself = all-of [SocialNetwork] of self]
]
The member? primitive should work, check out the dictionary entry for details. Here is an example where just a single household checks the sum of its social network's water use:
breed [ households household ]
households-own [ Public_ID Social_Network HH_Water_Use]
to setup
ca
create-households 10 [
setxy random-xcor random-ycor
set Public_ID 1000 + random 1000
set HH_Water_Use 100 + random 50
]
ask households [
set Social_Network sort [Public_ID] of n-of 4 other households
]
reset-ticks
end
to sum-social-network
ask one-of households [
show ( word "My social network comprises: " Social_Network )
ask households with [ member? Public_ID [Social_Network] of myself ] [
print ( word Public_ID " has a water use of " HH_Water_Use )
]
let social_sum sum [HH_Water_Use] of households with [ member? Public_ID [Social_Network] of myself ]
print ( word "My social network has a sum water use of " social_sum )
]
end
Edit:
Just a note that I agree with Nicolas and Jen above- this is definitely not the best approach. Use their link or agentset suggestions instead if possible.
That worked, Luke C's suggestion of using the member? snippet did the trick. I was able to sum, all at once, the value from the list of agents.
let social_sum sum [HH_Water_Use] of households with [ member? Public_ID [Social_Network] of myself ]

Netlogo - identifying a subset of an agentset

I spent all afternoon trying to work out with a part of my code and I don't seem to be getting anywhere. Basically, I'm trying to create a social network on model setup. Each person in the model starts off with a set of people that are nearby to them people-nearby. It is from this set that people choose who to connect with:
create-people population-size
[
set people-nearby turtle-set other people in-radius neighborhood-radius
]
to create-network
let num-links round (average-node-degree * population-size) / 2
while [ count links < num-links and count people with [length sort people-nearby > 0] > 0 ]
[ ask one-of people
[ *... initiate probabilistic link creation process...*
create-unlink-with chosen-friend
Once person A has connected to someone (ie. person B), person B is removed from person A's people-nearby set. I'm having trouble with this portion of the code where the people-nearby set is updated by excluding all nearby people that are members of the unlink-neighbors set (i.e., those to whom person A is already connected - this set including person B):
ifelse count turtle-set people-nearby > 1
[ let nearby-people-not-linked-to-me ( turtle-set people-nearby with [ not member? self [ turtle-set unlink-neighbors ] of myself ] )
set people-nearby nearby-people-not-linked-to-me ]
[ set people-nearby [ ] ]
For some reason this error keeps popping up:
"WITH expected input to be an agentset but got the list [(person 0) (person 1) (person 3) (person 4)] instead." whenever
people-nearby with [ not member? self [ turtle-set unlink-neighbors ] of myself is called.
I looked up so many posts but can't seem to get the form of the argument right so that it stops showing this error.
Can anyone help me fix this please? (Oh and it's my first post so apologies if I haven't set up the issue properly)
When you submit code, try to submit what is needed to recreate your problem- check out the asking help page, and specifically the section on helping others reproduce your problem. As is, I think your problem comes from using turtle-set. That primitive is mostly used to combine agentsets, not to query them. So in your line:
( turtle-set people-nearby with [ not member? self [ turtle-set unlink-neighbors ] of myself ] )
there is an syntax issue related to turtle-set. The error itself is saying that you have not returned an agentset but a list of agents, which behave differently.
If I understand correctly, you want all people to have a variable that contains all people within a radius of themselves: "people-nearby". Then, you want the people to form a link with one of their "neighbor" turtles. Finally, you want the people to update their "people-nearby" variable to exclude the person to whom they just formed a link. Below is some code with comments where I tried to follow those steps- obviously your variables will be different, but it may get you started. Let me know if I need to clarify anything or if I missed a step.
breed [ people person ]
turtles-own [ people-nearby ]
to setup
ca
reset-ticks
create-people 70 [
setxy (random 30 - 15) (random 30 - 15)
]
; do this after all turtles have spawned
ask people [
set people-nearby other people in-radius 3
]
end
to create-links
let num-links 10
;; Create a temporary agentset out of turtles that have people nearby
let turtles-with-neighbors turtles with [ any? people-nearby ]
; ask some number of the temporary agentset:
ask n-of num-links turtles-with-neighbors [
;; This just makes it easy to identify the turtle that causes the link
ask patches in-radius 3 [
set pcolor white
]
; create a link to one of the nearby people
create-link-to one-of people-nearby
; newly set people-nearby to only include turtles in radius
; that are not linked-to from the currently acting turtle
set people-nearby other people in-radius 3 with [ not member? self [ out-link-neighbors ] of myself ]
ask people-nearby [ set size 0.5 ]
]
end

How to create pairs in netlogo

I am trying to make connection between agents. I have created 3 breeds of agents: firms, officers and citizens ( each breed has 10 agents), and I need to create pairs. Each pair involves: one firm, one citizen and one officer ( agents are chosen randomly). I also need that all agents will create pairs.
breed [ firms firm]
breed [ officers officer]
breed [ citizens citizen]
;; then I need to create pairs, and If one agent of the pair is firm then, firm can dicide to bribe or not, if not, firm earns 30, officer earns 0 and citizen earns 10:
to go
if ticks mod 3 = 0
[
ask turtles
[
if breed = firms
[
if bribe? = false
[
set budget budget + 30
output-print (word " firms " budget)
ask other turtles
[
if breed = officers [ set budget budget + 0
output-print (word " officers " budget)]
if breed = citizens [ set budget budget + 10
output-print (word " citizens" budget)]
]
stop
]
]
]
]
;; then go other ticks, where citizen and officer decide to accept bribery or punish for accpeting bribery....
You say “each pair involves: one firm, one citizen and one officer”. I'd call that a triplet, or just a combination rather than a pair; “pair” always means two, never three.
Here's some sample code that forms all possible triplets and then does something approximating your description:
ask officers [
let this-officer self
ask citizens [
let this-citizen self
ask firms [
if bribe? [
set budget budget + 30
ask this-citizen [
set budget budget + 10
]
]
]
]
]
I wasn't able to understand everything you said about what you're trying to do. But hopefully the above code is close and illustrates the principle of nesting ask in order to form all possible combinations.