I get the following error when I run this code netlogo - netlogo

my model
of netlogo
globals [ mejor-recorrido
coste-mejor-recorrido ]
breed [ nodos nodo ]
breed [ hormigas hormiga ]
links-own [ coste
feromona ]
hormigas-own [ recorrido
coste-recorrido ]
to setup
__clear-all-and-reset-ticks
set-default-shape nodos "circle"
ask patches [set pcolor white]
crea-nodos
crea-aristas
crea-hormigas
set mejor-recorrido camino-aleatorio
set coste-mejor-recorrido longitud-recorrido mejor-recorrido
end
to crea-nodos
ask n-of num-nodos patches
[
sprout-nodos 1
[
set color blue + 2
set size 2
set label-color black
set label (word "Ciudad-" who)
]
]
end
to crea-aristas
ask nodos
[
create-links-with other nodos
[
; hide-link
set color red
set coste link-length
set feromona random-float 0.1
]
]
ask links [
if(feromona < 0.05) [die] ]
let max-coste max [coste] of links
ask links
[
set coste coste / max-coste
]
end
to crea-hormigas
create-hormigas num-hormigas [
hide-turtle
set recorrido []
set coste-recorrido 0
]
end
to reset
ask hormigas [die]
ask links [
hide-link
set feromona random-float 0.1
]
crea-hormigas
set mejor-recorrido camino-aleatorio
set coste-mejor-recorrido longitud-recorrido mejor-recorrido
clear-all-plots
end
to go
no-display
ask hormigas [
set recorrido generar-recorrido
set coste-recorrido longitud-recorrido recorrido
if coste-recorrido < coste-mejor-recorrido [
set mejor-recorrido recorrido
set coste-mejor-recorrido coste-recorrido
]
]
actualiza-feromona
tick
display
end
to-report camino-aleatorio
let resp [self] of nodos
report lput (first resp) resp
end
to-report generar-recorrido
let origen one-of nodos
let nuevo-recorrido (list origen)
let resto-nodos [self] of nodos with [self != origen]
let nodo-actual origen
while [not empty? resto-nodos] [
if (self = origen) [
ask hormigas [die]
]
let siguiente-nodo elige-siguiente-nodo nodo-actual resto-nodos
set nuevo-recorrido lput siguiente-nodo nuevo-recorrido
set resto-nodos remove siguiente-nodo resto-nodos
set nodo-actual siguiente-nodo
]
set nuevo-recorrido lput origen nuevo-recorrido
report nuevo-recorrido
end
to-report elige-siguiente-nodo [nodo-actual resto-nodos]
let probabilidades calcula-probabilidades nodo-actual resto-nodos
let rand-num random-float 1
report last first filter [first ? >= rand-num] probabilidades
end
to-report calcula-probabilidades [nodo-actual resto-nodos]
let pt map [([feromona] of ? ^ alpha) * ((1 / [coste] of ?) ^ beta)]
(map [arista nodo-actual ?] resto-nodos)
let denominador sum pt
set pt map [? / denominador] pt
let probabilidades sort-by [first ?1 < first ?2]
(map [(list ?1 ?2)] pt resto-nodos)
let probabilidad-normalizada []
let ac 0
foreach probabilidades [
set ac (ac + first ?)
set probabilidad-normalizada lput (list ac last ?) probabilidad-normalizada
]
report probabilidad-normalizada
end
to actualiza-feromona
;; Evapora la feromona del grafo
ask links [
set feromona (feromona * (1 - rho))
]
ask hormigas [
let inc-feromona (100 / coste-recorrido)
foreach aristas-recorrido recorrido [
ask ? [ set feromona (feromona + inc-feromona) ]
]
]
end
to-report aristas-recorrido [nodos-recorrido]
report map [arista (item ? nodos-recorrido)
(item (? + 1) nodos-recorrido)] (n-values num-nodos [?])
end
to-report arista [n1 n2]
report (link [who] of n1 [who] of n2)
end
to-report longitud-recorrido [nodos-recorrido]
report reduce [?1 + ?2] map [[coste] of ?] (aristas-recorrido nodos-recorrido)
end

I added
print aristas-recorrido nodos-recorrido
as the first line after to-report longitud-recorrido [nodos-recorrido]. This shows that aristas-recorrido nodos-recorrido returns a list in which some of the elements are nobody. That's what's processed by one of the lines that is generating the error you mentioned.
I believe that the problem is that in the definition of aristas-recorrido,
to-report aristas-recorrido [nodos-recorrido]
report map [arista (item ? nodos-recorrido)
(item (? + 1) nodos-recorrido)]
(n-values num-nodos [?])
end
arista attempts to report the link between subsequent nodo turtles in the list nodos-recorrido, but some of the pairs of nodos are not linked.
It looks to me like the procedure crea-aristas links every nodo with every other nodo, but then removes links with feromona < 0.05. After that, not all nodos are linked. Since nodos-recorrido above is just a randomly-ordered list of nodos (is this right?), some of the pairs of nodos are not linked, and thus arista returns nobody rather than a link for some pairs. Then this leads to the error in longitud-recorrido.
(I didn't investigate the other line that's generating the error, but I think you'll have enough information to track down that error now.)

Related

How to create a table to know which turtles visited each patch in the world?

I would like to remove a doubt and have some help.
I have a closed world of 600X600 patches. Each patch spawns a turtle (using the sprout command). Each turtle makes a series of moves and returns a value for its home patch. I would like to have the following result: know which turtle was in each patch in the world and export this result in table form in .csv
I created a list for this. But, NetLogo is running for a while and then it closes and doesn't finish the model. And so I think if I create a table it should work. The question is: will creating a table solve the problem of the model not running? And if so, how can I create a table by generating an output from that table in .csv? But, I haven't found a NetLogo command that I can create a table to adjust my code to.
Any tip is very welcome. I thank the attention
globals [ edge-size output-turtle-visits ]
patches-own [ turtle-visits ]
to setup
ca
random-seed 1
set edge-size 599
set-patch-size 1.2
resize-world 0 edge-size 0 edge-size
let pcolors []
set pcolors [ 85 95 ]
ask patches [ sprout 1 ]
ask patches [
set turtle-visits n-values count turtles [0]
set pcolor item (random 2) pcolors
]
reset-ticks
end
to go
ask turtles [
rt random 360
fd 1
]
ask patches [
foreach [who] of turtles-here [ id ->
let current-num-visits item id turtle-visits
set turtle-visits replace-item id turtle-visits (current-num-visits + 1)
]
]
end
to output
file-open ( output-turtle-visits )
file-print ( word "id_turtle;my_xcor;my_ycor;turtle_visits" )
foreach sort patches
[
t ->
ask t
[
file-print ( word self " ; " xcor " ; " ycor " ; " turtle-visits )
]
]
file-print "" ;; blank line
file-close
end

"Can't use XXX in an observer context because patch only"

I am havig some diffuculties with a part of my code. Netlogo reort "Can't use GO in an observer context because patch only"
My guess is that this is because in the go part I ask for a procedure (CACULATEWILANDATRAC) that does not begin with "ask Patches". However the (CACULATEWILANDATRAC) produce is to calculate one of the patches own-variables, so ask patches does not seem fit here.
I still tried to solve it with putting ask patches before the procure but then
I get another error when running the model : " only the observer can ASK the set of all patches.
error while patch 1079 509 running ASK
called by (anonymous command: [ [the-Land-use the-Senario] -> ask patches [ if count patches with [ the-Land-use ] > the-Senario [ set Willingstochange True ] ] ]) called by procedure CACULATEWILANDATRAC"
The problem thus lies with where to call for the CACULATEWILANDATRAC procedure?
It is now part of the go procedure but this thus gives the error "Can't use XXX in an observer context because turtle only".
My entire code:
> extensions [gis]
globals
[
land-use-map
Senario1N ;; the count of patches senario 1 describes
Senario1L
Senario1A
Senario1B
Senario1I
Senario1R
Senario1W
%landusetypeN ;; the amount patches
%landusetypeL
%landusetypeA
%landusetypeB
%landusetypeI
Willingstochange ;; If true a patch would like to change (if true the count of patches has a surplus comparing to the sneario, if false they have a shortage)
atractiveness ;; if a patch type is attractive to change in <1 = yess
Atractiveneighbor
]
patches-own
[ Land-use ;; Wat kind og landusetype a patch has
]
to setup
clear-all
load-gis ;;load the maps
setup-constants
update-global-variables
update-display
reset-ticks
end
to load-gis ;;load the maps
set land-use-map gis:load-dataset "a_LANDUSE_cellsize5.asc" ;;loads the land use map
gis:set-world-envelope-ds gis:envelope-of land-use-map ;;sets the envelope of the world to match that of the GIS dataset
gis:apply-raster land-use-map Land-use ;;patches in the land-use-map have a specific land-use now
ask patches [
if Land-use = 1 [ set pcolor Green ] ; Green = Nature ;; patches have a certain color now
if Land-use = 2 [ set pcolor red ] ; Dark red = Leisure
if Land-use = 3 [ set pcolor Yellow ] ; Yellow = Agriculture
if Land-use = 4 [ set pcolor brown ] ; brouwn = Buildup
if Land-use = 5 [ set pcolor grey ] ; grey = roads
if Land-use = 6 [ set pcolor pink ] ; pink = industry
if Land-use = 7 [ set pcolor blue ] ; Blue = water
]
resize-world 0 1633 0 780
set-patch-size 1
end
to setup-constants
set Senario1N 49174 ;; the count of patches senario 1 describes
set Senario1L 17871
set Senario1A 569970
set Senario1B 34202
set Senario1I 5540
set Senario1R 34968
set Senario1W 65594
end
to go ;; this asks the model to caculate certain variables defined below
givecountlansusetypes
askforchange
caculateWILandAtrac
tick
end
to givecountlansusetypes ;; here the cuurent amount of patches is shown
show count patches with [Land-use = 1]
show count patches with [Land-use = 2]
show count patches with [Land-use = 3]
show count patches with [Land-use = 4]
show count patches with [Land-use = 5]
show count patches with [Land-use = 6]
show count patches with [Land-use = 7]
end
to update-display
ask patches
[
if Land-use = 1 [ set pcolor Green ] ;; Green = Nature ;; patches have a certain color now
if Land-use = 2 [ set pcolor red ] ;; Dark red = Leisure
if Land-use = 3 [ set pcolor yellow ] ;; Yellow = Agriculture
if Land-use = 4 [ set pcolor brown ] ;; brouwn = Buildup
if Land-use = 5 [ set pcolor grey ] ;; grey = roads
if Land-use = 6 [ set pcolor pink ] ;; pink = industry
if Land-use = 7 [ set pcolor blue ] ;; Blue = water
]
end
to update-global-variables
if count patches > 0
[ set %landusetypeN (count patches with [ Land-use = 1 ] / count patches) * 100
set %landusetypeL (count patches with [ Land-use = 2 ] / count patches) * 100
set %landusetypeA (count patches with [ Land-use = 3 ] / count patches) * 100
set %landusetypeB (count patches with [ Land-use = 4 ] / count patches) * 100
set %landusetypeI (count patches with [ Land-use = 6 ] / count patches) * 100
]
end
to caculateWILandAtrac
;; Sets Willingness to change true if patches are with more fellowpatches than the senario decribes
(foreach list (Land-use = 1) (Land-use = 2)[49174 17871]
[ [the-Land-use the-Senario] -> ask patches [if count patches with [the-Land-use] > the-Senario [ set Willingstochange True ] ] ])
;; gives score to the patches attractiveness based on the ratio patches/senario
(foreach list (Land-use = 1) (Land-use = 2)[49174 17871]
[ [the-Land-use the-Senario] -> ask patches [ set atractiveness (count patches with [the-Land-use]/ the-Senario) ] ])
end
to askforchange
ask patches [
if Willingstochange = true [change] ;; this ask the patches that are willing to change (have a surpuls) to go and change
]
end
to change
ask neighbors with [Willingstochange = false ] ;; this asks if the patch had neigbors with a shortage
[set Atractiveneighbor min-one-of patches [atractiveness]] ;; this asks to give the neigbor with the lowest patchcount/senario ratio
ask patches [set Land-use ([Land-use] of Atractiveneighbor)] ;; this asks the patches to change their land-use to the land-use of neigbor with the lowest patchcount/senario ratio
end
In your last line of code the current asked patch (asked in askforchange) asks all patches to set their Land-use accordingly. I think that there lies your problem.
Maybe it solves your problem, if you replace the last line with the following:
set Land-use ([Land-use] of Atractiveneighbor)
With this, the currently asked patch changes its land-use accordingly. But I am not quite sure, if that is what you want the procedure to do there?

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.

Netlogo - Divide world equally between n agents

I'm creating an inspection model in Netlogo, and each inspector is responsible for n patches. That is, I need to divide the world in areas that are exclusive for each inspector.
I tried it with
set range (world-width * world-height / inspectors) ^ 0.5
But their range is higher than expected, and it allows one inspector to "invade" the area of other inspectors, which is not desirable.
This approach is probably way over-complicated but may do what you need- it splits the world into even vertical bands of "territory." Note that it only works properly if the world's minimum xcor is 0, and if the world-width is divisible by the number of inspectors- otherwise one inspector will have an inspection area that is different from all the others. For example, using this setup:
breed [ inspectors inspector ]
inspectors-own [ my-territory ]
to setup
ca
resize-world 0 29 0 29
create-inspectors ninspectors [
set my-territory nobody
]
split
reset-ticks
end
Make lists to store the minimum and maximum xcor values, then use those to section off patches to assign as territories to different inspectors. More explanation in comments:
to split
; get a count of the inspectors
let n count inspectors
; get section widths
let n-xcor ( max-pxcor - min-pxcor ) / n
; build lists to define min-maxes of sections
let n-min ( range min-pxcor max-pxcor n-xcor )
let n-max lput ( max-pxcor + 1 ) n-min
set n-max but-first n-max
; Foreach of the min-max pairs, set patches within
; the min-max boundary be set to the territory of one
; of the inspectors that currently has no territory
( foreach n-min n-max [
[ _min _max ] ->
set _min ceiling _min
set _max ceiling _max
let cur_inspector one-of inspectors with [ my-territory = nobody ]
ask patches with [ pxcor >= _min and pxcor < _max ] [
ask cur_inspector [
ifelse my-territory = nobody [
set my-territory myself
] [
set my-territory ( patch-set my-territory myself )
]
]
set pcolor ( [color] of cur_inspector ) - 2
]
])
; Move inspectors to their territory
ask inspectors [
setxy ( mean [pxcor] of my-territory ) ( mean [pycor] of my-territory )
show my-territory
pd
]
end
To check that it's working, you can have your inspectors wander around:
to go
ask inspectors [
face one-of neighbors with [ member? self [my-territory] of myself ]
fd 1
]
tick
end

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