#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <functional>
#include <locale>
using namespace std;
/* ================================================================
СТРУКТУРА ЗАЯВКИ
================================================================ */
struct Customer {
double arrival_time;
bool refused;
double start_time;
double service_time;
double departure_time;
Customer(double arr = 0.0)
: arrival_time(arr), refused(false),
start_time(-1.0), service_time(-1.0), departure_time(-1.0) {}
};
/* ================================================================
ГЛОБАЛЬНЫЕ КОНСТАНТЫ И ПАРАМЕТРЫ ЗАДАЧИ
================================================================ */
// Параметры системы
const int N0 = 6; // начальное число каналов
const int M = 4; // число мест в очереди
const double LAMBDA = 81.0; // интенсивность поступления заявок
const double MU = 7.0; // интенсивность обслуживания
const int J_CHANGE = 600; // после этой заявки меняется число каналов
const int K_NEW = 7; // новое число каналов
// Параметры моделирования
const int NUM_ARRIVALS = 1000; // заявок в одной серии
const int NUM_REPS = 100; // число серий
/* ================================================================
ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
================================================================ */
// Генератор экспоненциального распределения
double get_exp(double rate)
{
double u = (double)rand() / (RAND_MAX + 1.0);
return -log(1.0 - u) / rate;
}
// Вычисление среднего и СКО
void compute_mean_sko(const vector<double>& vals, double& mean, double& sko)
{
int n = (int)vals.size();
if (n <= 1) {
mean = 0.0;
sko = 0.0;
return;
}
mean = 0.0;
for (int i = 0; i < n; ++i) mean += vals[i];
mean /= n;
double sumsq = 0.0;
for (int i = 0; i < n; ++i) {
double d = vals[i] - mean;
sumsq += d * d;
}
sko = sqrt(sumsq / (n - 1.0));
}
/* ================================================================
ОСНОВНАЯ ФУНКЦИЯ
================================================================ */
int main()
{
setlocale(LC_ALL, "RU");
// Векторы результатов всех серий
vector<double> served_counts;
vector<double> rel_throughputs;
vector<double> abs_throughputs;
vector<double> avg_services;
vector<double> avg_waits;
vector<double> avg_busies;
vector<double> avg_queuelens;
srand((unsigned)time(NULL));
for (int rep = 0; rep < NUM_REPS; ++rep)
{
srand((unsigned)time(NULL) + (unsigned)rep);
vector<Customer> customers; // теперь используем глобальную структуру
customers.reserve(NUM_ARRIVALS);
double current_time = 0.0;
double last_update_time = 0.0;
double integral_busy = 0.0;
double integral_queuelen = 0.0;
priority_queue<double, vector<double>, greater<double> > departure_times;
queue<int> waiting_queue;
int current_n = N0;
int arrival_count = 0;
bool arrivals_done = false;
double next_arrival = get_exp(LAMBDA);
while (true)
{
double next_event = 1e18;
bool is_arrival = false;
if (!arrivals_done) {
next_event = next_arrival;
is_arrival = true;
}
if (!departure_times.empty()) {
double nd = departure_times.top();
if (nd < next_event) {
next_event = nd;
is_arrival = false;
}
}
if (next_event > 1e17) break;
double delta = next_event - last_update_time;
if (delta > 0.0) {
int busy = (int)departure_times.size();
int ql = (int)waiting_queue.size();
integral_busy += busy * delta;
integral_queuelen += ql * delta;
}
last_update_time = next_event;
current_time = next_event;
if (is_arrival)
{
arrival_count++;
customers.push_back(Customer(current_time));
int idx = (int)customers.size() - 1;
int busy = (int)departure_times.size();
if (busy < current_n) {
double serv = get_exp(MU);
customers[idx].start_time = current_time;
customers[idx].service_time = serv;
customers[idx].departure_time = current_time + serv;
departure_times.push(customers[idx].departure_time);
}
else if ((int)waiting_queue.size() < M) {
waiting_queue.push(idx);
}
else {
customers[idx].refused = true;
}
if (arrival_count < NUM_ARRIVALS) {
next_arrival = current_time + get_exp(LAMBDA);
}
else {
arrivals_done = true;
}
if (arrival_count == J_CHANGE) {
current_n = K_NEW;
while ((int)departure_times.size() < current_n && !waiting_queue.empty()) {
int qidx = waiting_queue.front(); waiting_queue.pop();
double serv = get_exp(MU);
customers[qidx].start_time = current_time;
customers[qidx].service_time = serv;
customers[qidx].departure_time = current_time + serv;
departure_times.push(customers[qidx].departure_time);
}
}
}
else
{
departure_times.pop();
if (!waiting_queue.empty()) {
int qidx = waiting_queue.front(); waiting_queue.pop();
double serv = get_exp(MU);
customers[qidx].start_time = current_time;
customers[qidx].service_time = serv;
customers[qidx].departure_time = current_time + serv;
departure_times.push(customers[qidx].departure_time);
}
}
}
// Обработка результатов серии
double T = current_time;
double avg_busy = (T > 0.0) ? integral_busy / T : 0.0;
double avg_queue = (T > 0.0) ? integral_queuelen / T : 0.0;
double sum_wait = 0.0, sum_serv = 0.0;
int num_served = 0;
for (int i = 0; i < (int)customers.size(); ++i) {
const Customer& c = customers[i];
if (!c.refused) {
sum_wait += c.start_time - c.arrival_time;
sum_serv += c.service_time;
num_served++;
}
}
double avg_wait = (NUM_ARRIVALS > 0) ? integral_queuelen / NUM_ARRIVALS : 0.0;
double avg_serv = (num_served > 0) ? sum_serv / num_served : 0.0;
double rel = (double)num_served / NUM_ARRIVALS;
double abs_th = (T > 0.0) ? (double)num_served / T : 0.0;
served_counts.push_back((double)num_served);
rel_throughputs.push_back(rel);
abs_throughputs.push_back(abs_th);
avg_services.push_back(avg_serv);
avg_waits.push_back(avg_wait);
avg_busies.push_back(avg_busy);
avg_queuelens.push_back(avg_queue);
// Таблица для первой серии
if (rep == 0) {
ofstream table("table.txt");
if (table.is_open()) {
table << "Таблица моделирования для одной серии (1000 заявок)\n\n";
table << setw(6) << "№"
<< setw(18) << "Время поступления"
<< setw(18) << "Начало обслуж."
<< setw(18) << "Окончание"
<< setw(15) << "Ожидание"
<< setw(15) << "Обслуживание"
<< " Статус\n";
table << "-----------------------------------------------------------------------------------------------\n";
table << fixed << setprecision(6);
for (int i = 0; i < (int)customers.size(); ++i) {
const Customer& c = customers[i];
table << setw(6) << (i + 1) << setw(18) << c.arrival_time;
if (c.refused) {
table << setw(18) << "-" << setw(18) << "-"
<< setw(15) << "-" << setw(15) << "-"
<< " Отказ\n";
}
else {
double wait = c.start_time - c.arrival_time;
table << setw(18) << c.start_time
<< setw(18) << c.departure_time
<< setw(15) << wait
<< setw(15) << c.service_time
<< " Обслужена\n";
}
}
table.close();
}
}
}
// Вычисление средних и СКО
double m_served, s_served, m_rel, s_rel, m_abs, s_abs;
double m_serv, s_serv, m_wait, s_wait, m_busy, s_busy, m_queue, s_queue;
compute_mean_sko(served_counts, m_served, s_served);
compute_mean_sko(rel_throughputs, m_rel, s_rel);
compute_mean_sko(abs_throughputs, m_abs, s_abs);
compute_mean_sko(avg_services, m_serv, s_serv);
compute_mean_sko(avg_waits, m_wait, s_wait);
compute_mean_sko(avg_busies, m_busy, s_busy);
compute_mean_sko(avg_queuelens, m_queue, s_queue);
// Запись в output.txt
ofstream out("output.txt");
if (out.is_open()) {
out << "Средние значения и среднеквадратические отклонения\n";
out << "(100 серий по 1000 заявок каждая)\n\n";
out << fixed << setprecision(6);
out << setw(45) << left << "Характеристика"
<< setw(18) << "Среднее"
<< setw(18) << "СКО" << "\n";
out << "--------------------------------------------------------------------------------\n";
out << setw(45) << left << "Число обслуженных заявок"
<< setw(18) << m_served
<< setw(18) << s_served << "\n";
out << setw(45) << left << "Относительная пропускная способность"
<< setw(18) << m_rel
<< setw(18) << s_rel << "\n";
out << setw(45) << left << "Абсолютная пропускная способность"
<< setw(18) << m_abs
<< setw(18) << s_abs << "\n";
out << setw(45) << left << "Среднее время обслуживания"
<< setw(18) << m_serv
<< setw(18) << s_serv << "\n";
out << setw(45) << left << "Среднее время нахождения в очереди"
<< setw(18) << m_wait
<< setw(18) << s_wait << "\n";
out << setw(45) << left << "Среднее число занятых каналов"
<< setw(18) << m_busy
<< setw(18) << s_busy << "\n";
out << setw(45) << left << "Среднее число занятых мест в очереди"
<< setw(18) << m_queue
<< setw(18) << s_queue << "\n";
out.close();
}
cout << "Симуляция завершена успешно!\n";
cout << "Созданы файлы: output.txt и table.txt\n";
return 0;
}