How do I create a global variable in NetLogo to monitor a specific turtle breed? - global-variables

I am using NetLogo to create an age-structured model of disease transmission. I have multiple turtle breeds - e.g., [persons1 person1], [persons2 person2], etc. - in which their disease state is described by the agent variable, state (e.g., state 1 is susceptible, state 2 is infected, state 3 is hospitalized, etc.). Each breed becomes infected at different rates and so I created a global variable, hospitalizations, that I am using to monitor the number of turtles who transition from infected to hospitalized at each timestep. For example:
ask turtles [
state 2
if random_float 1 < lambda [
set state 3
set hospitalizations hospitalizations + 1
]
]
However, I would like to create distinct global variables of hospitalizations for each breed to monitor the number of persons within each breed that transition to hospitalized - e.g., hospitalizations1 for persons1, hospitalizations2 for persons 2, etc.. Rather than copying the lines of code above for each breed [e.g., ask persons1...set hospitalizations1 hospitalizations1 + 1], is there another way to do this without modifying ask turtles? For instance, something like: set hospitalizations1 hospitalizations1 + 1 if persons1 = TRUE?
Any suggestions would be appreciated. Thank you.

I assume your breeds (persons1 and persons2) have turtle properties called state and the state will stay at state 3 as long as it is hospitalized. If that is the case, then I think you don't even need a global variable hospitalizations. Instead, you can monitor all of your turtles or a specific breed using count command like this :
;to count all breed
count turtles with [state = 3]
;counting specific breed
count persons1 with [state = 3]
count persons2 with [state = 3]

Related

R: Optimally Sharing Cookies Within Groups of Friends

I am working with the R programming language.
Suppose there are 100 people - each person is denoted with an ID from 1:100. Each person can be friends with other people. The dataset can be represented in graph/network format and looks something like this:
# Set the seed for reproducibility
set.seed(123)
# Generate a vector of ID's from 1 to 100
ids <- 1:100
# Initialize an empty data frame to store the "from" and "to" values
edges <- data.frame(from=integer(), to=integer(), stringsAsFactors=FALSE)
# Iterate through the ID's
for(id in ids) {
# Randomly select a minimum of 1 and a maximum of 8 neighbors for the current ID
neighbors <- sample(ids[ids != id], size=sample(1:8, size=1))
# Add a new row to the data frame for each "to" value
for(neighbor in neighbors) {
edges <- rbind(edges, data.frame(from=id, to=neighbor))
}
}
As we can see, the data can be visualized to reveal the graph/network format:
library(igraph)
library(visNetwork)
# Convert the data frame to an igraph object
g <- graph_from_data_frame(edges, directed=FALSE)
# Plot the graph
plot(g)
# Optional visualization
#visIgraph(g)
Now, suppose each person in this dataset has has a certain number of cookies. This looks something like this:
set.seed(123)
cookies = data.frame(id = 1:100, number_of_cookies = c(abs(as.integer(rnorm(25, 15, 5))), abs(as.integer(rnorm(75, 5, 5)))))
Here is my question:
I want to make sure that no person in this dataset has less than 12 cookies - that is, if someone has less than 12 cookies, they can "pool" together their cookies with their neighbors (e.g. first-degree neighbors, second-degree neighbors, ... n-th degree neighbors ... until this condition is satisfied) and see if they now have more than 12 cookies
However, I also want to make sure that during this pooling process, no pooled group of friends has more than 20 cookies (i.e. this might require having to "un-pool" neighbors that were previously pooled together)
And finally, if someone is in a group with some other people - this person can not be then placed into another group (i.e. no "double dipping")
I wrote a function that takes an ID as an input and then returns the total number of cookies for this ID and all of this ID's neighbors:
library(data.table)
library(dplyr)
sum_cookies_for_id <- function(id) {
# Get the connected IDs for the given ID
connected_ids <- c(id, edges[edges$from == id | edges$to == id, "to"])
# Sum the number of cookies for all connected IDs
sum(cookies[cookies$id %in% connected_ids, "number_of_cookies"])
}
# Test the function
sum_cookies_for_id(23)
But beyond this, I am not sure how to continue.
Can someone please show me how I might be able to continue writing the code for this problem? Can Dynamic Programming be used in such an example?
Thanks!
Notes:
I think that this problem might have a "stochastic" nature - that is, depending on which ID you begin with and which other ID's you group this specific ID with ... might eventually lead to fewer or more people with less than 12 cookies
I think that writing a "greedy" algorithm that performs random groupings might be the easiest option for such a problem?
In the future, I would be interested in seeing how more "sophisticated algorithms" (e.g. Genetic Algorithm) could be used to make groupings such that the fewest number of people with less than 12 cookies are left behind.
Food for Thought: Is it possible that perhaps some pre-existing graph/network clustering algorithm could be used for this problem while taking into consideration these total/sum constraints (e.g. Louvain Community Detection)?

Markov Chain Adjusting Initial State Vector to Solve For Desired Vector Element

I'm trying to increase the initial state vector in a discrete Markov chain at each step in order to solve for a state vector element at some future point time, and it seems to be quite cumbersome.
For a simple example, assume a corporation has an initial state vector comprised of entry level employees with 3 transition states of (entry level, promotion, quit company). The initial state vector with 1000 entry level employees is defined as:
initialstate <- t(as.matrix(c(1000,0,0)))
The transition matrix for remaining entry level, getting promoted, or leaving the company is given by:
transitionmatrix <- matrix(c(0.5,0,0,0.2,1,0,0.3,0,1),nrow = 3,ncol = 3)
After two iterations:
step1state <- initialstate%*%transitionmatrix
(500 entry level employees remaining)
step2state <- step1state%*%transitionmatrix
(250 entry level employees remaining)
After step2state, I have 250 entry level employees remaining, but suppose I want 1,300 entry level employees after Step 1 and 2,000 entry level employees after Step 2. To do this, I hire additional employees by increasing the state vectors. This now becomes a cumbersome process where I increase the initialstate matrix to account for new hires in Step 1, observe the number of entry level employees in Step 2, and then increase step1state to achieve the Step 2 target.
For example, after running the previous Markov chain, I run it again and add 800 new hires in Step 1:
step1state <- initialstate%*%transitionmatrix + t(as.matrix(c(800,0,0)))
step2state <- step1state%*%transitionmatrix
Step 1 has 1,300 entry level employees as desired, but Step 2 now needs 1,350 entry level employees hired (down from 1,750 in the initial run). The following satisfies my hiring targets in each period:
step1state <- initialstate%*%transitionmatrix + t(as.matrix(c(800,0,0)))
step2state <- step1state%*%transitionmatrix + t(as.matrix(c(1350,0,0)))
If my entry level employee target changes at any step, I have to re-run the markov chain for every step afterward because the number of entry level employees depends on the number of employees in previous periods (but the transition probabilities do not). The MarkovChain package in R didn't seem to be able to solve the state vector for specific values at each step, so I'm simply running a baseline Markov Chain and iteratively adding new employees to each initialstate vector to get the target I want at each step.
Is there a better way to do this? Is a Markov Chain the right choice of model for what I'm trying to achieve?
I'm not sure what you mean by "Is a Markov Chain the right choice of model for what I'm trying to achieve?", because I don't actually understand what you are trying to achieve, nor is it entirely clear what you mean by a "Markov Chain" although I'm guessing you want to iterate a series of "Markov" transitions from an initial state vector. For a starting vector state of 1000 new hires the state after n iterations will be:
library(expm)
initialstate %*% (transitionmatrix %^% n)
The expm-package implements a matrix exponential operator %^% which allows you to calculate in one step the outcomes of n iterations of a Markov transition matrix.
So after 25 iterations there will be:
> initialstate %*% (transitionmatrix %^% 25)
[,1] [,2] [,3]
[1,] 2.980232e-05 400 600
.... 400 promoted individuals and 600 "leavers". This is all linear, so if you started with 2000 you would then have 800 and 1200 in those states respectively. And it's not surprising that their ratio is 2:3 since that is also the ratio for the numbers making the transition due to the second and third elements of the first column. Note that the 1's in the diagonal for columns 2 and 3 make those "absorbing states". Once you are "promoted" you will remain promoted. There is no exit. Just like Hotel California if you're an Eagles fan. Once you "leave", there's also no return possible.

Choco solver shift scheduling

i m a total beginner in Choco Solver. I want to make a simple shift scheduler.
i have set integer variables like this
IntVar day1 = model.intVar("day1", new int[] {0,1,2,3,4,5});
where 0 , 1,...5 is a reference ID to an employee.
I have a total of 30 variables,(one for every day of the month) since this a monthly based shift schedule.
I have set up constraints, that do not allow e.g. not be on shift for two days in a row.
My question is,
how can i set up a constraint, such that each employer has a minimum of 5 shifts ie. each value in the domain appears at least 5 times in all 30 variables ?
Thank you!
There are several ways of doing this. Give a look at model.globalCardinality and model.count, these constraints enable to count the number of times a value is used by a set of variables.
http://choco-solver.org/apidocs/org/chocosolver/solver/constraints/IConstraintFactory.html
For instance, model.count(3, vars, model.intVar(5,10)).post(); means that between 5 and 10 variables in vars should be equal to 3, so employee 3 should do between 5 and 10 shifts.

Differences in turtle-per-patch fillup in even and odd scenarios?

I'm new at netlogo, and in my model, I'm trying to make it so there's one turtle per patch, so that all the patches are filled up with one turtle instead of them overlapping each other. The code for that part of the model is
to solid
set color blue
set xcor random sqrt number-of-particles - number-of-particles / 2
set ycor random sqrt number-of-particles - number-of-particles / 2
ifelse any? patches with [pcolor = black and count turtles-here = 0]
[move-to one-of patches with [pcolor = black and count turtles-here = 0]]
[die]
end
I've been trying it out with different variables, but it works for odd "Volume" (amount of patches in each row) but not the even ones.
(even numbered one) Link 1
(odd numbered one) Link 2
how would i make it so that it works for both odd and even numbers? thanks!
This is my full setup code. Sorry that I posted them in my comments, this is my first time on stackoverflow.
to Setup-Container
ca
cro 4
[set color black
rt 45
fd Volume * sqrt 2 / 2
rt 135
pd
set pen-size 6
fd Volume
die
]
ask patches
[ifelse pxcor <= Volume / 2 and pxcor >= Volume / 2 * -1
and pycor <= Volume / 2 and pycor >= Volume / 2 * -1
[set pcolor black] [set pcolor black + 3]
]
end
; Creates a number of particles, which depends on the corresponding slider.
; Executes certain commands depending on the temperature slider.
to Setup-Particles
ask turtles
[die]
cro number-of-particles
ask turtles [
set shape "water"
if Temperature <= 0 ; freezing point is 0 degrees celsius.
[ice-cube]
if Temperature > 0 and Temperature < 100
[water]
if Temperature >= 100 ; boiling point is 100 degrees celsius.
[water-vapor]
]
end
There's actually a primitive that just creates a turtle on a given patch: sprout. So, ask patches [ sprout 1 ] would create one turtle on each patch.
Bryan's answer is most probably the right one, here: if your main requirement is to have one turtle per patch, sprout is the way to go.
A few more comments:
In the screenshots you've shown us, you control your "volume" and your number of particles separately, so there is aways a chance that your container will be either too big or too small for the number of particles you want. If you really want a one-to-one relationship between the size of your container and the number of particles, you should really have a single parameter for both.
sprout allows you to give commands to the newly created turtles. If you don't want them to be "rainbow colored", you can do: ask patches with [pcolor = black] [sprout 1 [set color blue]].
In your original code, you set the xcor and the ycor of your turtles... and then immediately move them. The point will be moot if you use sprout, but I wanted to point out that these two lines were unnecessary.
If you still have trouble with sprout, I'd suggest you ask a separate question and show us what you tried. We may able to help you...

Create teams of 2-people according to players preferences

Goal
Imagine a even number of individuals that have to create teams of two people. Each individual has to call a R function and enter two parameters; 1) Their own name and 2) the names of the other individuals in the order of their preference. When everyone has voted a function extracts the best combination of teams. The goal is to construct this function.
Example
John, Peter, Mary and Jessica need to construct teams of two people. John preferentially wants to be with Peter, moderatly with Mary and would prefer not be with Jessica. Therefore John enters the following code line:
Create_binom(MyName='John', Preferences = c('Peter', 'Mary', 'Jessica'))
The three other players do the same, they enter their names and their preferences:
Create_binom(MyName='Mary', Preferences = c('Peter', 'Jessica', 'John'))
Create_binom(MyName='Peter', Preferences = c('John', 'Jessica', 'Mary'))
Create_binom(MyName='Jessica', Preferences = c('Mary', 'John', 'Peter'))
At the last call (when the last player called the function entering its name and preferences), the function recognizes that all players have indicated their preferences and the function create the best combinations of 2-people teams and print it. The best combination is defined as the combination that minimizes the sum of the positions of the teammates in the preferences of all players. We'll call this sum the "index" of the combination.
Index of a combination
The combination (John with Mary) and (Peter with Jessica) has associated index 2 + 3 + 2 + 3 = 10.
The combination (Mary with Jessica) and (Peter with John) has associated index 1 + 1 + 2 + 1 = 5. With this combination only one player (Mary) will not play with her best friend! It is the best possible solution in my example.
Of course, in a perfect world, everybody would be associated with his/her best friend and the index of the perfect combination would equal the number of players, but this is often not possible.
Output of the example (Best combination for the example)
Here is what the function should print out:
list(c("Peter", "John"),c("Mary", "Jessica"))
...or any of the 8 equivalents results.
Special case
Of course if there are several best combinations, then the function should just pick one of the best combination at random.

Resources