Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

3-4

.js
Скачиваний:
8
Добавлен:
28.06.2021
Размер:
12.84 Кб
Скачать
//Вспомогательные функции:

// Экспоненциальная случайная переменная
function Exponentional(lambda) {
const u = Math.random()
return -Math.log(u) / lambda;
}

// функция интенсивности
function lamFunc(t) {
return 2 + 2 / (t + 2);
}

// генерация Ts
function PoissonNonuniform(start, lambda) {
let t = start;
while (true) {
let u1 = Math.random();
t = t - Math.log(u1) / lambda;

let u2 = Math.random();
//console.log(lamFunc(t) / lambda)
if (u2 <= lamFunc(t) / lambda) {
return t;
}
}
}


//Функции событый:

//прибытие клиента
function clientArrival(variables, out) {
variables.t = variables.ta; // движение вдоль оси времени ко времени tA
variables.Na += 1; // прибывших всего
variables.n += 1; // клиентов в системе к моменту t

// генерируем следующего клиента
variables.ta = PoissonNonuniform(variables.t, variables.intensity) //Ts

if (variables.n == 1) {
variables.td = variables.t + Exponentional(variables.lam);
}

// запомнить время прибытия клиента Na
out.A[variables.Na] = variables.t;

out.summary.timeLine.push({
i: "A" + variables.Na,
t: variables.t
});
out.summary.sumOfClients += 1;
out.summary.clientsAtEvent.push(variables.n);
}

// уход клиента
function clientLeft(variables, out) {
variables.t = variables.td;
variables.Nd += 1;
variables.n -= 1;

if (variables.n == 0) {
variables.td = Infinity;
} else {
variables.td = variables.t + Exponentional(variables.lam);
}

// запомнить время ухода клиента Nd
out.D[variables.Nd] = variables.t;

out.summary.timeLine.push({
i: "D" + variables.Nd,
t: variables.t
});
out.summary.clientsAtEvent.push(variables.n);
}

// конец работы, но еще есть клиенты в системе
function clientLast(variables, out) {
variables.t = variables.td;
variables.Nd += 1;
variables.n -= 1;

if (variables.n > 0) {
variables.td = variables.t + Exponentional(variables.lam);
}

// запомнить время ухода клиента Nd
out.D[variables.Nd] = variables.t;

out.summary.timeLine.push({
i: "D" + variables.Nd,
t: variables.t
});
out.summary.clientsAtEvent.push(variables.n);
}

// никаких клиентов не осталось
function clientOut(variables, out) {
out.Tp = Math.max(variables.t - variables.T, 0);

out.summary.clientsAtEvent.push(variables.n);
}

// Функции проверки возможности свершения событий:

// проверка: следующее событие – прибытие клиента
function canEventArrival(variables) {
const { ta, td, T } = variables;
return ta <= td && ta <= T;
}

// проверка: следующее событие – уход клиента
function canEventLeft(variables) {
const { ta, td, T } = variables;
return td < ta && td <= T;
}

// проверка: следующее событие происходит после времени T, но еще есть клиенты в системе
function canEventLast(variables) {
const { ta, td, T, n } = variables;
return (Math.min(ta, td) > T) && (n > 0);
}

// проверка: никаких клиентов не осталось, время работы закончилось
function canEventOut(variables) {
const { ta, td, T, n } = variables;
return (Math.min(ta, td) > T) && (n == 0);
}

// Имитация СМО с одним устройством
function smo(intensity, lmb, T) {
let result = {
D: [], // время ухода клиентов
A: [], // время прибытия клиентов
Tp: 0, // время после T, когда последний клиент уходит
summary: {
timeLine: [],
sumOfClients: 0, // всего клиентов
clientsAtEvent: [], // число клиентов в системе к моментам времени
nonServiceTime: 0
},
T: T // длина периода времени обслуживания
}

// переменные
let variables = {
t: 0, // время
Na: 0, // число прибывших клиентов к моменту времени t
Nd: 0, // число уходов клиентов к моменту времени t
n: 0, // число клиентов в системе к моменту времени t
ta: 0, // время следующего прибытия клиента (после t);
td: Infinity, // время завершения работы устройства после обслуживания клиента (если нет, то бескон.)
intensity: intensity,
lam: lmb,
T: T
}

variables.ta = Exponentional(lmb)
variables.td = Infinity

while (true) {
/**
* Случаи:
* следующее событие – прибытие клиента
* следующее событие – уход клиента
* следующее событие происходит после времени T, но еще есть клиенты в системе
* никаких клиентов не осталось, время работы закончилось
*/

if (canEventArrival(variables)) {
clientArrival(variables, result);
} else if (canEventLeft(variables)) {
clientLeft(variables, result);
} else if (canEventLast(variables)) {
clientLast(variables, result);
} else if (canEventOut(variables)) {
clientOut(variables, result);

// конец обслуживания
break;
}
}
return result;
}



function showData() {
let oneGen = smo(3, 7, 10);

console.log("Клиенты:");
console.log("i\t|\t A(i) \t\t|\t D(i) \t\t\t|\t D(i) - A(i)");
console.log(`${''.padEnd(4, '-')}|${''.padEnd(15, '-')}|${''.padEnd(19, '-')}|${''.padEnd(19, '-')}`);

// время пользователя в системе
let userInSystem = 0;

for (var i = 0; i < oneGen.D.length; i++) {
if (oneGen.A[i] == undefined)
continue;
console.log(`${i} \t|\t ${oneGen.A[i].toFixed(4)} \t|\t ${oneGen.D[i].toFixed(4)} \t\t|\t ${(oneGen.D[i] - oneGen.A[i]).toFixed(4)}`);
userInSystem += oneGen.D[i] - oneGen.A[i];
}

console.log();
console.log();
console.log("Число клиентов в определнный момент времени:");
console.log("Событие\t|\t Время \t\t|\tQ(t)");
console.log(`${''.padEnd(8, '-')}|${''.padEnd(15, '-')}|${''.padEnd(8, '-')}`);
let arrayOfA = [];
let W = []; // время задержки клиента в очереди

// для расчета среднего времени между поступлениями
let arrival = {
old: null,
size: 0,
sum: 0
};

// для расчета среднего числа клиентов в системе Q(T) (интеграл)
let count = {
old: null,
sum: 0
};
let nonServiceTime = 0; // время незанятости

for (var i = 0; i < oneGen.summary.timeLine.length; i++) {
console.log(`${oneGen.summary.timeLine[i].i.padEnd(3, " ")} \t|\t ${oneGen.summary.timeLine[i].t.toFixed(4)} \t|\t ${oneGen.summary.clientsAtEvent[i]}`);

// число клиентов в системе
if (count.old != null) {
// число клиентов на отрезок времени (частичная сумма, численный интеграл)
count.sum += (oneGen.summary.timeLine[i].t - count.old) * oneGen.summary.clientsAtEvent[i];
}
count.old = oneGen.summary.timeLine[i].t;

// если событие прибытия
if (oneGen.summary.timeLine[i].i.includes("A")) {
// если первый клиент
if (i == 0) {
nonServiceTime = oneGen.summary.timeLine[i].t;

// если не первый и предыдущий не занят был момент
} else if (oneGen.summary.clientsAtEvent[i - 1] == 0) {

// прибавляем время простоя
nonServiceTime = oneGen.summary.timeLine[i].t - oneGen.summary.timeLine[i - 1].t;
}

// время между поступлениями
if (arrival.old != null) {
arrival.sum += oneGen.summary.timeLine[i].t - arrival.old;
arrival.size = arrival.size + 1;
}
arrival.old = oneGen.summary.timeLine[i].t;
}

// если событие прибытия и не занято
if (oneGen.summary.timeLine[i].i.includes("A") && oneGen.summary.clientsAtEvent[i] <= 1) {
W.push({ i: oneGen.summary.timeLine[i].i.replace("A", ""), t: 0 })

// иначе для прибытия если занято
} else if (oneGen.summary.timeLine[i].i.includes("A")) {
// сохраняем событие отдельно в очередь
arrayOfA.push({
i: oneGen.summary.timeLine[i].i.replace("A", ""),
t: oneGen.summary.timeLine[i].t
})
}

// если событие ухода клиента
if (oneGen.summary.timeLine[i].i.includes("D") && arrayOfA.length != 0) {
// изымаем из очереди и заносим время ожидания
let elemA = arrayOfA.shift();
W.push({
i: elemA.i,
t: (oneGen.summary.timeLine[i].t - elemA.t)
});
}
}

console.log();
console.log("Время ожидания в очереди для каждого клиента: ");
console.log("Клиент \t|\t Время в очереди");
console.log(`${''.padEnd(8, '-')}|${''.padEnd(20, '-')}`);
for (var i = 0; i < W.length; i++) {
console.log(`${W[i].i.padEnd(3, " ")} \t|\t ${W[i].t.toFixed(4)}`);
}

console.log(); console.log();

console.log("Статистики:");
console.log("Число клиентов N = " + oneGen.summary.sumOfClients);
console.log("Cреднее время, в течение которого клиент проводит в системе St = " + (userInSystem / oneGen.summary.sumOfClients).toFixed(4));
console.log("Среднее время между поступлениями = " + (arrival.sum / arrival.size).toFixed(4));

const WSum = W.map(el => el.t).reduce((a, b) => a + b, 0);
console.log("Среднее время обслуживания = " + ((userInSystem - WSum) / oneGen.summary.sumOfClients).toFixed(4));
console.log("Cредняя задержка клиентов в очереди W(T) = " + (WSum / oneGen.summary.sumOfClients).toFixed(4));
console.log("Среднее число клиентов в очереди Q(T) = " + (count.sum / oneGen.T).toFixed(4));
console.log("Коэффициент занятости устройства обслуживания rho(T) = " + ((oneGen.T - nonServiceTime) / oneGen.T).toFixed(4));
console.log(`Длительность моделируемого периода = ${oneGen.T} ч.`);

console.log();
console.log("Время после T, когда последний клиент уходит (Tp) = " + oneGen.Tp.toFixed(4));

//TpObs(2000);
}

//оценка Tp - время после T, когда ушел последний клиент
function TpObs(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += smo(3, 2, 10).Tp;
}
const tp = sum / n
console.log(`Среднее Tp при ${n} испытаниях = ${tp.toFixed(4)}`);
}

showData();
Соседние файлы в предмете Компьютерное моделирование