Netlogo: How to ask link-neighbor to do something - netlogo

I am simulating a classroom. In a classroom there are about 90 seats, 20 lights, 20 fans and 4 ACs. I create num-of-students where each student has an assigned random entry-time. When each student enters after a random time and sits on a seat the corresponding (in-radius)light or fan or ac turn on and a link is established between the the student and the in-radius appliance. Each appliance (e,g light, fan and AC) has their own wattage value. After all the students sits down the total energy consumption (in KWh) will be calculated for all the fans, lights and ACs.
How can I store the on-time of each appliance e.g (time minus entry-time), where time is the total class time. So that afterwards I can sum all the on-time of each appliance(e.g fan) and multiply it with its watt value. This is the part of the code.
globals[
temp1 simulation-timer number-of-seats number-of-lights number-
of-fans number-of-acs ]
breed [lights light]
breed [fans fan]
breed [acs ac ]
breed [students student ]
to setup
...
...
place-seats-students
place-lights
place-fans
place-acs
create-students-classroom
end
to create-students-classroom
create-students number-of-students [
set entry-time random threshold + 1
let stu-no sort-on [who] students
foreach stu-no [x -> ask x [ show (word x " -> " entry-time )
] ]
ask students [
set shape "person"
set color 3
] ]
end
to go
set simulation-timer 0
output-show (word "timer = "simulation-timer )
tick
move-students
while [simulation-timer < time ] [
set simulation-timer simulation-timer + 1
output-show (word "timer = "simulation-timer )
end
to move-students
let s sort [who] of seats
let a first s
let l length s
while [ l > (number-of-seats - number-of-students )] [
set temp1 simulation-timer
tick
tick
ask students [ if ( entry-time = temp1 ) [
move-to seat a
set color red
ask students
[create-links-with lights in-radius 5
create-links-with fans in-radius 5
create-links-with acs in-radius 9 ]
show (word "number of links is" count links)
appliance-on
store-on-time
show (word temp1 "," l "," a)
set s remove a s
set a a + 1
set l length s
]
]
set simulation-timer simulation-timer + 1
output-show (word "timer = "simulation-timer )]
end
to appliance-on
ask students with [color = red ]
[ask my-links
[ask other-end [set color green] ] ]
stop
end
to store-on-time
ask students [
ask link-neighbor fan ifelse it is on [
let on-time [ time - entry-time ]
[do nothing]
ask students [
ask link-neighbor light ifelse it is on [
let on-time [ time - entry-time ]
[do nothing]
end
How can I write the store-on-time procedure, so that later I will be able sum to all the on-times for all the appliance to calculate the KWh consumed. Any help will be greatly appreciated.

If you need to store something, then you need to create a variable for it. Since they might turn on, off, on etc, I would personally have two variables for each appliance (eg lights-own and fans-own etc). For lights, they could be named light-on-time, light-on-duration and similarly for others.
The way this works in code is add
set light-on-time ticks
whenever you turn the light on. And have
set light-on-duration light-on-duration + ticks - light-on-time + 1
whenever you turn the light off. The reporter ticks is just the current state of the clock.

Related

Stopping turtles from having negative resources

My model creates a relationship between employees and citizens. Whereby the employees obtain office and then distribute to the employees:
globals [
office-space
]
breed [ offices office ]
breed [ service-desks service-desk ]
breed [ employees employee ]
breed [ citizens citizen ]
offices-own [ money ]
employees-own [ money ]
citizens-own [ money ]
to setup
clear-all
create-offices 1 [
set shape "building institution"
set size 4
set color yellow
set money num-of-money
]
create-employees num-of-employees [
set shape "person"
set size 1.5
set color blue
setxy random-xcor random-ycor
]
create-citizens num-of-citizens [
set shape "person"
set size 1.5
set color white
setxy random-xcor random-ycor
]
;; create 4 service desks
let service-desk-patches (patch-set patch 0 8 patch 8 0 patch 0 -8 patch -8 0)
ask service-desk-patches [
sprout-service-desks 1 [
set shape "building institution"
set color pink
set size 3
]
]
;; create office space
set office-space patches with [pxcor <= 8 and pxcor >= -8 and pycor <= 8 and pycor >= -8 ]
ask office-space [set pcolor grey]
;; set all employees randomly within the grey box
place-on-color-employees
;; set all citizens randomly outside of the grey box
place-on-color-citizens
reset-ticks
end
to place-on-color-employees
let _patches (patches with [pcolor = grey])
ask employees [
move-to one-of (_patches with [not any? turtles-here])
]
end
to place-on-color-citizens
let _patches (patches with [pcolor = black])
ask citizens [
move-to one-of (_patches with [not any? turtles-here])
]
end
to go
ask employees [
set label money
]
ask citizens [
set label money
]
employee-movement-without-money
employee-take-money
employee-movement-with-money
citizens-movement
citizen-take-money
tick
end
to employee-movement-with-money
ask employees [
ifelse [ pcolor ] of patch-ahead 1 = black
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of citizens [ distance myself ]
if money > 0 [
face target
fd 1
]
]
end
to employee-movement-without-money
ask employees [
let target patch 0 0
if ( money = 0 ) or ( money < 0 ) [
face target
fd 1
]
]
end
to citizens-movement
ask citizens [
ifelse [pcolor] of patch-ahead 1 = grey
[ rt random-float 360 ]
[ forward 1 ]
let target min-one-of service-desks [ distance myself ]
if money = 0 [
set heading (towards target )
]
]
end
to employee-take-money
ask employees [
if any? offices-here [
set money money + 1
set color green
;set label money
]
]
end
to citizen-take-money
ask citizens [
if any? employees in-radius 0.5 [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
When this model is run, the employees collect money and go to meet citizens, however, in the citizen-take-money procedure, I have not found a way to prevent the citizens from taking money from the employees so they don't have negative values. I tried adding the employee-movement-without-money to force the employees to turn move away from the citizens, but they just congregate on patch 0 0.
I also tried adjusting the citizens-take-money procedures by creating an if and arugment:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
But that didn't work either.
First piece of advice, build NetLogo models gradually. You need to make sure each piece works before adding the slightly more complicated behaviour. You should never have more than one thing wrong in a NetLogo model at the same time, very hard to debug.
Here, the basic problem appears to be that you are acting on all turtles instead of just the relevant turtle. Here is your supplementary code that tries to introduce a check:
to citizen-take-money
ask citizens [
if (any? employees in-radius 0.5) and (employees money > 0) [
ask employees [
set money money - 1
]
]
set money money + 1
set color orange
]
end
First, have a look at your check - conceptually, what are you testing with the second part employees money > 0. That doesn't actually look like valid NetLogo code to me, are you trying to ask if there are any employees with with money > 0?
Regardless, let's say it gets past that check, the next line is ask employees - at this point you are telling EVERY employee in the model to reduce their money.
What you need to do is just find the right employees and have those ones reduce their money. Something more like:
to citizen-take-money
ask citizens
[ let nearby employees in-radius 0.5 with [money > 0]
if any? nearby
[ ask nearby [ set money money - 1 ]
set money money + 1
set color orange
]
]
end
Also, this procedure is asking every citizen to do this and you have named it as if only one citizen is doing it. So think about which way you actually want the process to work.
Finally, what happens if you have several citizens close to several employees. Say 3 citizens reduce their money because they are close to the same employee - at the moment, the employee only increases their money by 1 and the remaining 2 disappears. This is an example of what I mean by build gradually and check it works before adding in the next thing. Perhaps you could have them just change colours if the condition is met before trying to add in the money transfers. That would help you spot that you had lots of people triggered at once.

Choice based on other turtles' variables

I'm stuck with my ABM. The situation is very simple: there are some turtles, producers, and others, choosers. Producers produce a product with a certain quality, choosers choose based on perceived quality.
Perceived quality is a function "quality-of-product-of-producers - beta-of-chooser", where beta is an individual adaptive variable. All these variables are turtles-own, and they all own them (at each round roles are switched).
I'd like the following to happen: quality-of-product is a producers' variable, beta is a choosers' variable. How to code the operation?
I've tried the following things:
ask turtles with [group = "producers"] [
set perceived-product-quality ((product-quality - beta))
]
However, like beta is producers' one (incorrect, should be choosers).
Then I've tried this:
ask turtles with [group = "choosers"] [
let quality [product-quality] of turtles with [ group = "producers" ]
set perceived-product-quality quality - beta
]
However, it doesn't work, runtime error: “expected input to be a number but got the list“.
How can I do it?
I'm not sure what your exact use case is, if you're trying to query the mean product quality / beta from all producers and choosers, but the general answer I think is that you need to be explicit with which turtles you're actually trying to pull values from. When you use ask, the agent that you are asking to do something will default to using its own variables if it owns them. So, if you are needing to stick with turtles-own variables rather than making breeds and breed-specific variables, you'll need to explicitly state which turtle you're trying to reference. Here is a toy example that has choosers pick the product quality of whatever producer is nearest for use in the formula:
turtles-own [ group product-quality beta perceived-product-quality]
to setup
ca
ask n-of 10 patches [
sprout 1 [
set group one-of [ "producers" "choosers" ]
]
]
ask turtles [
ifelse group = "producers" [
set product-quality random 500 + 500
set beta random 200 + 100
set color red
] [
set product-quality random 50 + 50
set beta random 20 + 10
set color blue
]
]
reset-ticks
end
to set-perceived
let current-producers turtles with [ group = "producers" ]
let current-choosers turtles with [ group = "choosers" ]
ask current-choosers [
; Pick the closest producer
let closest-producer min-one-of current-producers [ distance myself ]
; Pull the product quality of that closest producer
let closest-product-quality [ product-quality ] of closest-producer
; Set MY perceived product quality to be closest-product-quality - MY beta
set perceived-product-quality closest-product-quality - beta
show (
word "I used the turtle " closest-producer
" to determine my perceived product quality of: " perceived-product-quality
)
]
end
Edit:
Comment update:
I'd like the following to happen: choosers do the operation “perceived-product-quality - beta“ for all turtles in the Moore neighbour. After doing this, they are going to choose the product with highest value of perceived-product-quality.
In this version, there is a to-report procedure that reports the perceived product quality from the perspective of from-who. This can then be used with max-one-of to return the turtle with the highest perceived value.
turtles-own [ group product-quality beta perceived-product-quality]
to setup
ca
resize-world 0 5 0 5
set-patch-size 40
ask patches [
sprout 1 [
set group one-of [ "producers" "choosers" ]
]
]
ask turtles [
ifelse group = "producers" [
set product-quality random 500 + 500
set beta random 200 + 100
set color red
] [
set product-quality random 50 + 50
set beta random 20 + 10
set color blue
]
]
reset-ticks
end
to choose-best-moore
let current-choosers turtles with [ group = "choosers" ]
ask current-choosers [
let current-producers ( turtles-on neighbors ) with [ group = "producers" ]
ifelse any? current-producers [
let turtle-with-highest-perceived max-one-of current-producers [ perceived-target-value myself ]
let real-product-quality [product-quality] of turtle-with-highest-perceived
let false-product-quality [ perceived-target-value myself ] of turtle-with-highest-perceived
show ( word "I surveyed " count current-producers " and found that " turtle-with-highest-perceived
" had the best product quality (real: " real-product-quality ", perceived: " false-product-quality ")" )
] [
show "I found no producers in my neighboring cells"
]
]
end
to-report perceived-target-value [ from-who ]
let target-product-quality product-quality
let target-perceived-quality ( target-product-quality - [beta] of from-who )
report target-perceived-quality
end

Storing a value

A classroom is simulated where appliances (e.g lights Fans and ACs) turn on when a student sits next to it. Each appliance has its own wattage rating. When an appliance is turned on its color changes to green and the on-time is noted and the duration on-time is stored. But if a student sits next to a appliance (e.g light) that is already on. The duration-on-time should not be stored as it would be a repetition.
globals[
simulation-timer
to appliance-on
ask students [ ask lights in-radius 4
[ifelse not already-on?
[ set color green
set light-on-time ticks
set light-on-duration light-on-duration + (time - ticks)
show (word "light on duration = " light-on-duration)
set already-on? true] [
set light-on-duration light-on-duration]]]
In this code the light-on-duration is not adding for all of the lights. Only individual light-on-duration is shown. How should I fix this? Thank you!
I think you have a logic problem rather than a coding problem. You can't add to duration when the light turns on because it hasn't yet built up any duration. Here is a complete model that turns lights on and off and stores duration. I am using ticks as the time, and each tick it adds 5 students and removes 5 students. But what's important is the logic of turning the lights on and off.
globals [light-radius]
breed [students student]
students-own
[ desk
]
breed [lights light]
lights-own
[ on?
turned-on
duration-on
]
to setup
clear-all
set light-radius 3
ask patches [ set pcolor white ]
ask patches with [pxcor mod 3 = 0 and pycor mod 3 = 0]
[ sprout-lights 1
[ set size 0
set on? false
set pcolor gray
]
]
reset-ticks
ask n-of 30 patches
[ sprout-students 1
[ set color blue
]
ask lights in-radius light-radius [switch-light-on]
]
end
to go
repeat 5 [student-arrive]
repeat 5 [student-leave]
ask lights with [any? students in-radius light-radius]
[ switch-light-on
]
tick
end
to student-arrive
ask one-of patches with [not any? students-here]
[ sprout-students 1
[ set color blue
ask lights in-radius light-radius with [not on?]
[ switch-light-on
]
]
]
end
to switch-light-on
set pcolor yellow
set on? true
set turned-on ticks
end
to student-leave
ask one-of students
[ die
]
ask lights with [ on? and not any? students in-radius light-radius ]
[ switch-light-off
]
end
to switch-light-off
set pcolor gray
set on? false
type "previous duration: " print duration-on
let how-long ticks + 1 - turned-on
set duration-on duration-on + how-long
type "new duration: " print duration-on
end
Note that you can't actually see the light turtles, I am making the patch turn yellow for on and grey for off. Every third patch has a light.

How to select up to a maximum number of turtles using roulette wheel selection

In my model the turtles have two sexes where the males have two potential tactics. The females count the number of males in a set radius.
I want the females to weight their probability of selecting from the group of males (without replacement) depending on the relative frequency of the two male tactics.
I already have the code for the probability of selecting from the males (matingPoolProbAnad and matingPoolProbRes) but I don't know how to implement it, though the rnd extension seems the way to go, specifically rnd:weighted-n-of size agentset [ reporter ].
It's complicated by three things (1) the males can mate with more than one female but (2) only once with a given female and (3) females can only mate with a maximum of five males.
to count-mates ; ask the females to count the number of males in a 10 patch radius & then
; determine the frequency of the resident males in their patch
ask turtles with [sex = "female"]
[
if any? turtles with [sex = "male"] in-radius 10
[ set potentialMates turtles with [sex = "male"] in-radius 10
ifelse any? potentialMates with [anadromousM = 1]
[ set FA count potentialMates with [anadromousM = 1] / count potentialMates ]
[ set FA 0]
ifelse any? potentialMates with [anadromousM = 0]
[ set FR count potentialMates with [anadromousM = 0] / count potentialMates ]
[ set FR 0]
]
]
end
to mating-pool-prob ; negative frequency dependency which is based on the number of male
; resident turtles
ask turtles with [sex = "female"]
[
ifelse (FA = 1) and (FR = 0)[
set matingPoolProbAnad 1
set matingPoolProbRes 0
]
[ifelse (FA > 0) and (FR < 1)
[
set matingPoolProbRes exp(a - b * (FR - c ))/(1 + exp(a - b * (FR - c)))
set matingPoolProbAnad 1 - matingPoolProbRes
]
[
set matingPoolProbAnad 0
set matingPoolProbRes 1
]
]
]
end
This example may approach what you're getting at, but obviously would need to be adapted from this toy version. This setup sprouts 75% of males with strategy A and the rest with strategy B, and gives all turtles an empty agentset of mates to start off:
breed [ males male ]
breed [ females female ]
turtles-own [ mates ]
males-own [ strategy ]
females-own [ max-mate-count mate-count ]
to setup
ca
ask n-of 200 patches [
sprout-males 1 [
ifelse random-float 1 < 0.75 [
set strategy "A"
set color orange
] [
set strategy "B"
set color violet
]
]
]
ask n-of 50 patches with [ not any? turtles-here ] [
sprout-females 1 [
set color green
]
]
ask turtles [
set mates ( turtle-set )
]
reset-ticks
end
Use a while loop to have each female iteratively assess the strategy proportions of the males available to her, then add them to her 'mates' list. More detail in comments:
to choose-mates
ask females [
; set a cap on possible mates for females; 5, or the number
; available within the radius if less than 5
let availa-males males in-radius 10
let n-max count availa-males
set max-mate-count ifelse-value ( n-max < 5 ) [ n-max ] [ 5 ]
; Until a female has chosen up to her maximum number of mates:
while [ mate-count < max-mate-count ] [
; determine which available males are not already in her 'mates' agentset
set availa-males availa-males with [ not member? self [mates] of myself ]
; assess the proportion of B strategy in remaining available males
let prop_B ( count availa-males with [ strategy = "B" ] ) / n-max
; example probability choice, just meant to choose B males
; with a frequency disproportionate to availability
let proba_B ifelse-value ( prop_b * 2 < 0.6 ) [ prop_b * 2 ] [ 0.6 ]
; use a random float to determine which strategy type is chosen
set mates ( turtle-set mates ifelse-value ( random-float 1 < proba_B )
[ one-of availa-males with [ strategy = "B" ] ]
[ one-of availa-males with [ strategy = "A" ] ] )
; count the current mates to break the while loop once
; the maximum number of mates is reached
set mate-count count mates
]
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
]
end
To check that 'B' males are being chosen disproportionately to their availability:
to check-values
let all-mates map [ i -> [strategy] of i ] [mates] of females
print word "Average proportion of 'B' mates chosen: " mean map b-proportion all-mates
print word "Actual proportion of 'B' males: " ( ( count males with [ strategy = "B" ] ) / count males )
end
to-report b-proportion [ input_list ]
let tot length input_list
let nb length filter [ i -> i = "B" ] input_list
report nb / tot
end
I'm not 100% sure that that's what you're after- maybe you can use the rnd package to clean up the loop.
Edit in response to comment
If you modify the end of the `choose-mates like so:
...
...
; have the female's males add her to their own mates agentset
ask mates [
set mates ( turtle-set mates myself )
]
if n-max < count mates [
print "Fewer available males than mates"
]
]
end
And your go looks like:
to go
choose-mates
end
You can run setup and go as many times as you like and you should never see the printout "Fewer available males than mates":
to repeat-1000
repeat 1000 [
setup
go
]
end
I ran that a few times and never had count availa-males be less than the count of mates. However, if you add in movement without allowing the females to reset their mates agentset, you do start to see it- for example, try running this a few times:
to go
choose-mates
ask turtles [ fd 1 ]
end
Now, because the turtles are moving around, you have some cases where females held on to their mates from the previous function call and then moved into a space where there were fewer availa-males. The quick and easy fix is to have females clear their mates each time. Where you do that depends on your model goals (how often do females choose mates? Do they only forget some of their previous ones? etc), but here's a very simple way:
to go
ask turtles [ set mates ( turtle-set ) ]
choose-mates
ask turtles [ fd 1 ]
end
Now you can run that as many times as you like and shouldn't see the "Fewer available males than mates" printout.

Subtract. SET variableX-variableY only once

I'm trying to set a resource variable. It will be time and will function like sugar in sugarscape. Its setup is: ask agentes [set time random-in-range 1 6].
The thing is... I want the agentesto participate in activities linking like we said here. But, with each participation, it should subtract a unity of agentes's time. I imagine it must be with foreachbut I seem to be unable to grasp how this works.
ask n-of n-to-link agentes with [n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
while [time >= 2] [
create-participation-with myself [ set color [color] of myself ] ]
foreach (command I don't know)[
set time time - count participations]]
Essentially, I want the agentes to look if they have time to participate. If they do, they create the link and subtract 1 to their time. Only ONE per participation. If they have 3 time, they'll have 2 participations and 1 time. If they have 1 time, they won't have links at all.
EDIT
You're right. I don't need while. About foreach, every place I looked said the same thing but I can't think of other way. About colors, they're only for show purpose.
The relationship between time and participation counts is as follows: the agentes have time they can spend in activities. They participate if time>=2. But every participation (link with activity) consumes 1 time when the link is active (I didn't write the decay code yet; they'll regain their time when it is off).
EDIT V2
Nothing, it keeps subtracting even with the []. Maybe the best choice is if I give you the code so you can try it. You'll have to set 5 sliders: prob-female (53%), initial-people (around 200), num-activity (around 20), n-capacity (around 25) and sight-radius (around 7). And two buttons, setup and go. I also set a patch size of 10 with 30 max-pxcor and max-pycor. Here is the code. Sorry if I'm not clear enough!
undirected-link-breed [participations participation]
turtles-own [
n-t-activity
]
breed [activities activity]
activities-own [
t-culture-tags
shared-culture
]
breed [agentes agente]
agentes-own [
gender
time
culture-tags
shared-culture
]
to setup
clear-all
setup-world
setup-people-quotes
setup-activities
reset-ticks
END
to setup-world
ask patches [set pcolor white]
END
to setup-people-quotes
let quote (prob-female / 100 * initial-people)
create-agentes initial-people
[ while [any? other turtles-here ]
[ setxy random-xcor random-ycor ]
set gender "male" set color black
]
ask n-of quote agentes
[ set gender "female" set color blue
]
ask agentes [
set culture-tags n-values 11 [random 2]
set shared-culture (filter [ i -> i = 0 ] culture-tags)
]
ask agentes [
set time random-in-range 1 6
]
ask agentes [
assign-n-t-activity
]
END
to setup-activities
create-activities num-activity [
set shape "box"
set size 2
set xcor random-xcor
set ycor random-ycor
ask activities [
set t-culture-tags n-values 11 [random 2]
set shared-culture (filter [i -> i = 0] t-culture-tags)
]
ask activities [
assign-n-t-activity]
]
END
to assign-n-t-activity
if length shared-culture <= 4 [
set n-t-activity ["red"]
set color red
]
if length shared-culture = 5 [
set n-t-activity ["green"]
set color green
]
if length shared-culture = 6 [
set n-t-activity ["green"]
set color green
]
if length shared-culture >= 7 [
set n-t-activity ["black"]
set color black
]
END
to go
move-agentes
participate
tick
end
to move-agentes
ask agentes [
if time >= 2 [
rt random 40
lt random 40
fd 0.3
]
]
end
to participate
ask activities [
if count my-links < n-capacity [
let n-to-link ( n-capacity - count my-links)
let n-agentes-in-radius count (
agentes with [
n-t-activity = [n-t-activity] of myself ] in-radius sight-radius)
if n-agentes-in-radius < n-to-link [
set n-to-link n-agentes-in-radius
]
ask n-of n-to-link agentes with [
n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
if time >= 2 [
create-participation-with myself [
set color [color] of myself ]
ask agentes [set time time - count my-participations] ]
]
ask activities [
if not any? agentes in-radius sight-radius [
ask participations [die]
]
]
]
]
end
to-report random-in-range [low high]
report low + random (high - low + 1)
END
EDIT V3
I asked Bill Rand to help me and he solved the problem. The issue was in this line: let candidates agentes with [ n-t-activity = [n-t-activity] of myself ] in-radius sight-radius. He solved the problem this way: let candidates agentes with [ n-t-activity = [n-t-activity] of myself and not participation-neighbor? myself ] in-radius sight-radius. Being this and not participation-neighbor? myself the condition to make sure that the agente is not already a part of that activity.
You almost never need foreach in NetLogo. If you find yourself thinking you need foreach, your immediate reaction should be that you need ask. In particular, if you are iterating through a group of agents, this is what ask does and you should only be using foreach when you need to iterate through a list (and that list should be something other than agents). Looking at your code, you probably don't want the while loop either.
UPDATED FOR COMMENTS and code - you definitely do not need while or foreach.
Your problem is the following code. You ask agentes that satisfy your conditions to create the links, but then you ask ALL AGENTES to change their time (line I have marked), not just the agentes that are creating participation links.
ask n-of n-to-link agentes with [
n-t-activity = [n-t-activity] of myself] in-radius sight-radius [
if time >= 2 [
create-participation-with myself [
set color [color] of myself ]
ask agentes [set time time - count my-participations] ] ; THIS LINE
]
The following code fixes this problem. I have also done something else to simplify reading and also make the code more efficient - I created an agentset (called candidates) of the agentes that satisfy the conditions. In this code, the candidates set is only created once (for each activity) instead of twice (for each activity) because you are creating it to count it and then creating it again to use for participation link generation.
to participate
ask activities
[ if count my-links < n-capacity
[ let candidates agentes with [
n-t-activity = [n-t-activity] of myself ] in-radius sight-radius
let n-to-link min (list (n-capacity - count my-links) (count candidates ) )
ask n-of n-to-link candidates
[ if time >= 2
[ create-participation-with myself [ set color [color] of myself ]
set time time - count my-participations ] ; REPLACED WITH THIS LINE
]
ask activities [
if not any? agentes in-radius sight-radius [
ask participations [die]
]
]
]
]
end