Repeating the "go" cycle from scratch every 1000 ticks - time

I am working on a simplified model of the stock market, and I am still learning to manage time in NetLogo. In my model a day is made of 1000 ticks. In a day several things happen: turtles sell and buy stocks, at some point during the day they set their strategies, various logs are written and then erased at the end of the day.
I would like the model to start again after 1000 ticks, i.e. at the end of the day the model does not stop but starts again, thus simulating more than one single day.
What do you suggest?

Why not just use if ticks mod 1000 = 0 [setup-locations]

Related

Google Sheets Countdown Timer for Aircraft Flight Plan "Time Remaining"

I'm struggling with a formula in Google Sheets that will display a countdown for how much time remains until an aircraft is overdue, based on a filed flight plan.
What I have: 2 key pieces of information about a flight plan:
how much estimated time it will take to make the flight (ETE:
Estimated Time Enroute)
what time the aircraft departed (ATA: Actual Time of Departure)
Constraints: (mandated by company policy)
The ETE must be entered in decimal format, in numbers of hours. A 1hr 30min flight must have an ETE of 1.5, or a 20 minute flight must have an ETE of .3 (rounded to the nearest 10th).
The ATA must be entered in 4-digit 24hr time, but without the colon. 1:30pm must be entered as "1330"
The countdown timer must be displayed in minutes, rounded to the nearest whole number. 1hr 28min must be listed "88"
The countdown should be "live" (this is solved by spreadsheet settings to update "on update or every minute".
The countdown should easily indicate aircraft that have become "overdue" (this will be solved with conditional formatting to highlight negative numbers)
My pseudo formula is essentially just: Now() - (ETE+ATD), but I'm stuck on how to get around the constraints, specifically the three different time formats (decimal hours ETE, 4-digit 24hr time ATA, and remaining time in minutes).
I've set up a dummy sheet here:
https://docs.google.com/spreadsheets/d/165mXKRquI4aBEEap8PIHVrFpAraaapykGqjkDg22qeU/edit?usp=sharing
*I've looked through this Q&A, but it's a GAS solution. I'd much prefer to just have a formula. Preferably an array formula, so that it copies down to however many rows there might end up being.
**Possibly a secondary concern down the road: at the moment, we do not conduct overnight flights, but it's possible in the future. Starting a 3hr flight at 10pm will result in the arrival time being the next day. Hopefully, there is a solution for this.
I suggest some testing before use, but should be worth trying:
=if(now()>today()+1*(left(A2,2)&":"&right(A2,2)),round(24*60*(today()+1*(left(A2,2)&":"&right(A2,2))-now())+B2*60,0),"")
where the ATA value is in A2 and the ETE in B2.
Could be simplified but longer might be easier to adapt for overnight, if required.

How to Schedule Tasks

There is a carwash that can only service 1 customer at a time. The goal of the car wash is to have as many happy customers as possible by making them wait the least amount of time in the queue. If the customers can be serviced under 15 minutes they are joyful, under an hour they are happy, between 1 hour to 3 hours neutral and 3 hours to 8 hours angry. (The goal is to minimize angry people and maximize happy people). The only caveat to this problem is that each car takes a different amount of time to wash and service so we cannot always serve on first come first serve basis given the goal we have to maximize customer utility. So it may look like this:
Customer Line :
Customer1) Task:6 Minutes (1st arrival)
Customer2) Task:3 Minutes (2nd arrival)
Customer3) Task:9 Minutes (3rd)
Customer4) Task:4 Minutes (4th)
Service Line:
Serve Customer 2, Serve Customer 1, Serve Customer 4, Serve Customer 3.
In this way, no one waited in line for more than 15 minutes before being served. I know I should use some form of priority queue to implement this but I honestly know how should I give priority to different customers. I cannot give priority to customers with the least amount of work needed since they may be the last customer to have arrived for example (others would be very angry) and I cannot just compare based on time since the first guy might have a task that takes the whole day.So how would I compare these customers to each other with the goal of maximizing happiness?
Cheers
This is similar to ordering calls to a call center. It becomes more interesting when you have gold and silver customers. Anyway:
Every car has readyTime (the earliest time it can be washed, so it's arrival time - which might be different for each car) and a dueTime (the moment the customer becomes angry, so 3 hours after readyTime).
Then use a constraint solver (like OptaPlanner) to determine the order of the cars (*). The order of the cars (which is a genuine planning variable) implies the startWashingTime of each car (which is a shadow variable), because in your example, if customer 1 is ordered after customer 2 and if we start at 08:00, we can deduce that customer 1's startWashingTime is 08:03.
Then the endWashingTime is startWashingTime + washingDuration.
Then it's just a matter of adding 2 constraints and let the solver solve() it:
endWashingTime must be lower than dueTime, this is a hard constraint. This is to have no angry customers.
endWashingTime must be lower than startTime plus 15 minutes, this is a soft constraint. This is to maximize happy customers.
(*) This problem is NP-complete or NP-hard because you can relax it to a knapsack problem. In practice this means: you can't write an algorithm for it that scales out and finds the optimal solution in reasonable time. But a constraint solver can get you close.

time scale in NetLogo / remove turtle

I would like to build a system which has time scale of minutes and hours
there are number of turtles which stay in specific patches for different time based on their types then leave.
I use data-and-time as a property of turtle to record arrive time then calculate the leaving time
but i don't know how can I make the turtle reaches this leaving time ( after 4 to 6 hours)
also I got confused to deal with hours and minutes scale ? as the turtles will arrive at any time between the morning and the midday , stay for a period of time based on their type then leave
thanks
I'd suggest equating one tick with one minute, and doing all your calculations in minutes.

Even prize distribution

I'm currently facing interesting algorithm problem and I am looking for ideas or possible solutions. Topic seems to be common so maybe it's known and solved but I'm unable to find it.
So lets assume that I'm running shop and
I'm making lottery for buying customers. Each time they buy something they can win prize.
Prizes are given to customers instantly after buying.
I have X prizes and
I will be running lottery for Y days
Paying customer (act of buying, transaction) should have equal chance to win prize
Prizes should be distributed till last day (at last day there should be left some prizes to distribute)
There can not be left prizes at the end
I do not have historical data of transactions per day (no data from before lottery) to estimate average number of transactions (yet lottery could change number of transactions)
I can gather data while lottery is running
It this is not-solvable, what is closest solution?
Instant prize distribution have to stay.
Possible Solution #1
Based on #m69 comment
Lets says there are 6 prizes (total prizes) and 2 days of lottery.
Lets define Prizes By Day as PBD (to satisfy requirement have prizes till last day).
PBD = total prizes / days
We randomly choose as many as PBD events every day. Every transaction after this event is winning transaction.
Can be optimized to no to use last hour of last day of lottery to guarantee giving away all of prizes.
Pluses
Random. Simple, elegant solution.
Minuses
Seems that users have no equal chance to win.
Possible Solution #2
Based on #Sorin answer
We start to analyze first time frame (example 1 hour). And we calculate chance to win as:
where:
Δprizes = left prizes,
Δframes = left frames
What you're trying to do is impossible. Once you've gave away the last prize you can't prove any guarantee for the number of customers left, so not all customers will have equal chance to win a prize.
You can do something that approximates it fairly well. You can try to estimate the number of customers you will have, assume that they are evenly distributed and then spread the prizes over the period while the contest is running. This will give you a ratio that you can use to say if a given customer is a winner. Then as the contest progresses, change the estimates to match what you see, and what prizes are left. Run this update every x (hours/ minutes or even customer transaction) to make sure the rate isn't too low and every q prizes to make sure the rate isn't too high. Don't run the update too often if the prizes are given away or the algorithm might react too strongly if there's a period with low traffic (say overnight).
Let me give you an example. Say you figure out that you're going to see 100 customers per hour and you should give prizes every 200 customers. So roughly 1 every 2 hours. After 3 hours you come back and you see you saw 300 customers per hour and you've given out 4 prizes already. So you can now adjust the expectation to 300 customers per hour and adjust the distribution rate to match what is left.
This will work even if your initial is too low or too high.
This will break badly if your estimate is too far AND you updates are far in between (say you only check after a day but you've already given away all the prizes).
This can leave prizes on the table. If you don't want that you can reduce the amount of time the program considers the contest as running so that it should finish the prizes before the end of the contest. You can limit the number of prizes awarded in a given day to make the distribution more uniform (don't set it to X/Y, but something like X/Y * .25 so that there's some variation), and update the limit at the end of the day to account for variation in awards given.

Best practices for overall rating calculation

I have LAMP-based business application. SugarCRM to be more precise. There are 120+ active users at the moment. Every day each user generates some records that are used in complex calculation to get so called “individual rating”.
It takes for about 6 seconds to calculate one “individual rating” value. And there was not a big problem before: each user hits the link provided to start “individual rating” calculations, waits for 6-7 seconds, and get the value displayed.
But now I need to implement “overall rating” calculation. That means that additionally to “individual rating” I have to calculate and display to the user:
minimum individual rating among ALL the users of the application
maximum individual rating among ALL the users of the application
current user position in the range of all individual ratings.
Say, current user has individual rating equal to 220 points, minimum value of rating is 80, maximum is 235 and he is on 23rd position among all the users.
What are (imho) the main problems to be solved?
If one calculation lasts for 6 seconds, that overall calculations will take more than 10 minutes. I think it’s no good to make the application almost unaccessible for this period. And what if the quantity of users will rise in the nearest future 2-3 times?
Those calculations could be done as nightly job but all the users are in different timezones. In Russia difference between extreme timezones is 9 hours. So people in west part of Russia are still working in “today”. While people in eastern part is waking up to work in “tomorrow”. So what is the best time for nightly job in this case?
Are there any best practices|approaches|algorithms to build such rating system?
Given only the information provided, the only options I see:
The obvious one - reduce the time taken for a rating calculation (6 seconds to calculate 1 user's rating seems like a lot)
If possible, have intermediate values which you only recalculate some of, as required (for example, have 10 values that make up the rating, all based on different data, when some of the data changes, flag the appropriate values for recalcuation). Either do this recalculation:
During your daily recalculation or
When the update happens
Partial batch calculation - only recalculate x of the users' ratings at chosen intervals (where x is some chosen value) - has the disadvantage that, at all times, some of the ratings can be out of date
Calculate if not busy - either continuously recalculate ratings or only do so at a chosen interval, but instead of locking the system, have it run as a background process, only doing work if the system is idle
(Sorry, didn't manage with "long" comment posting; so decided to post as answer)
#Dukeling
SQL query that takes almost all the time for calculation mentioned above is just a replication of business logic that should be executed in PHP code. The logic was moved into SQL with the hope to reduce calculation time. OK, I’ll try both to optimize SQL query and play with executing logic in PHP code.
Suppose after that optimized application calculates individual rating for just 1 second. Great! But even in this case the first user logged into system should awaits for 120 seconds (120+ users * 1 sec = 120 sec) to calculate overall rating and gets its position in it.
I’m thinking of implementing the following approach:
Let’s have 2 “overall ratings” – “today” and “yesterday”.
For displaying purposes we’ll use “yesterday” overall rating represented as huge already sorted PHP array.
When user hits calculation link he started “today” calculation but application displays him “yesterday” value. Thus we have quickly accessible “yesterday” rating and each user randomly launches rating calculation that will be displayed for them tomorrow.
User list are partitioned by timezones. Each hour a cron job started to check if there’re any users in selected timezone that don’t have “today” individual rating calculated (e.g. user didn’t log into application). If so, application starts calculation of individual rating and puts its value in “today” (still invisible) ovarall rating array. Thus we have a cron job that runs nightly for each timezone-specific user group and fills the probable gaps in case users didn’t log into system.
After all users in all timezones had been worked out, application
sorts “today” array,
drops “yesterday” one,
rename “today” in “yesterday” and
initialize new “today”.
What do you think of it? Is it reasonable enough or not?

Resources