Netlogo random values for list bounded by values - list

For my graduation project I am investigating the electricity consumption of occupants in officebuildings. Occupants when arriving at office they can leave their work desk doing other activities (e.g. lunch, meetings, restroom). Each occupant has his own time when going to office and when going home.
What I want is that occupants determine when they leave workdesk randomly distributed between going to office and going home.
to go
if time = 0 [start-day]
ask occupants [
let $currenttime hour-of-day
ifelse (go-to-office-today AND (workDays = "M-F" AND (Day >= 0) AND (Day
<= 4) AND ($currenttime * 100 >= workStartHour ) AND ($currenttime * 100
<= workEndHour - 100 )))
[if (not atWork?) [GoWork] ]
[if (atWork?) [GoHome] ]
if go-to-office-today and workschedule-next < length workschedule [
let workschedule-item item workschedule-next workschedule
]]
tick
to start-day
ask occupants [ set schedule-next 0
set go-to-office-today false
]
let $Occupancy-Percentage (50 + random 0)
ask n-of( int ($Occupancy-Percentage / 100 * count occupants)) occupants [
set go-to-office-today true
set workschedule [ ]
]
DetermineWorkSchedule
setMeetingSchedule
end
now i have only one fixed value for the list. But i want several normally distributed between workstarthour and workendhour (e.g between 10 and 90 ticks)
to go to restroom frequencie will be 4 times then i want the list to be workschedule [ 15 28 51 73 ]
to DetermineWorkSchedule
ask occupants [
let lunchtime [ ]
set lunchtime lput precision (random-normal 12 1 ) 0 lunchtime
set workschedule lput one-of lunchtime workschedule
let toilettime []
set toilettime lput precision (random-normal 15 2) 0 toilettime
set workschedule lput one-of toilettime workschedule
end

Since you now say you just want a n stochastic values between two endpoints without any distributional constraint, you could do this:
to-report transition-times [#n #start #end]
let _possible n-values (#end - #start + 1) [#start + ?]
report sort n-of #n _possible
end
This will give you values in [#start,#end] -- that is, including #start and #end. (Adjust to taste.) Values are constrained to be unique.

Related

Latest values by category based on a selected date

First, as I am a French guy, I want to apologise in advance for my poor English!
Despite my searches since few days, I cannot find the correct measure to solve my problem.
I think I am close to the solution, but I really need help to achieve this job!
Here is my need:
I have a dataset with a date table and a "Position" (i.e. "stock") table, which is my fact table, with date column.
Classic relationship between these 2 tables. Many Dates in "Position" table / 1 date un "Dates" table.
My "Dates" table has a one date per day (Column "AsOf")
My "Deals" table looks like this:
Id
DealId
AsOfDate
Notional
10000
1
9/1/2022
2000000
10001
1
9/1/2022
3000000
10002
1
9/1/2022
1818147
10010
4
5/31/2022
2000000
10011
4
5/31/2022
997500
10012
4
5/31/2022
1500000
10013
4
5/31/2022
1127820
10014
5
7/27/2022
140000
10015
5
7/27/2022
210000
10016
5
7/27/2022
500000
10017
5
7/27/2022
750000
10018
5
7/27/2022
625000
10019
1
8/31/2022
2000000
10020
1
8/31/2022
3000000
10021
1
8/31/2022
1801257
10022
1
8/31/2022
96976
10023
1
8/31/2022
1193365
10024
1
8/31/2022
67883
Based on a selected date (slicer with all dates from "Dates" table), I would like to calculate the sum of Last Notional for each "Deal" (column "DealId").
So, I must identify, for each Deal, the last "Asof Date" before or equal to the selected date and sum all matching rows.
Examples:
If selected date is 9/1/2022, I will see all rows, except rows asof date = 8/31/2022 for deal 1 (as the last date for this deal is 9/1/2022).
So, I expect to see:
DealId Sum of Notional
1 6 818 147
4 5 625 320
5 2 225 000
Grand Total 14 668 467
If I select 8/31/2022, total for Deal 1 changes (as we now take rows of 8/31 instead of 1/9):
DealId Sum of Notional
1 8 159 481
4 5 625 320
5 2 225 000
Grand Total 16 009 800
If I select 7/29, only deals 4 and 5 are active on this date, so the results should be:
DealId Sum of Notional
4 5 625 320
5 2 225 000
Grand Total 7 850 320
I think I found a solution for the rows, but my total is wrong (only notionals of the selected date are totalized).
I also think my measure is incorrect if I try to display the notional amounts aggregated by Rating (other column in my table) instead of deal.
Here is my measure:
Last Notional =
VAR SelectedAsOf =
SELECTEDVALUE ( Dates[AsOf] )
VAR LastAsofPerDeal =
CALCULATE (
MAX ( Deals[AsOf Date] ),
FILTER ( ALLEXCEPT ( Deals, Deals[DealId] ), Deals[AsOf Date] <= SelectedAsOf )
)
RETURN
CALCULATE (
SUM ( Deals[Notional] ),
FILTER (
ALLEXCEPT ( Deals, Deals[DealId]),
LastAsofPerDeal = Deals[AsOf Date]
)
)
I hope it is clear for you, and you will be able to find a solution for this.
Thanks in advance.
Antoine
Make sure you have no relationship between your calendar table and deals table like so.
Create a slicer with your dates table and create a table visual with deal id. Then add a measure to the table as follows:
Sum of Notional =
VAR slicer = SELECTEDVALUE(Dates[Date])
VAR tbl = FILTER(Deals,Deals[AsOfDate] <= slicer)
VAR maxBalanceDate = CALCULATE(MAX(Deals[AsOfDate]),tbl)
RETURN
CALCULATE(
SUM(Deals[Notional]),
Deals[AsOfDate] = maxBalanceDate
)

How to ask for a specific share of turtles with a minimum share of a value?

I've set up firms (turtles) in an industry (world) which either produce at home (firms-at-home located > ycor) or have offshored their production (offshore-firms located < ycor). I have given them a firms-own called offshored? which is answered with either true or false. At setup, they also get a firms-own firm-level-of-automation which is random between 0 and 1.
Now, I would like to have 30 % of them with the lowest firm-level-of-automation to move production to < 0 ycor and report: offshored? = true
breed [ firms firm ]
firms-own [
firm-level-of-automation ;; initially random between 0 and 1
offshored? ;; true or false
]
to go
tick
ask firms [
set firm-level-of-automation 0 + random-float 1
if min [ firm-level-of-automation ] of firms [
count firms * 0.3 firms [ setxy random-xcor random-between ( -10 ) -1 ;; distribute randomly abroad in an area < 0 ycor
set offshored? true ] ] ]
end
I don't know how to mix the if and min command best here. Any suggestions?
Not sure why you are being down voted for this, it seems like a sensible question. Anyway, there is no need to mix min and if, you can simply ask the 30% of turtles with the lower values to do what you want. Look up the min-n-of primitive in the dictionary, you will want something like:
ask min-n-of (0.3 * count firms) firms [firm-level-of-automation]
[ setxy random-xcor random-between ( -10 ) -1
set offshored? true
]

Percent Retention

I am trying to create a "Percent Retention" for policies during a given time period ( By month, YTD and year over year) . So all of the policies at a given time period compared to those active at the end of the period.
Policies can be:
N=New
RN=ReNew
C=Cancel
RI=ReInstate
NR=NonRenew
Transaction data kinda looks like this, the StatusNum is something I can derive to show inforce status.
PolicyID PolicyNum StatusDate Status StatusNum Net
1 123 1/1/2018 N 1 1
2 123 3/31/2018 C 0 -1
3 123 4/1/2018 RI 1 +1
4 123 6/1/2018 RN 1 0
5 222 2/1/2018 N 1 1
6 222 7/1/2018 RN 1 0
7 333 1/1/2018 N 1 1
8 333 6/1/2018 NR 0 -1
9 444 1/1/2018 N 1 1
10 444 5/30/2018 C 0 -1
My best guess on how to do this is to take the sum of the last StatusNum values at a PIT (partitioned by Policy Number) divided by the first StatusNum value at the beginning PIT. So if I filter by dates 1/1/2018 to 8/1/2018
123 will be in force (+1,+1)
222 will not be in force yet(so not counted for anything) (+0,+0)
333 was in force at the beginning, but it non renewed (+1,-1)
444 was in force at the beginning, but it cancelled (+1,-1)
So 3 of the policies were active at 1/1/2018 and 2 cancelled, 1 doesn't matter so the retention would be 33.3%
Can anyone offer feedback if this is the best way to do this and how to accomplish this?
Thank you in advance for your assistance.
Update
This is kinda what I am looking for, but it is too slow:
'AsOfPolicies =
var A= SELECTCOLUMNS(SUMMARIZECOLUMNS(Transactions[PolicyNumber], filter( Transactions,Transactions[DateKey]=min(Transactions[DateKey])&&Transactions[IsInForce]=-1) ),"aPolicyNumber", [PolicyNumber])
var B=SELECTCOLUMNS(SUMMARIZECOLUMNS(Transactions[PolicyNumber], filter( Transactions,Transactions[DateKey]<=MAX(Transactions[DateKey]) ),"MaxDate",MAX(Transactions[DateKey]) ),"bPolicyNumber",[PolicyNumber],"MaxDate",[MaxDate]) var C = SELECTCOLUMNS(filter(CROSSJOIN(A,B),[aPolicyNumber]=[bPolicyNumber]),"cPolicyNumber",[aPolicyNumber],"MaxDateKey",[MaxDate])
Var D = SELECTCOLUMNS(filter(CROSSJOIN(C,Transactions),[cPolicyNumber]=[PolicyNumber] && [MaxDateKey]=[DateKey]),"PolicyNumber",[PolicyNumber],"PD_ID",[PD_ID],"IsInForce",[IsInForce])
Return D'
Update
Also the filter does not appear to be working
I think you can do something like this:
Retention =
VAR StartDates =
SUMMARIZE (
ALLSELECTED ( PolicyLog ),
PolicyLog[PolicyNum],
"Start", MIN ( PolicyLog[StatusDate] )
)
VAR Included =
SELECTCOLUMNS (
FILTER ( StartDates, [Start] <= MIN ( Dates[Date] ) ),
"Policies", PolicyLog[PolicyNum]
)
VAR Filtered = FILTER ( PolicyLog, PolicyLog[PolicyNum] IN Included )
RETURN
DIVIDE (
SUMX ( Filtered, PolicyLog[Net] ),
COUNTROWS ( SUMMARIZE ( Filtered, PolicyLog[PolicyNum] ) )
)
First, you create a table, StartDates, that gives the earliest dates for each policy limited to the time frame you have selected. It would look something like this:
StartData =
PolicyNum Start
123 1/1/2018
222 2/1/2018
333 1/1/2018
444 1/1/2018
From there, we just want a list of which policies we want to include in the calculation. So we pick the ones that have a Start on the minimum selected date in the date slicer. We just want a list of the resulting policy numbers, so we just select that column.
Included =
Policies
123
333
444
From there we filter the whole PolicyLog table to just include these ones (Filtered).
Finally, we can add up the Net column for each of these selected policies and divide by the distinct count of them to get our retention percentage.
Edit: In response to your comment, I think you want to be a bit more selective with the StartDate variable. Instead of MIN( PolicyLog[StatusDate] ), try something more like this:
CALCULATE( MIN(PolicyLog[StatusDate]), PolicyLog[Status] IN {"N", "RN", "RI"} )

Netlogo missing inconsistent results when iterating through a list of ~ 6K lists

I'm setting up patches from values read from a file. The values are in a list of lists:
[[10001 53 1 2 160 4 4 4 1] [10004 69 1 2 143 4 4 4 2] [10005 70 2 2 135 3 3 4 2] [10006 51 2 2 132 4 4 3 3] ... ]
Each "internal" list has the values for the properties of a patch.
The value in position 2 (I'm counting from 0 for the first value) represents gender:
1=male, 2=female.
My procedure:
to setup-patches-as-agents [ patches-data ]
set male-count 0
set female-count 0
set total-rows 0
foreach patches-data [
[ one-row ] ->
ask patches with [ pxcor = random-pxcor and pycor = random-pycor]
[ set total-rows total-rows + 1
;; add values to patch properties
;; **** id ****
set p-midus_id item 0 one-row
;; **** age *****
set p-age item 1 one-row
;; gender 1= MALE; 2= FEMALE; 7= DON'T KNOW; 8= REFUSE
set p-gender item 2 one-row
if item 2 one-row = 1 ;; male
[ set pcolor blue
set male-count male-count + 1 ] ;; male
if item 2 one-row = 2 ;; female
[ set pcolor orange
set female-count female-count + 1 ] ;; female
;; **** lose10lb ****
set p-lose10lb item 3 one-row
;; **** weightYrAgo ****
set p-weightYrAgo item 4 one-row
;; **** limitLiftCarryGroceries ****
set p-limitLiftCarryGroceries item 5 one-row
;; **** limitClimbingStairs ****
set p-limitClimbingStairs item 6 one-row
;; **** limitWalkingSeveralBlocks ****
set p-limitWalkingSeveralBlocks item 7 one-row
;; **** limitWalkingSeveralBlocks ****
set p-limitWalkingSeveralBlocks item 8 one-row
]
]
type "male-count: "
print male-count
type "female-count: "
print female-count
type "total-count: "
print total-rows
end
The total number of rows read is: 6325 (output after reading the file, which matches the number of rows in the file
Total number of Males should be: 3004, and for females: 3321. The count I get with those variables changes, including the total number of "rows"
Any idea why??
Glad you figured out a workaround! Just to give my two cents, I think your solution points to the likely issue with your first code- your
ask patches with [ pxcor = random-pxcor and pycor = random-pycor]
did not remove patches with assigned values from the pool of patches- that is to say you could have a patch be chosen multiple times, and so its initial values would be overwritten every time it was chosen. Since in your turtles solution you create a new turtle for each row, there is no overwriting happening.
If you need it to be patches instead of turtles, you can change your with statement to something that only selects patches that have not had values assigned yet. For example (assuming your setup does not previously set p-gender), you could take advantage of the fact that all declared variables are by default set to 0 until they are changed in code and change your original code to something like
...
foreach patches-data [
[ one-row ] ->
ask one-of patches with [ p-gender = 0 ] [
...
In the same pass you can just use one-of rather than manually choosing a random pxcor and pycor- it's simpler I think.
Additionally, and this is obviously up to you, instead of manually incrementing your counter for male and female, you might want to just set up a to-report procedure that monitors those for you. For example, if you have this in your code:
to-report male-turtle-count
report count turtles with [ gender = 1 ]
end
and then you print male-count (or use a monitor on the interface), it will show you the number of turtles that currently have a gender of 1. This dynamically updates so you don't have to keep track of a counter.
I switched to turtles and setup all properties, including initial coordinates and now I'm getting the right counts. I suspect that the condition for the coordinates to select a patch might be an issue, but I'm not sure. Anyway, here's my solution:
to setup-turtles [ turtles-data ]
foreach turtles-data [
[ one-row ] ->
crt 1 [
set shape "square"
setxy random-xcor random-ycor
set size 2
;;(item 0 one-row) and ycor = (item 1 one-row) ] [
;; **** id ****
set midus_id item 0 one-row
;; **** age *****
set age item 1 one-row
;; gender 1= MALE; 2= FEMALE; 7= DON'T KNOW; 8= REFUSE
set gender item 2 one-row
if item 2 one-row = 1 ;; male
[ set color blue ] ;; male
if item 2 one-row = 2 ;; female
[ set color orange ] ;; female
;; **** lose10lb ****
set lose10lb item 3 one-row
;; **** weightYrAgo ****
set weightYrAgo item 4 one-row
;; **** limitLiftCarryGroceries ****
set limitLiftCarryGroceries item 5 one-row
;; **** limitClimbingStairs ****
set limitClimbingStairs item 6 one-row
;; **** limitWalkingSeveralBlocks ****
set limitWalkingSeveralBlocks item 7 one-row
;; **** physicalFitnessCompared5YrAgo ****
set physicalFitnessCompared5YrAgo item 8 one-row
]
]
end

Netlogo turtles need to move same time at two different target location

Sorry, I am yet beginner with Netlogo programming i am trying to
schedule the jobs on machine based on their priority.
At the moment only product1 turtle is process by one machine turtle.
While other products turtles are not been run on the machines which
are idle e.g machine2 and machine3. Currently they are waiting for
the other loop to finish to process the next.
What i want to achieve is Product1 needs only Machine1 for operation.
while P2 needs M2 and M3, P3 needs M1,M2 and M3. So when Product1
turtles are on M1, other turtles should move to their corresponding
targets and schedule themselves
breed [product1 productA]
breed [product3 productB]
breed [product2 productC]
breed [machine1 machineA]
breed [machine2 machineB]
breed [machine3 machineC]
breed [schedulers scheduler]
globals [Priority]
product1-own
[
productID
productLength
arriveTime
startTime
finishTime
]
product2-own
[
productID
productLength
arriveTime
startTime
finishTime
waitTime
]
product3-own
[
productID
productLength
arriveTime
startTime
finishTime
]
schedulers-own
[
numJobArrive
numJobStart
numJobFinish
numJobWait
currentmachineID
]
machine-own
[
machineID
numJobStart
numJobFinish
waitTimeM
idleTimeM
nextAvailTime
currentproductID
utilization
]
to setup
clear-all
ask patches [set pcolor 8]
ask patch -3 6 [set pcolor 125]
ask patch -3 2 [set pcolor 125]
ask patch 1 4 [set pcolor black]
setup-products1
setup-products2
setup-products3
setup-machines
reset-ticks
end
to setup-machines
create-machine1 1 [setxy -3 6
set shape "computer server"]
create-machine2 1[setxy -3 2
set shape "computer server"]
create-machine3 1[setxy 1 4
set shape "computer server"]
end
to setup-products1
create-product1 Job1-products [
set shape "hexagonal prism"
set color red
set size 1.25
set xcor -14
set ycor 6
set heading 90
separate-products
]
end
to setup-products2
create-product2 Job2-products [
set shape "die 4"
set color blue
set xcor -14
set ycor 4
set size 1.25
set heading 90
separate-products
]
end
to setup-products3
create-product3 Job3-products [
set shape "box"
set color brown
set size 1.25
set xcor -14
set ycor 2
set heading 90
separate-products
]
end
; this procedure is needed so when we click "Setup" we
; don't end up with any two Products on the same patch
to separate-products ;; turtle procedure
if any? other turtles-here
[ fd 1.5
separate-products ]
end
to go-product3
let totalprod (turtle-set product1 product2 product3)
let targetmachine1 patch -3 6
let targetmachine2 patch -3 2
let targetmachine3 patch 1 4
if count product3 > 0
[
ask one-of product3 [
if not any? product1-on machine1 or not any? product2-on machine1
[
move-to targetmachine1
]
if not any? product1-on machine2 or not any? product2-on machine2
[
face targetmachine2
move-to targetmachine2
]
if not any? product1-on machine3 or not any? product2-on machine3
[
face targetmachine3
move-to targetmachine3
die
]
]]
tick
end
to go-product2
let targetmachine1 patch -3 2
let targetmachine2 patch 1 4
if count product2 > 0
[
ask one-of product2 [
if not any? product1-on machine2 or not any? product3-on machine2
[
face targetmachine1
move-to targetmachine1
]
if not any? product1-on machine3 or not any? product3-on machine3
[
face targetmachine2
move-to targetmachine2
die
]
]]
tick
end
to go-product1
let targetmachine patch 1 4
if count product1 > 0
[
ask one-of product1
[
if not any? product2-on machine3 or not any? product3-on machine3
[
face targetmachine
move-to targetmachine
die
]
]]
tick
end
to go
let totalprod (turtle-set product1 product2 product3)
while [count totalprod > 0] [
if Priority = "0" [
go-product1
go-product2
go-product3
]
if Priority = "1" [
while [count product1 > 0][
go-product1 ]
go-product2
go-product3
]
if Priority = "2" [
while [count product2 > 0][
go-product2 ]
go-product1
go-product3
]
if Priority = "3" [
while [count product3 > 0][
go-product3 ]
go-product1
go-product2
]
]
tick
end
Take the calls to tick out of your individual go-product procedures. It only ever makes sense to call tick once in your entire model, and that's at the end of your main go procedure.
Remove the uses of while from your go procedure. Time will pass in your model because go is called over and over again in a forever button -- not because you have loops inside your go procedure. The forever button is looping enough.
The goal is to structure your model so that each time through go (which is to say one tick), only one unit of work or action or motion takes place. Then, as go runs over and over again, then longer units of work, that take multiple ticks to accomplish, will appear to take place concurrently.
Nearly every model in Sample Models, including the Tutorial 3 model, is structured this way. You should only have a different structure if you're absolutely sure you know what you're doing and why you're doing it.