Advertisement
Guest User

Untitled

a guest
May 21st, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.78 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <limits>
  4. #include <random>
  5. #include <chrono>
  6. #include <variant>
  7. #include <iomanip>
  8.  
  9. /* Время моделирования */
  10. #define SIMULATION_TIME 86400
  11.  
  12. /* Рандомное число от 0 до 1 */
  13. double random_value()
  14. {
  15.   unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  16.   std::default_random_engine generator(seed);
  17.   return std::generate_canonical<double,std::numeric_limits<double>::digits>(generator);
  18. }
  19.  
  20. /* Экспоненциальное распределение */
  21. double exponential_distribution(double min, double bias)
  22. {
  23.   double rez = -std::numeric_limits<double>::infinity();
  24.   while (rez < min || rez > 7200)
  25.   {
  26.     double rn = random_value();
  27.     double avg = min + bias;
  28.     rez = avg * (-log(1 - rn));
  29.   }
  30.   return rez;
  31. }
  32.  
  33. /* Класс состояний транзакта(станка) */
  34. struct MachineState
  35. {
  36.     struct AtWork {}; // В работе
  37.     struct InQueue {}; // В очереди
  38.     struct UnderRepair {}; // На ремонте
  39.  
  40.     using State = std::variant<AtWork, InQueue, UnderRepair>;
  41.    
  42.     void put_in_work()
  43.     {
  44.         m_state = std::visit(WorkEvent{}, m_state);
  45.     }
  46.    
  47.     void put_in_queue()
  48.     {
  49.         m_state = std::visit(QueueEvent{}, m_state);
  50.     }
  51.    
  52.     void put_in_repair()
  53.     {
  54.         m_state = std::visit(RepairEvent{}, m_state);
  55.     }
  56.    
  57.     struct WorkEvent
  58.     {
  59.         State operator()(const AtWork&){ return AtWork(); }
  60.         State operator()(const InQueue&){ return AtWork(); }
  61.         State operator()(const UnderRepair&){ return AtWork(); }
  62.     };
  63.    
  64.     struct QueueEvent
  65.     {
  66.         State operator()(const AtWork&){ return InQueue(); }
  67.         State operator()(const InQueue&){ return InQueue(); }
  68.         State operator()(const UnderRepair&){ return InQueue(); }
  69.     };
  70.  
  71.     struct RepairEvent
  72.     {
  73.         State operator()(const AtWork&){ return UnderRepair(); }
  74.         State operator()(const InQueue&){ return UnderRepair(); }
  75.         State operator()(const UnderRepair&){ return UnderRepair(); }
  76.     };
  77.  
  78.     State m_state;
  79. };
  80.  
  81. /* Перечисление состояний транзакта (станка) */
  82. enum States { AtWork, InQueue, UnderRepair};
  83.  
  84. /* Класс транзакта (станка) */
  85. class Machine
  86. {
  87.     double simulation_time = 0; // Время, в котором находится транзакт (станок)
  88.     double working_time = 0; // Время работы (время работы с момента последней починки)
  89.     double lead_time = 0; // Время обработки станком одной операции
  90.     MachineState state; // Текущее состояние транзакта (станка)
  91. public:
  92.     Machine() {}
  93.     void set_simulation_time(int time)
  94.     {
  95.         simulation_time = time;
  96.     }
  97.     void set_working_time(int time)
  98.     {
  99.         working_time = time;
  100.     }
  101.     void set_lead_time(int time)
  102.     {
  103.         lead_time = time;
  104.     }
  105.     auto set_state(States s)
  106.     {
  107.         switch (s)
  108.         {
  109.             case AtWork:
  110.                 state.put_in_work();
  111.                 break;
  112.             case InQueue:
  113.                 state.put_in_queue();
  114.                 break;
  115.             case UnderRepair:
  116.                 state.put_in_repair();
  117.                 break;
  118.         }
  119.     }
  120.     int get_simulation_time()
  121.     {
  122.         return simulation_time;
  123.     }
  124.     int get_working_time()
  125.     {
  126.         return working_time;
  127.     }
  128.     int get_lead_time()
  129.     {
  130.         return lead_time;
  131.     }
  132.     auto get_state()
  133.     {
  134.         States s = AtWork;
  135.         if (std::holds_alternative<MachineState::InQueue>(state.m_state))
  136.             s = InQueue;
  137.         else if (std::holds_alternative<MachineState::UnderRepair>(state.m_state))
  138.             s = UnderRepair;
  139.         return s;
  140.     }
  141.     auto get_next_state()
  142.     {
  143.         States s = AtWork;
  144.         if (std::holds_alternative<MachineState::InQueue>(state.m_state))
  145.             s = UnderRepair;
  146.         else if (std::holds_alternative<MachineState::UnderRepair>(state.m_state))
  147.             s = AtWork;
  148.         else if (std::holds_alternative<MachineState::AtWork>(state.m_state))
  149.             s = InQueue;
  150.         return s;
  151.     }
  152. };
  153.  
  154. /* Класс фабрики */
  155. class Factory
  156. {
  157.     std::vector<Machine> m; // Массив станков
  158.     double simulation_time = 0; // Текущее время моделирования работы фабрики
  159.     int count_of_machines = 0; // Количество станков
  160.     int count_of_services = 0; // Количество технических специалистов
  161.     int total_work = 0; // Общее количество выполненной работы
  162.     int total_queue = 0; // Общее количество вхождений в очередь
  163.     int total_enrty = 0; // Общее количество станков, начавших ремонт
  164.     int total_repair = 0; // Общее количество отремонтированных станков
  165.     int cur_queue = 0; // Текущая длина очереди
  166.     int cur_enrty = 0; // Текущее количество станков, начавших ремонт
  167.     double sum_queue = 0; // Сумма длин очередей в каждый момент времени
  168.     double N_coeff = 0; // Коэффициент загрузки операторов
  169.     std::vector<int> i_cur_queue; // Текущая очередь на ремонт
  170.  
  171. public:
  172.     Factory() {}
  173.  
  174.     Factory(int count_m, int count_s) : count_of_machines(count_m), count_of_services(count_s)
  175.     {
  176.         m = std::vector<Machine>(count_of_machines);
  177.     }
  178.  
  179.     /* Текущее количество станков, находящихся в ремонте */
  180.     int cur_repair()
  181.     {
  182.         int rez = 0;
  183.         for (int i = 0; i < count_of_machines; ++i)
  184.         {
  185.             if (m[i].get_state() == UnderRepair)
  186.             {
  187.                 ++rez;
  188.             }
  189.         }
  190.         return rez;
  191.     }
  192.  
  193.     void update(double cur_time)
  194.     {
  195.         std::vector<int> i_cur_m; // Текущие номера транзактов
  196.         simulation_time = cur_time; // Текущее время моделирования
  197.  
  198.         /* Заполняем массив текущих номеров транзактов */
  199.         for (int i = 0; i < count_of_machines; ++i)
  200.         {
  201.             if (cur_time == m[i].get_simulation_time())
  202.             {
  203.                 i_cur_m.push_back(i);
  204.             }
  205.         }
  206.  
  207.         /* Если это начало моделирования, то задаем каждому станку время обработки одной операции */
  208.         if (cur_time == 0)
  209.         {
  210.             for (int i = 0; i < count_of_machines; ++i)
  211.             {
  212.                 m[i].set_lead_time(exponential_distribution(400, 200));
  213.             }
  214.         }
  215.  
  216.         /* Если станок закончил ремонтироваться, то переводим его в рабочий режим */
  217.         for (int i = 0;  i < i_cur_m.size(); ++i)
  218.         {
  219.             if (m[i_cur_m[i]].get_state() == UnderRepair)
  220.             {
  221.                 m[i_cur_m[i]].set_lead_time(exponential_distribution(400, 200));
  222.                 m[i_cur_m[i]].set_state(AtWork);
  223.                 ++total_repair;
  224.             }
  225.         }
  226.  
  227.         /* Если станок сломался (рабочее время скоро превысит 2 часа),
  228.         отправляем его  очередь на починку */
  229.         bool flag = false;
  230.         for (int i = 0;  i < i_cur_m.size(); ++i)
  231.         {
  232.             if (m[i_cur_m[i]].get_working_time() >= 7200 - m[i_cur_m[i]].get_lead_time())
  233.             {
  234.                 m[i_cur_m[i]].set_state(InQueue);
  235.                 m[i_cur_m[i]].set_working_time(0);
  236.                 i_cur_queue.push_back(i_cur_m[i]);
  237.                 total_queue += 1;
  238.                 cur_queue += 1;
  239.                 flag = true;
  240.             }
  241.         }
  242.         sum_queue += cur_queue;
  243.  
  244.         /* Если станок в очереди на починку, то отправляем его чиниться, если есть места */
  245.         if ((i_cur_queue.size() >= count_of_services - cur_repair()) && ((count_of_services - cur_repair()) > 0))
  246.         {
  247.             total_enrty = total_enrty + count_of_services - cur_repair();
  248.             cur_queue = cur_queue - count_of_services + cur_repair();
  249.             double summ_serv_time = 0;
  250.             for (int i = 0; i < count_of_services - cur_repair(); ++i)
  251.             {
  252.                 double serv_time = exponential_distribution(600, 400);
  253.                 summ_serv_time += serv_time;
  254.                 m[i_cur_queue[i]].set_simulation_time(m[i_cur_queue[i]].get_simulation_time() + serv_time);
  255.                 m[i_cur_queue[i]].set_state(UnderRepair);
  256.             }
  257.             i_cur_queue.erase(i_cur_queue.begin(), i_cur_queue.begin() + count_of_services - cur_repair() + 1);
  258.             N_coeff += double(summ_serv_time) / count_of_services;
  259.         }
  260.         else if ((i_cur_queue.size() < count_of_services -  cur_repair()) && (i_cur_queue.size() > 0))
  261.         {
  262.             total_enrty += i_cur_queue.size();
  263.             cur_queue = 0;
  264.             double summ_serv_time = 0;
  265.             for (int i = 0; i < i_cur_queue.size(); ++i)
  266.             {
  267.                 double serv_time = exponential_distribution(600, 400);
  268.                 summ_serv_time += serv_time;
  269.                 m[i_cur_queue[i]].set_simulation_time(m[i_cur_queue[i]].get_simulation_time() + serv_time);
  270.                 m[i_cur_queue[i]].set_state(UnderRepair);
  271.             }
  272.             i_cur_queue.erase(i_cur_queue.begin(), i_cur_queue.end());
  273.             N_coeff += double(summ_serv_time) / count_of_services;
  274.         }
  275.  
  276.         /* Если станок находится в рабочем состоянии, то он выполняет еще одну операцию */
  277.         for (int i = 0;  i < i_cur_m.size(); ++i)
  278.         {
  279.             if (m[i_cur_m[i]].get_state() == AtWork)
  280.             {
  281.                 m[i_cur_m[i]].set_working_time(m[i_cur_m[i]].get_working_time() + m[i_cur_m[i]].get_lead_time());
  282.                 m[i_cur_m[i]].set_simulation_time(m[i_cur_m[i]].get_simulation_time() + m[i_cur_m[i]].get_lead_time());
  283.                 ++total_work;
  284.             }
  285.         }
  286.  
  287.         /* Если станок ожидает в очереди, то рассчитываем, сколько ещё времени он будет ожидпть */
  288.         int fut_queue = 0;
  289.         for (int i = 0;  i < i_cur_m.size(); ++i)
  290.         {
  291.             if (m[i_cur_m[i]].get_state() == InQueue)
  292.             {
  293.                 m[i_cur_m[i]].set_simulation_time(near_transition(cur_time));
  294.                 ++fut_queue;
  295.             }
  296.         }
  297.         sum_queue += i_cur_queue.size() * (near_transition(cur_time) - cur_time - 1);
  298.     }
  299.  
  300.     /* Ближайшее время, когда произойдет какое-либо событие */
  301.     double near_transition(double cur_time)
  302.     {
  303.         double nearest_future = std::numeric_limits<double>::infinity();
  304.         for (int i = 0; i < count_of_machines; ++i)
  305.         {
  306.             if (m[i].get_simulation_time() < nearest_future && m[i].get_simulation_time() != cur_time)
  307.             {
  308.                 nearest_future = m[i].get_simulation_time();
  309.             }
  310.         }
  311.         return nearest_future;
  312.     }
  313.  
  314.     /* Моделирование работы фабрики time времени */
  315.     void work(double end_time)
  316.     {
  317.         for (double i = 0; i <= end_time; i = near_transition(i))
  318.         {
  319.             update(i);
  320.         }
  321.     }
  322.  
  323.     int get_total_work()
  324.     {
  325.         return total_work;
  326.     }
  327.  
  328.     double get_avg_queue()
  329.     {
  330.         return sum_queue /simulation_time;
  331.     }
  332.  
  333.     double get_N_coeff()
  334.     {
  335.         return  N_coeff / simulation_time;
  336.     }
  337. };
  338.  
  339.  
  340. int main()
  341. {
  342.     std::cout << "k\t\t" << "total_work\t" << "avg_queue\t" << "N_coeff" << std::endl;
  343.     /* Для количества технических специалистов от 1 до 42 */
  344.     for (int k = 1; k <= 41; ++k)
  345.     {
  346.         Factory f(40, k); // создание фабрики (40 станков, k технических специалистов)
  347.         f.work(SIMULATION_TIME); // моделирование работы фабрики в течеие SIMULATION_TIME секунд
  348.  
  349.         std::cout <<  std::fixed << std::setprecision(3) << k << "\t\t" \
  350.         << f.get_total_work() << "\t\t" << f.get_avg_queue() << "\t\t" << f.get_N_coeff() << std::endl;
  351.     }
  352.  
  353.     return 0;
  354. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement