netlogo: nested ifelse cannot access the last ifelse command - if-statement

I have three level of ifelse command. I attempt to make an agent to do something by comparing 2 variable of different agent. A brief description about the ifelse command.
Procedure 1 & 2 attempt to compare variable of two different agent on the same patch and do something; else
Procedure 3 attempt to compare variable of two agent on different patch in radius 2, then do something ; else.
Problem :
When I run procedure 1 and 3 (disable procedure 2) OR procedure 2 and 3 (disable procedure 1), code is fine. But when I tried to run the whole procedure, it can't access [do something] command on procedure 3.
My code looks like this;
to cocreate-value1
ask capabilities-here
[ let this-resource one-of resource
ask one-of prevalues-here
[ ifelse value = this-resource
[ use-resource ]
[ cocreate-value2]
] ]
end
to cocreate-value2
ask capabilities-here
[ let this-knowledge one-of knowledge
ask one-of prevalues-here
[ ifelse value = this-knowledge
[use-knowledge ]
[cocreate-value3]
] ]
end
to cocreate-value3
ask one-of other capabilities in-radius 2
[let resource2 sentence (resource) (knowledge)
let this-resource2 one-of resource2
let new-cap capabilities with [one-of resource = this-resource2]
ask prevalues-here
[ ifelse value = this-resource2
[ask capabilities-here
[if any? other new-cap in-radius 2
[ create-link-to one-of other new-cap in-radius 2
set color white]] ;; this code is not executed
use-network ] ;; this one too
[set color yellow ]
]]
end
Can anyone find the problem? Thank you for your help

Does this expose the problem?
to cocreate-value1
ask capabilities-here [
let _resource one-of resource
let _pv one-of prevalues-here
if (_pv != nobody) [
ask _pv [
ifelse (value = _resource) [
use-resource
] [
cocreate-value2
]
]
]
]
end
to cocreate-value2
print "enter cv3"
ask capabilities-here [
let _knowledge one-of knowledge
let _pv one-of prevalues-here
if (_pv != nobody) [
ask _pv [
ifelse (value = _knowledge) [use-knowledge ] [cocreate-value3]
]
]
]
print "exit cv3"
end
to cocreate-value3
print "enter cv3"
let _oc one-of other capabilities in-radius 2
ifelse (_oc = nobody) [
print "no other capabilities"
] [
ask _oc [
let _resource2 one-of (sentence resource knowledge)
let _resource one-of resource
let _new-cap capabilities with [_resource = _resource2]
if (not any? prevalues-here) [error "no prevalues here!"]
ask prevalues-here [
ifelse (value = _resource2) [
ask capabilities-here [
let _other one-of other _new-cap in-radius 2
if (_other != nobody) [
print "found a link partner!"
create-link-to _other
set color white
]
] ;; this code is not executed
use-network
] [;; this one too
set color yellow
]
]
]
]
print "leave cv3"
end

Related

Let agents follow its neighbour but got the error "FACE expected input to be an agent but got NOBODY instead."

I try to move each agents to its related agents (defined by high trust connection and in my view) if there are any such agents, and else move the agent to one of its neighbours. However, I get the error "FACE expected input to be an agent but got NOBODY instead." and I don't know how to solve it. I think the use != nobody might cause the error. Any suggestions on how to solve this?
This is my code:
breed [ persons a-person ]
undirected-link-breed [ connections connection ]
connections-own [ trust ]
persons-own [ neighbours ]
to setup
clear-all
create-persons 10
[ setxy random-xcor random-ycor ]
setup-connections
reset-ticks
end
to setup-connections
ask persons
[
create-connections-with other persons
[ set trust 0.6 ]
]
end
to go
setNeighbours
movePersons
tick
end
to setNeighbours
ask persons [ set neighbours other persons in-cone 4 360 ]
end
to movePersons
ask persons
[
let highlyRelatedPersons (turtle-set [other-end] of my-out-connections with [trust = 0.6]) in-cone 4 360
let relatedPersons (turtle-set [other-end] of my-out-connections with [trust = 0.6])
ifelse any? highlyRelatedPersons
[
face one-of highlyRelatedPersons
]
[
let weaklyRelatedNeighbour one-of neighbours with [not member? self highlyRelatedPersons] ;select one of my neighbours that is not a highlyRelatedPerson
ifelse weaklyRelatedNeighbour != nobody
[
face weaklyRelatedNeighbour
]
[
face one-of relatedPersons
]
]
]
end
You are correct in what is causing the error
highlyRelatedPersons is an agentset and while an agentset can be empty, an agentset can never be nobody. one-of highlyRelatedPersons however, will be nobody if the agentset is empty, so you could use ifelse (one-of highlyRelatedPersons != nobody).
That said, is easier to just check if the agentset is empty by using any?:
ifelse any? highlyRelatedPersons
Your code also never actually creates any links for highlyRelatedPersons and relatedPersons is always empty. This means that the code will always return false on the first ifelse and move on to the second. Generally most turtles will have neighbours they can face, but sometimes there are none so they try to face one-of relatedPersons, which again causes a crash since relatedPersons is an empty agentset.

Netlogo: How to transfer lists belonging to neighbours to a matrix?

A list called ownList2 consists of two parameters. Flockmates are all the neighbours in a given radius of the neighbour. I tried this code in version 6.0. But it doesn't work.
Basically, I want to put a list of equal dimension into a matrix. Is there something wrong I am doing? Or someone could improve the code piece?
ask turtles[set ownList2 (list who sensed)]
;sensed is sensor value of a turtle with respect to the patch.
;ownList2 is like a message of two bytes,
;first byte mentioning the identity of the itself
;second byte mentioning the value of the sensor.
ask turtles[
foreach (list flockmates)
[
i -> set m45 matrix:to-column-list ( list [ownList2] of i )
]
]
Result:
For turtle-0 with neighbours 1, 2, 3:
ownList2 ~ [1 200]
[2 400]
[3 900]
The m43 for turtle-0 should look like
[[1 200][2 400][3 900]]
Thanks for adding that information. Here is a toy example that might do what you need:
extensions [ matrix ]
turtles-own [ ownlist2 sensed m45 ]
to setup
ca
; Setup example turtles as per question
foreach [ 100 200 400 900 ] [
n ->
crt 1 [
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
set sensed n
set ownlist2 ( list who sensed )
]
]
; Get the turtles to create matrices from the ownlists of
; sorted other turtles
ask turtles [
set m45 matrix:from-column-list map [ i -> [ ownlist2] of i ] sort other turtles
]
; Example output:
ask turtle 0 [
print "Turtle 0's m45:"
print matrix:pretty-print-text m45
]
reset-ticks
end
Output example:
Turtle 0's m45:
[[ 1 2 3 ]
[ 200 400 900 ]]

NetLogo sort list of agents by a specific value

I have a model with 5000+ farmers and several factories. Sometimes a new factory is built, at which point I want the factory to do the following:
Create a list with all farmers and then sort that list according to distance of farmer to the factory (from low to high).
I have tried doing this with a table,
ask factory 1 [ask farmers [set distance-to-factory distance myself]]
ask factory 1 [set a table:group-agents farmers [distance-to-factory]]
but then the resulting agentsets are not ordered from low to high or vice versa. Moreover, I want the factory to be able afterwards to ask single agents from the ordered table (or list) to do something:
After ordering the farmers by their distance-to-factory, I want the factory to be able to ask farmers from that list to deliver their goods (i.e. the closest farmer is asked first, but when it has no goods, the second closest farmer is asked and so on).
Your help is much appreciated!
You need to create an agent variable for the factory that stores the list of farmers in distance order. Here is a full example, run it and inspect a factory to convince yourself that it works.
breed [factories factory]
breed [farmers farmer]
factories-own [my-farmers]
to setup
clear-all
create-farmers 100
[ setxy random-xcor random-ycor
set color yellow
set shape "circle"
set size 0.5
]
create-factories 3
[ setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
]
reset-ticks
end
to initialise-factory
set my-farmers sort-on [distance myself] farmers
end
Look at the initialise-factory procedure. The sort-on primitive operating on an agentset returns a list. And the [distance myself] of ... is calculating the distance back to the factory (because the factory is doing the asking and is therefore myself). So the list is sorted by distance to the factory.
Once you have created the list, you use list procedures (eg the item primitive) to do the asking specific farmers.
There are indeed multiple factories and the distance-to-factory is to the most recently created factory, but the my-farmers list that each factory has doesn't change.
I already used the profiler extension on a previous version of the model and that one was very slow because of every factory asking each farmer every time (once a year) if they had goods:
let closest-farmer (min-one-of farmers with [status = 0] [distance myself])
That is why I thought of every factory creating a list of farmers from closest to furthest, so that factories can run through that list. Below you find a more elaborate piece of code, I hope this helps you to get a better image.
breed [factories factory]
breed [farmers farmer]
globals [
count-down
total-capacity-factories
price-goods
]
farmers-own [
area
goods-per-area
goods
distance-to-factory
status
]
factories-own [
my-farmers
goods-delivered
capacity
revenues-this-year
total-revenues
]
to setup
clear-all
create-farmers 1000 [
setxy random-xcor random-ycor
set area one-of [10 50 100]
set goods-per-area one-of [5 10 15]
set color yellow
set shape "circle"
set size 0.5
]
create-factories 20 [
setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
]
set market-demand-goods 250000
set total-capacity-factories sum [capacity] of factories
set count-down 11
reset-ticks
end
to go
if count-down = 11 [
change-market-demand
ask farmers [
set status 0
set goods 0
]
]
if count-down = 10 [
ask farmers [
sow-seeds
]
]
if count-down = 5 [
if market-demand-goods - [capacity] of one-of factories > total-capacity-factories [
build-factory
]
]
if count-down = 2 [
ask farmers [
harvest-goods
]
ask factories [
receive-harvested-goods
sell-goods
]
]
set count-down count-down - 1
if count-down = 0 [
set count-down 11
]
end
to initialise-factory
set capacity 10000
ask farmers [
set distance-to-factory distance myself
]
set my-farmers (sort-on [distance-to-factory] farmers)
end
to change-market-demand
let chance random 100
if chance < 33 [
set market-demand-goods market-demand-goods - 50000
]
if chance >= 33 and chance < 66 [
set market-demand-goods market-demand-goods + 10000
]
if chance >= 66 [
set market-demand-goods market-demand-goods + 50000
]
let chance2 random 100
if chance2 < 50 [
set price-goods price-goods + 1
]
if chance2 >= 50 [
set price-goods price-goods - 1
]
end
to sow-seeds
set color brown
end
to build-factory
loop [
if total-capacity-factories >= market-demand-goods [stop]
create-factory 1 [
setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
set total-capacity-factories (total-capacity-factories + [capacity] of myself
]
end
to harvest-goods
set goods area * goods-per-area
end
to receive-harvested-goods
let i 0
loop [
if goods-delivered >= capacity [stop]
let closest-farmer-with-goods (item i my-farmers)
ifelse [status] of closest-farmer-with-goods = 0 [
set goods-delivered + [goods] of closest-farmer-with-goods
ask closest-farmer-with-goods [
set status "goods-delivered"
]
]
[set i i + 1]
]
end
to sell-goods
set revenues-this-year goods-delivered * price-goods
set total-revenues total-revenues + revenues-this-year
end
#JenB, thanks for the help! I also found out that it can be done as follows:
hatch factory 1 [
ask farmers [set distance-to-factory distance myself]
set my-farmers (sort-on [distance-to-factory] farmers)
]
Then I designed the following code for asking from the my-farmers list:
let i 0
loop [
if goods-delivered > capacity [stop]
let closest-farmer-with-goods (item i my-farmers)
ifelse [status] of closest-farmer-with-goods = 0 [ (; aka goods are not delivered yet to another factory)
set goods-delivered + [goods] of closest-farmer-with-goods
]
[set i i + 1] ; *else*
]
But this makes the model quite slow. Do you know how to make this simpler?

IFELSE [Compare the length of two separate lists] [ACT]

Following my question yesterday, I was trying to implement the code with filter and length. I think I achieved the filter but now I need the agents to compare their list length with other agent (activities) list. Here is my code:
ask agentes [
set culture-tags n-values 17 [random 2]
set shared-culture (filter [ i -> i = 0 ] culture-tags) ;count 0s and
create shared-culture
]
end
to move-agentes
ask agentes [
let nearest-activity min-one-of (activities) [ distance myself ]
ifelse any? activities in-radius sight-radius with
[ length t-shared-culture = length shared-culture ] ;as many 0s in t-shared-culture (specified later in the setup for activities) as in shared-culture
[ face nearest-activity ]
[ rt random 40
lt random 40
fd 0.3
]
]
Netlogo prints the next error: "ACTIVITIES breed does not own variable SHARED-CULTURE error while activity 176 running SHARED-CULTURE".
I imagine the mistake must be here: [ length t-shared-culture = length shared-culture ] but I don't know how to make both lists to interact.

Netlogo : inequality doesn't work properly under foreach

It supposes to be a simple code, but I don't know why it doesn't work properly.
I want to change a color of non-white turtle back into white if a condition is fulfilled. I put inequality as the condition.
for example, if the amount of red turtle > = 5, then [ do something ].
No error message for the code, but I found that [ do something ] codes are executed before the condition is fulfilled. For example, it is executed when the amount of turtle is 1 or 4. And I also found that there are moments when it reach > = 5, [ do something] code is not executed.
Below is the code
to seize-value
ask consumers [set type-of-value ( list blue red green) ]
foreach type-of-value [
if count consumers with [color = ?] > = 5 [
let z consumers with [color = ?]
ask z [ set color white ]
ask consumers with [color = white] [set value? false]
ask one-of cocreation-patches [ sprout 1 [gen-prevalue]]
]]
end
I've tried using a single color, instead of a list of color (without - foreach) it doesn't work either.
Can anyone help with this?
Thank you
You have something like the following at the top of your code to set up type-of-value as an agent variable:
breed [ consumers consumer ]
consumers-own [ type-of-value ]
However, you are treating it as a global variable in your code. First you say ask consumers [set type-of-value ( list blue red green) ] to set the AGENT variable called type-of-value to the list of colours. But you end that ask [] statement before starting the foreach.
Unless the consumers have different lists of colours, what you really want is something more like this (untested). Note that I have also removed your multiple creations of the same agentset (for efficiency):
globals [ type-of-value ]
to setup
clear-all
...
set type-of-value ( list blue red green)
...
reset-ticks
end
to seize-value
*type "seize-value on tick " print ticks
foreach type-of-value
[ let changers consumers with [color = ?]
*print ?
*print count changers
if count changers >= 5
[ ask changers
[ set color white
set value? false
]
ask one-of cocreation-patches [ sprout 1 [gen-prevalue] ]
]
]
end
UPDATE for debugging I have added three lines that will output key information for debugging. They are marked with an asterisk (*). Add those lines (without the *) and look at the output.