I have model which consists of two type of agents rescue-agents and population-agents. The model is basically a search and rescue where there are bunch of nodes connected with links.The rescue agents will first search for an agent to be rescued, then travel from node to node till they reach the population agent.
Lets say my population-agents-own a variable called injury level, which takes values 1,2 or 3. I want my rescue-agents to first rescue population-agents with injury- level 2 or 3. Doesn't matter which one it is. Next move on to injury-level 1.
The way I have written the code is, if the count of my population-agents with injury level 2 and 3 becomes 0. Start searching for agents with injury-level 1. But the problem is, as my population agents with injury level 2 or 3 closes to 0 (1 or 2 left), some of my rescue agents will remain at the same node without looking for agent of injury level 1, until all agents with injury 2 or 3 are rescued.
For example if there were 2 rescue-agents, 1 pop-agent with injury-level 3 and 2 pop-agents with injury level 1. One of the rescue agent will travel to the pop-agent with injury 3. but the other will remain in the same node, until all pop-agents with injury 3 are rescued and then he will starting to move on to injury 1.
Note each rescue agent will only target one population agent, to make sure they don't travel to the same person.
Is there any way to solve this problem where rescue agent are not waiting in same node until the population of injury 2 and 3 reaches 0? or better way of solving
Thanks
breed[rescue-agents rescue-agent]
breed[pop-agents pop-agent]
pop-agents-own [injury]
rescue-agents-own [target-pop-agent]
...
to go
...
;search agent
to find-agents
let pop-ij1 pop-agents with [injury = 1]
let pop-ij2 pop-agents with [injury = 2]
let pop-ij3 pop-agents with [injury = 3]
let Pop-ij2&3 pop-agents with [injury = 2 or injury = 3]
if target-pop-agent = nobody[
ifelse (count pop-ij2 = 0 and count pop-ij3 = 0)
[set target-pop-agent min-one-of (pop-ij1) in-radius 30 with [not
targeted?][distance myself]]
[set target-pop-agent min-one-of (pop-ij2&3) in-radius 30 with [not
targeted?][distance myself]]
]
...
end
Related
I am working on a project to model the impact of charging electric cars on the grid and modeling/simulating the driving and charging habits of the car users. I'm getting an issue in my code that unable to resolve yet.
Each location has a limited number of charging ports. For example, WORK has a total of 2 TERMINALS, so only 2 adopters can charge there simultaneously (first-come-first-serve basis). What I want to do is when 2 adopters arrive at WORK, they start charging (if required, i.e. "charging-status" = true). Any additional adopters wait until a port is available there. The adopters who finish charging should vacate the charging port for those in the wait-list, even if they don't leave.
Here's part of my effort (code) that I did:
to go
...
charge-car ; sets the charging-status based on state-of-charge.
ask adopters
[
if charging? and not marked?
[
ifelse remaining-ports != 0
[
set remaining-ports max list (remaining-ports - 1) 0
set marked? true
]
[set occupied? true]
]
if marked? and not charging?
[
set remaining-ports min list (remaining-ports + 1) terminals
set marked? false
set occupied? false
]
]
ask adopters with [charging? and marked?]
[
set color green
let battery0 battery
let charging-speed0 charging-speed
let battery1 max list 0 ( battery + charging-speed0 )
set battery min list battery1 battery-capacity
let charged min list ( battery - battery0 ) charging-speed0
set charge-demand charge-demand + charged
set soc battery / battery-capacity
set range-left battery / discharge-patch
]
tick
end
Now, the issue is this: there are multiple location on the map with charging ports. This code gives different results at some locations, even though it is the same algorithm for all locations and agents. For example, if both ports are occupied at certain locations, the "occupied?" will be true for some locations and not all of the ones with all ports engaged. I mean to say, this is showing quite a random response.
Can anyone please help me with this? Is there another way to do what I want to do? Also, please let me know if you need more info to understand my situation.
Thank you!
Edit:
This is my code for to go
to go
...
ask adopters
[
if patch-here = current-loc ; choose next target only when reached at a destination (current location)
[
choose-target
set nearest-station min-one-of patches with [location = "charging-station"][distance myself]
] ; choose target based on start time and current location
; go to target only when NOT at the arbitrary target location
if target != [0 0]
[
let dist-to-targ distance-between current-loc target
let dist-to-station distance-between current-loc nearest-station
ifelse dist-to-targ > range-left and dist-to-station < range-left
[go-to-station nearest-station]
[go-to-target]
]
if charging = "Charge Car Now"
[charge-car]
...
]
where, charge-car is
to charge-car
if patch-here = current-loc and charging-point
[
ifelse soc < 1
[
if charge-power = 1
[
set charging-speed 1 / 12
set charging-status true
]
if charge-power = 2
[
set charging-speed 6.6 / 12
set charging-status true
]
]
[
set charging-status false
set color blue
]
]
end
and go-to-target is
to go-to-target
ifelse patch-here != target
[
; move towards destination and use fuel
face target
; set marked? false
set color blue
ifelse distance target <= speed
[set speed1 0.3 * distance target] ; decrease speed as target gets nearer
[set speed1 speed]
forward speed1
set moving? true
set charging-status false
if marked?
[
set rem-term min list (rem-term + 1) terminals
type patch-here type "Updated ports" print rem-term
set marked? false
set occupied? false
]
]
[
move-to target
if target != [0 0]
[set dist-trav distance-between current-loc target]
set current-loc target
set moving? false
set dwell dwell-acq day-ind time-ind position [location] of target places ; calculate dwell time based on arrival time at target
ifelse dwell < 0
[
set dwell 288 - (ticks mod 288) ; spend rest of the time till 24:00 at that location
set dwell-flag 1
]
[set dwell-flag 0]
if current-loc = target
[
set arrival-time (ticks mod 288)
set start-time (dwell + arrival-time) mod 288
set target [0 0]
set battery battery - (discharge-patch * dist-trav) ; discharge based on distance traveled per tick
set soc battery / battery-capacity
set range-left battery / discharge-patch
if battery < 0
[set battery 0]
if soc < 0
[set soc 0]
]
]
end
where, rem-term is same as remaining-ports and charging-status is same as charging?.
I tried adding the same code in the go-to-target function, since charging-status changes there first, but that didn't show any change in the results I'm getting.
I can't see anything obviously wrong with your code. This sort of thing usually happens because you have multiple ask turtles blocks, and you work out the intention in the first block but don't do the behaviour until the second block. In your case, I can see you updating the ports count in the first block, so that doesn't directly apply.
However, I wonder if you're doing something similar with your if statements, that turtles are going through different blocks than you expect and the relevant code is missing from the extract that you pulled out. The easiest way to diagnose this type of problem is with print statements. See below for one possibility.
ask adopters
[ if charging? and not marked?
[ ifelse remaining-ports > 0
[ type patch-here print remaining-ports
set remaining-ports remaining-ports - 1
set marked? true
type patch-here type "Updated ports" print remaining-ports
]
[ set occupied? true ]
]
if marked? and not charging?
[ set remaining-ports min list (remaining-ports + 1) terminals
set marked? false
set occupied? false
]
]
Note that I also changed your code for testing/updating number of remaining ports for clarity.
On your question about lists, there is no problem adding a turtle to a list (eg set queue lput self queue) but if you want more detail than that, please ask a separate question. I strongly recommend that you do not make any attempt to introduce queues for your ports until you have the existing code working properly.
In my model currently, I have a monitor on the Interface that counts the total number of turtles (deer in my case) every tick. Is it possible to have another monitor that counts the number of deer after a certain line of code is executed? For example, here's a snippet of code:
to catch-fawns-source
let fawn-hunting-rate (fawn-harvest-rate-source)
if any? fawns-on source-patches
[ ask fawns-on source-patches [
if random-float 1.0001 < (fawn-hunting-rate)
[ set harvest (harvest + 1)
set fawn-harvest (fawn-harvest + 1)
set source-harvest (source-harvest + 1)
die ] ]
]
end
In this case, this is where I have fawns being harvested. This code is the same for my male and female adult and juvenile deer. So is there a way I could track my population specifically after that snippet of code (and the other identical ones for the juveniles and adults) is executed?
I'm not sure if I would need any sort of Netlogo extension (if there are any applicable to this) or if I could somehow add in another global variable and lines of code that accomplishes this task.
Thanks for all of your help as always!
I think you can get away with another global variable that you just update however often you want. For a very simple example, consider this setup:
globals [ most-recent-pop-check ]
to setup
ca
crt 10
set most-recent-pop-check count turtles
reset-ticks
end
Here, most-recent-pop-check will only be updated when needed, then you can just set a monitor to display that variable. In this example, the value will only change every 25 ticks- see comments for more detail:
to go
ask turtles [
; Turtles may die
if random-float 1 < 0.25 [
die
]
; Throw in some density-dependence to control population size
if random-float 1 < ( 0.5 * ( 1 - ( count turtles / 500 ) ) ) [
hatch random 2 + 1
]
]
; If the ticks are not 0, and if the remainder after dividing
; the ticks by 0 is 0, update the most-recent-pop-check
; variable to reflect the current turtle population.
if ticks != 0 and ticks mod 25 = 0 [
set most-recent-pop-check count turtles
]
tick
end
Of course, in your case rather than having the update occur based on the number of ticks, just have it occur whenever you run the code chunk you're after.
I have created a network of agents where each agent has a GDP value and a GDP growth rate. The agents are interconnected with undirected links.
I have made a countdown that every 200 ticks randomly assign a 'shock status' to 10 agents. When an agent is under shock it gets the value 'in-crisis? = true' and consequentially its GDP growth rate changes.
However, I want to add a second trigger. I want agents with the 'in-crisis? = false' to check their link-neighbors and see if any of them have 'in-crisis? = true'. If they are linked to an agent whose in-crisis is true, then they should check if their own GDP is smaller than half of the GDP of the linked state that has 'in-crisis? = true'. If it is smaller, then the agent will set his own 'in-crisis?' as true.
to shock
if ticks mod 200 = 0 [ ;; This is the countdown
spread-crisis
ask n-of 10 turtles [
become-in-crisis]
]
end
to spread-crisis ;;;;;;;;;;;;;;;; This is the second trigger. I need help here!
ask turtles with [in-crisis? = false]
[ if any? link-neighbors with [in-crisis? = true] [
if any? link-neighbors with [gdp > my-gdp] [
become-in-crisis ] ]]
end
to-report my-gdp
report (gdp * 2)
end
to become-in-crisis
set in-crisis? true
let random-years-of-shock 20 + random 100
set shock-tick random-years-of-shock
end
If you have time, please help me to adjust the spread-crisis procedure!
Thank you
Change my-gdp to [my-gdp] of myself.
to spread-crisis
ask turtles with [not in-crisis?] [
if any? link-neighbors with [in-crisis? and gdp > [my-gdp] of myself] [
become-in-crisis
]
]
end
I'm totally new to NetLogo, and am trying to create an agent-based reinforcement learning (RL) model. I have recreated a toy model to get help on.
Here, one agent is doing RL by interacting with two agents, one of whom is unreliable (and so interactions with this agent ARE NOT reinforced), and another which is reliable (and so interactions with this agent ARE reinforced).
But I keep getting the error: Extension exception: No urn specified
So, clearly, I need to figure out how to specify urns!
The project folder is available for you to checkout at: http://bit.ly/1m8TAxq
Bellow is the minimal, complete, verify code is as follows (though you will need the URN extension in the linked dropbox folder above to do so).
Any help would be tremendously appreciated.
extensions [ urn ] ;; the urn extension that contains the RL functions
breed [ agents agent ]
globals [ ;; Global variables
A1 ;; urn-ball name of agent 1 (RED)
A2 ;; urn-ball name of agent 2 (GREEN)
]
agents-own [ ;; Values assigned to each agent
main-urn ;; Name of the Polya urn used in RL
interactionPartner ;; Variable tracking who the learner is interacting with
knowledgeState ;; Variable tracking whether the learner knows the truth after each interaction
]
to setup ;; Setup the stage
clear-all
reset-ticks
setup-agents ;; Sets up the agents
end
to have-agents-setup-urns ;; Setting up agent polya urns for reinforcement learning (by observer)
ask agent 0 [
set main-urn urn:make-polya-urn initial-weight (list A1 A2)
;; There are two types of balls in the urn: A1, A2 corresponding to the two possible agents with whom the chooser may interact
]
end
to setup-agents ;; Setting up the agents in the population (by observer)
create-agents 3 [
setxy (-6 * cos ( who * 360 / population-size)) (12 * sin (who * 360 / population-size))
set shape "circle"
set size 4
]
ask agent 0 [ ;; This is the agent doing the reinforcement learning (BLUE)
set color [0 0 255 175]
]
ask agent 1 [ ;; This is the unreliable agent (RED)
set knowledgeState 0
set color [255 0 0 175]
]
ask agent 2 [ ;; This is the reliable agent (GREEN)
set knowledgeState 1
set color [0 255 0 175]
]
end
to step ;; The step function
ask turtles [do-game-play]
tick
end
to go ;; The go function simply calls step continuously
step
end
to do-game-play ;; The game play function (by observer)
ask agent 0 [
set interactionPartner urn:draw-ball main-urn ;; Draw from the agent urn to figure out with whom to interact.
if (interactionPartner = A1) [
set knowledgeState ( 0 ) ;; If the interactionPartner is agent 1 (who is unreliable), then set agent 0 knowledge state to 0.
]
if (interactionPartner = A2) [
set knowledgeState ( 1 ) ;; If the interactionPartner is agent 2 (who is reliable), then set agent 0 knowledge state to 1, and reinforce.
urn:reinforce main-urn A2 1
]
]
end
how to set the value of 1st turtle when comparing 2 turtles value in nested if like we have attribute age in turtles now if age of turtle 1 is greater then 20 then check age of turtle 2 in side the nested if of first if if the inner if condition true then set the value of age of turtle 1 here is the code example
let i 0
let j 0
let node1 one-of turtles
let node2 one-of turtles
;; initialize the distance lists
while [i < number-of-nodes]
[
set j 0
while [j < number-of-nodes]
[
set node1 turtle i
set node2 turtle j
;; zero from a node to itself
if i != j
[
ask node1
[
if value = 0
[
ask node2
[
if value = 0 [
; here what i do so i can set the value of node1
]
]
]
]
set j j + 1
]
set i i + 1
]
you can directly set the value with
ask node1 [set value XXX]
However, you might want to reconsider the approach. At the beginning you have let node1 one-of turtles which randomly selects a turtle to be node1. But then you are overriding this assignment with loops to select specific turtles to be node1 and node2 that are nominated by your indices i and j. Using such an index relies on the turtles actually having who numbers that are from 0 to number-of-nodes - 1. Relying on who numbers instead of using agentsets (or lists) is likely to lead to problems later on, because it will only work if you create all your node turtles before creating anything else that uses a who number, and never create (or delete) others.