📜 ⬆️ ⬇️

How did I count the time of arrival by the Monte Carlo method

Easy and "semi-festive" post. All involved in the holiday :)

One of the most exciting things in the eighties was software modeling for solving some complicated analytical problems and one of the most used techniques was the Monte Carlo method. It lies in the fact that it starts modeling a large number of times to get more and more reliable results.

Despite the fact that PHP is not a scientific language and is rarely used for research purposes, the Monte Carlo method can easily be implemented on it. And in this article I will show how to do it.
')
Real life challenge

A couple of days ago I should have a meeting at 9 am, 100 miles from my house. At 6:30 in the morning I woke up, got dressed, and while I was having breakfast, I began to figure out the next couple of hours in my notebook. I, as usual, wanted to arrive on time, so I started throwing a route: leaving the city, a country road, then north, east across the state, a local road to the east, driving through the city, then north again and arriving in the city. It all looked something like this:


image

My wife filled the tank last night and I could safely ride along the country road. The tires seemed fine when I looked at them, but the thought of whether or not to stop for 10 minutes to check their pressure didn’t bother me. After all, if I stop and check them, I will be confident in their pressure, because now I was not sure about it, and tire pressure can affect my movement and speed ...

I can leave earlier, for example, at 6.40, but then my wife will have to take her daughter to school herself, instead of going straight to work. If I wait another 10 minutes, then I can be at the school just at the moment when they just open their doors, thereby saving my wife from inconvenience, especially since the school is on the way to leaving the city and it did not delay me much .

I went back to what I was painting and added the following:

image

Drinking a second cup of coffee, I stood by the window. The clear morning sky, the light morning breeze confirmed the good forecast on my smartphone and I thought that the trip would be quick this time. Finishing my planning, I drew an approximate time for each stage, which I drew earlier:

image

The expected trip time was 115 minutes (1 hour and 55 minutes), if I can move without unnecessary stops. I expected to arrive at 8.35, if I go at once, or at 8.55, if I have to take my daughter with me, to send her to school and check the tires at the same time.

But any planning ceases to be perfect after it collides with reality! For some unknown reason, many parents decide to leave their children at school earlier than usual, so I lost more than 5 minutes compared to what I had planned for my quick trip. Realizing that I was a little late, I decided not to check tire pressure and go right away.

I got to the exit from the city 5 minutes earlier than I had planned in the worst case scenario and everything went well evenly until somewhere between points B and C in my plan I didn’t stumble upon a fog that had a strong effect on visibility on road. Has the mist lowered my average speed? and it also made it difficult to overtake slow but long trucks. I overcame the city traffic much easier than usual and it did not take more than 10 minutes. After a few miles on the southern road, the fog dropped and I could safely ride at the permitted speed. But when I was approaching my goal, I realized that road works were ahead and this again would take away my scheduled time. In general, I spent another 10 extra minutes on my journey and in the end I was late.

Simulate the journey

I understand that most of the work with PHP is directed to all sorts of online shopping and other websites. But PHP can be a great tool for scientific research, because it’s easy to train non-professional programmers, such as engineers and scientists, unlike my favorite Python.

Let's write a small code that will help me understand how sooner or later I can arrive at the meeting if a couple of stages of my journey depart a little from the intended path. To begin with, you can describe our way as it is:

<?php class MyTrip { protected $departureTime; protected $meetingTime; protected $travelTimes; public function __construct() { $this->setDepartureTime('0640'); $this->setMeetingTime('0900'); //       $this->setTravelTimes(array( 'AB' => 17, 'BC' => 17, 'CD' => 36, 'DE' => 9, 'EF' => 15, 'FG' => 15, 'GH' => 6 )); } //       protected static function convertToMinutes($timeStr) { return substr($timeStr, 0, 2) * 60 + substr($timeStr, 2, 2); } public function setDepartureTime($timeStr) { $this->departureTime = self::convertToMinutes($timeStr); } public function setMeetingTime($timeStr) { $this->meetingTime = self::convertToMinutes($timeStr); } public function setTravelTimes(array $travelTimes) { $this->travelTimes = $travelTimes; } public checkPlan($stopAtSchool = true, $checkTires = true) { // ... } } 


The plan must be a feasible and suitable criterion for determining this to be such that the sum of all the times plus the early departure time must be less than or equal to the time that my meeting is scheduled for. Actually this is what determines the checkPlan () method:

 <?php public checkPlan($stopAtSchool = true, $checkTires = true) { //       $travelTime = array_sum($this->travelTimes); //  ,        $schoolDelay = ($stopAtSchool) ? 10 : 0; //       $tiresDelay = ($checkTires) ? 10 : 0; //     $meetingArriveTime = $this->departureTime + $travelTime + $schoolDelay + $tiresDelay; //    ? $arriveOnTime = $meetingArriveTime <= $this->meetingTime; return array($meetingArriveTime, $this->meetingTime, $arriveOnTime); } 


Everything, we need only to make an instance of this class and check:

 <?php $trip = new MyTrip(); print_r($trip->checkPlan()); 


Taking into account the default settings, the output will be as follows:

 Array ( [0] => 535 [1] => 540 [2] => 1 ) 


I have to arrive at 535 minutes, and the meeting is scheduled for 540 minutes. If translated into hours, I will arrive at 8.45, 15 minutes ahead of schedule.

But what about the possible delays? How to foresee and calculate them?

Monte Carlo method or add randomness

In the simplest form, we can define a certain safe gap for each event and say that it can happen 10% earlier and 25% later than the specified time. These gaps can be randomly added to the initial delays (daughter, pressure) and the time between stages of multiplying each factor by rand (90,125) / 100.
You can also assign a 50% chance to two solutions — take your daughter to school and check tires. Here rand () will help again:

 $this->checkTires = rand(1, 100) > 50; 


By combining all this together, you can define the checkPlanRisk () method to calculate the decision whether I will arrive on time or not, taking into account the different situation on the way:

 <?php public function checkPlanRisk() { //    $travelTime = 0; foreach ($this->travelTimes as $t) { $travelTime += $t * rand(90, 125) / 100; } //      $schoolDelay = 0; if (rand(1, 100) > 50) { $schoolDelay = 10 * rand(90, 125) / 100; } //    $tiresDelay = 0; if (rand(1, 100) > 50) { $tiresDelay = 10 * rand(90, 125) / 100; } //    $meetingArriveTime = $this->departureTime + $travelTime + $schoolDelay + $tiresDelay; //    ? $arriveOnTime = $meetingArriveTime <= $this->meetingTime; return array($schoolDelay, $tiresDelay, $meetingArriveTime, $this->meetingTime, $arriveOnTime); } 


Now the question is, will I arrive on time, taking into account all possible delays? The Monte Carlo method allows to solve this issue by running a large number of times of a given task and calculating the “confidence level” as the ratio of the arrival time in time to the total number of task launches.

If you run this a sufficient number of times and write down how often I arrive on time, then I will be able to determine some probability that I will arrive as planned.

 <?php public function runCheckPlanRisk($numTrials) { $arriveOnTime = 0; for ($i = 1; $i <= $numTrials; $i++) { $result = $this->checkPlanRisk(); if ($result[4]) { $arriveOnTime++; } echo ": " . $i; echo " : " . $result[0]; echo " : " . $result[1]; echo "  : " . $result[2]; if ($result[4]) { echo " -- "; } else { echo " -- "; } $confidence = $arriveOnTime / $i; echo " : $confidencen"; } } 


Create a new instance and do 1000 calculations one after the other:

 <?php $trip = new MyTrip(); $trip->runCheckPlanRisk(1000); 


After completion we will receive the forecast:

 : 1000 : 0 : 11.3  : 530.44 --   : 0.716 


With the current parameters, as you can see, I have a 72% chance to arrive at the meeting on time. Of course, this is just an average value, but it also has the right to life.

From myself: the article most likely carries absolutely nothing new, the title is a bit yellowish, but this article seemed funny to me. Read a long time, and remembered with the appearance of the article on the Habré about Monte Carlo. Maybe someone will come in handy.

Source: https://habr.com/ru/post/192448/


All Articles