Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <limits>
- #include <random>
- #include <chrono>
- #include <variant>
- #include <iomanip>
- /* Время моделирования */
- #define SIMULATION_TIME 86400
- /* Рандомное число от 0 до 1 */
- double random_value()
- {
- unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
- std::default_random_engine generator(seed);
- return std::generate_canonical<double,std::numeric_limits<double>::digits>(generator);
- }
- /* Экспоненциальное распределение */
- double exponential_distribution(double min, double bias)
- {
- double rez = -std::numeric_limits<double>::infinity();
- while (rez < min || rez > 7200)
- {
- double rn = random_value();
- double avg = min + bias;
- rez = avg * (-log(1 - rn));
- }
- return rez;
- }
- /* Класс состояний транзакта(станка) */
- struct MachineState
- {
- struct AtWork {}; // В работе
- struct InQueue {}; // В очереди
- struct UnderRepair {}; // На ремонте
- using State = std::variant<AtWork, InQueue, UnderRepair>;
- void put_in_work()
- {
- m_state = std::visit(WorkEvent{}, m_state);
- }
- void put_in_queue()
- {
- m_state = std::visit(QueueEvent{}, m_state);
- }
- void put_in_repair()
- {
- m_state = std::visit(RepairEvent{}, m_state);
- }
- struct WorkEvent
- {
- State operator()(const AtWork&){ return AtWork(); }
- State operator()(const InQueue&){ return AtWork(); }
- State operator()(const UnderRepair&){ return AtWork(); }
- };
- struct QueueEvent
- {
- State operator()(const AtWork&){ return InQueue(); }
- State operator()(const InQueue&){ return InQueue(); }
- State operator()(const UnderRepair&){ return InQueue(); }
- };
- struct RepairEvent
- {
- State operator()(const AtWork&){ return UnderRepair(); }
- State operator()(const InQueue&){ return UnderRepair(); }
- State operator()(const UnderRepair&){ return UnderRepair(); }
- };
- State m_state;
- };
- /* Перечисление состояний транзакта (станка) */
- enum States { AtWork, InQueue, UnderRepair};
- /* Класс транзакта (станка) */
- class Machine
- {
- double simulation_time = 0; // Время, в котором находится транзакт (станок)
- double working_time = 0; // Время работы (время работы с момента последней починки)
- double lead_time = 0; // Время обработки станком одной операции
- MachineState state; // Текущее состояние транзакта (станка)
- public:
- Machine() {}
- void set_simulation_time(int time)
- {
- simulation_time = time;
- }
- void set_working_time(int time)
- {
- working_time = time;
- }
- void set_lead_time(int time)
- {
- lead_time = time;
- }
- auto set_state(States s)
- {
- switch (s)
- {
- case AtWork:
- state.put_in_work();
- break;
- case InQueue:
- state.put_in_queue();
- break;
- case UnderRepair:
- state.put_in_repair();
- break;
- }
- }
- int get_simulation_time()
- {
- return simulation_time;
- }
- int get_working_time()
- {
- return working_time;
- }
- int get_lead_time()
- {
- return lead_time;
- }
- auto get_state()
- {
- States s = AtWork;
- if (std::holds_alternative<MachineState::InQueue>(state.m_state))
- s = InQueue;
- else if (std::holds_alternative<MachineState::UnderRepair>(state.m_state))
- s = UnderRepair;
- return s;
- }
- auto get_next_state()
- {
- States s = AtWork;
- if (std::holds_alternative<MachineState::InQueue>(state.m_state))
- s = UnderRepair;
- else if (std::holds_alternative<MachineState::UnderRepair>(state.m_state))
- s = AtWork;
- else if (std::holds_alternative<MachineState::AtWork>(state.m_state))
- s = InQueue;
- return s;
- }
- };
- /* Класс фабрики */
- class Factory
- {
- std::vector<Machine> m; // Массив станков
- double simulation_time = 0; // Текущее время моделирования работы фабрики
- int count_of_machines = 0; // Количество станков
- int count_of_services = 0; // Количество технических специалистов
- int total_work = 0; // Общее количество выполненной работы
- int total_queue = 0; // Общее количество вхождений в очередь
- int total_enrty = 0; // Общее количество станков, начавших ремонт
- int total_repair = 0; // Общее количество отремонтированных станков
- int cur_queue = 0; // Текущая длина очереди
- int cur_enrty = 0; // Текущее количество станков, начавших ремонт
- double sum_queue = 0; // Сумма длин очередей в каждый момент времени
- double N_coeff = 0; // Коэффициент загрузки операторов
- std::vector<int> i_cur_queue; // Текущая очередь на ремонт
- public:
- Factory() {}
- Factory(int count_m, int count_s) : count_of_machines(count_m), count_of_services(count_s)
- {
- m = std::vector<Machine>(count_of_machines);
- }
- /* Текущее количество станков, находящихся в ремонте */
- int cur_repair()
- {
- int rez = 0;
- for (int i = 0; i < count_of_machines; ++i)
- {
- if (m[i].get_state() == UnderRepair)
- {
- ++rez;
- }
- }
- return rez;
- }
- void update(double cur_time)
- {
- std::vector<int> i_cur_m; // Текущие номера транзактов
- simulation_time = cur_time; // Текущее время моделирования
- /* Заполняем массив текущих номеров транзактов */
- for (int i = 0; i < count_of_machines; ++i)
- {
- if (cur_time == m[i].get_simulation_time())
- {
- i_cur_m.push_back(i);
- }
- }
- /* Если это начало моделирования, то задаем каждому станку время обработки одной операции */
- if (cur_time == 0)
- {
- for (int i = 0; i < count_of_machines; ++i)
- {
- m[i].set_lead_time(exponential_distribution(400, 200));
- }
- }
- /* Если станок закончил ремонтироваться, то переводим его в рабочий режим */
- for (int i = 0; i < i_cur_m.size(); ++i)
- {
- if (m[i_cur_m[i]].get_state() == UnderRepair)
- {
- m[i_cur_m[i]].set_lead_time(exponential_distribution(400, 200));
- m[i_cur_m[i]].set_state(AtWork);
- ++total_repair;
- }
- }
- /* Если станок сломался (рабочее время скоро превысит 2 часа),
- отправляем его очередь на починку */
- bool flag = false;
- for (int i = 0; i < i_cur_m.size(); ++i)
- {
- if (m[i_cur_m[i]].get_working_time() >= 7200 - m[i_cur_m[i]].get_lead_time())
- {
- m[i_cur_m[i]].set_state(InQueue);
- m[i_cur_m[i]].set_working_time(0);
- i_cur_queue.push_back(i_cur_m[i]);
- total_queue += 1;
- cur_queue += 1;
- flag = true;
- }
- }
- sum_queue += cur_queue;
- /* Если станок в очереди на починку, то отправляем его чиниться, если есть места */
- if ((i_cur_queue.size() >= count_of_services - cur_repair()) && ((count_of_services - cur_repair()) > 0))
- {
- total_enrty = total_enrty + count_of_services - cur_repair();
- cur_queue = cur_queue - count_of_services + cur_repair();
- double summ_serv_time = 0;
- for (int i = 0; i < count_of_services - cur_repair(); ++i)
- {
- double serv_time = exponential_distribution(600, 400);
- summ_serv_time += serv_time;
- m[i_cur_queue[i]].set_simulation_time(m[i_cur_queue[i]].get_simulation_time() + serv_time);
- m[i_cur_queue[i]].set_state(UnderRepair);
- }
- i_cur_queue.erase(i_cur_queue.begin(), i_cur_queue.begin() + count_of_services - cur_repair() + 1);
- N_coeff += double(summ_serv_time) / count_of_services;
- }
- else if ((i_cur_queue.size() < count_of_services - cur_repair()) && (i_cur_queue.size() > 0))
- {
- total_enrty += i_cur_queue.size();
- cur_queue = 0;
- double summ_serv_time = 0;
- for (int i = 0; i < i_cur_queue.size(); ++i)
- {
- double serv_time = exponential_distribution(600, 400);
- summ_serv_time += serv_time;
- m[i_cur_queue[i]].set_simulation_time(m[i_cur_queue[i]].get_simulation_time() + serv_time);
- m[i_cur_queue[i]].set_state(UnderRepair);
- }
- i_cur_queue.erase(i_cur_queue.begin(), i_cur_queue.end());
- N_coeff += double(summ_serv_time) / count_of_services;
- }
- /* Если станок находится в рабочем состоянии, то он выполняет еще одну операцию */
- for (int i = 0; i < i_cur_m.size(); ++i)
- {
- if (m[i_cur_m[i]].get_state() == AtWork)
- {
- m[i_cur_m[i]].set_working_time(m[i_cur_m[i]].get_working_time() + m[i_cur_m[i]].get_lead_time());
- m[i_cur_m[i]].set_simulation_time(m[i_cur_m[i]].get_simulation_time() + m[i_cur_m[i]].get_lead_time());
- ++total_work;
- }
- }
- /* Если станок ожидает в очереди, то рассчитываем, сколько ещё времени он будет ожидпть */
- int fut_queue = 0;
- for (int i = 0; i < i_cur_m.size(); ++i)
- {
- if (m[i_cur_m[i]].get_state() == InQueue)
- {
- m[i_cur_m[i]].set_simulation_time(near_transition(cur_time));
- ++fut_queue;
- }
- }
- sum_queue += i_cur_queue.size() * (near_transition(cur_time) - cur_time - 1);
- }
- /* Ближайшее время, когда произойдет какое-либо событие */
- double near_transition(double cur_time)
- {
- double nearest_future = std::numeric_limits<double>::infinity();
- for (int i = 0; i < count_of_machines; ++i)
- {
- if (m[i].get_simulation_time() < nearest_future && m[i].get_simulation_time() != cur_time)
- {
- nearest_future = m[i].get_simulation_time();
- }
- }
- return nearest_future;
- }
- /* Моделирование работы фабрики time времени */
- void work(double end_time)
- {
- for (double i = 0; i <= end_time; i = near_transition(i))
- {
- update(i);
- }
- }
- int get_total_work()
- {
- return total_work;
- }
- double get_avg_queue()
- {
- return sum_queue /simulation_time;
- }
- double get_N_coeff()
- {
- return N_coeff / simulation_time;
- }
- };
- int main()
- {
- std::cout << "k\t\t" << "total_work\t" << "avg_queue\t" << "N_coeff" << std::endl;
- /* Для количества технических специалистов от 1 до 42 */
- for (int k = 1; k <= 41; ++k)
- {
- Factory f(40, k); // создание фабрики (40 станков, k технических специалистов)
- f.work(SIMULATION_TIME); // моделирование работы фабрики в течеие SIMULATION_TIME секунд
- std::cout << std::fixed << std::setprecision(3) << k << "\t\t" \
- << f.get_total_work() << "\t\t" << f.get_avg_queue() << "\t\t" << f.get_N_coeff() << std::endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement