Моделирование работы станка с поломками

Автор: Пользователь скрыл имя, 10 Января 2014 в 12:16, курсовая работа

Описание работы

Целью данной курсовой работы является разработка имитационной модели с регулярным входным потоком, отсутствующей очередью и естественным отсчетом времени т.е моделирование работы больничной палаты. Основой для разработки модели в данной курсовой работе является метод имитационного моделирования. Так же курсовая работа предполагает создание программы на языке C++, обеспечивающей ввод исходной информации, ее обработку, реализацию алгоритма имитации процесса и выдачу необходимой информации.

Содержание

1. Введение………………………………………………………………………3
2. Моделирование систем массового обслуживания…………………………5
2.1 Структура и параметры эффективности и качества функционирования СМО………………………………………………………………………………5
2.2 Классификация СМО и их основные элементы………………...…………6
2.3 Процесс имитационного моделирования…………………………………12
3. Описание моделируемой системы……………………………………...…..16
3.1 Модельное время……………………………………………………….…..17
3.2 Используемые классы и объекты……………...………………….……….17
3.3 События и методы………………………………………………….………19
4. Программная реализация на С++…. ………………………………….……21
5. Анализ результатов работы программы……………………………....……35
6. Заключение……………….……………………………………………...…..38
7. Список использованной литературы…………………………………….…39

Работа содержит 1 файл

Моделирование работы станка.doc

— 571.50 Кб (Скачать)

Листинг программы файл 10.h. Описание классов

 

#include<cstdio>

#include<cstdlib>

#include<ctime>

#define _USE_MATH_DEFINES

#include<cmath>

using namespace std;

#include "List.h"

#include "erlang.h"

#include "normal.h"

#include "random.h"

FILE *que;            //файл для сбора статистики о длине очереди

FILE *sojourn;        //файл для сбора статистики  о времени пребывания

                      //в системе

int entered=0;        //счетчик поступлений

int completed=0;      //счетчик  обслуженных заявок

int completed1=0;     //счетчик заявок, не возвращавшихся в очередь


int completed2=0;     //счетчик  заявок, возвращавшихся в очередь

float ro_ave=0;       //переменная  для подсчета коэффициента загрузки

                      //станков

float que_ave=0;      //переменная для подсчета средней длины очереди

float soj_ave=0;      //переменная  для подсчета среднего времени  пребывания

                      //в системе

long int total;       //счетчик  модельного времени

 

class Client

{

 int id;                //уникальный идентификатор

 int time;              //текущее время пребывания в системе

 int to_serve;          //остаточное время обслуживания

 int interrupt;         //признак возврата в очередь

protected:

  static int counter;   //счетчик заявок

 public:

 friend class Machine;

 Client();

};

int Client::counter=0;   //инициализация  статического поля данных вне  класса

Client::Client()    //конструктор

{

 counter++;

 id=counter;

 time=0;

 interrupt=0;

 to_serve=-1;

}

 

class Machine

{

 const static int volume=1;

 const static int input_rate=1;

 const static int serve_median=30;


 const static int serve_offset=6;

 const static int set_median=21;

 const static int set_offset=9;

 const static int break_median=20;

 const static int break_offset=2;

 const static int repair_rate=133;

 const static int repair_stages=3;

 ListNode<Client> *queue;   //очередь

 Client **serving;          //обслуживаемые заявки

 int *to_serve;             //текущее время до окончания обслуживания

 int *to_setting;           //текущее время до окончания наладки

 int *to_break;             //оставшееся время безаварийной работы

 int *to_repair;            //текущее время до окончания ремонта

 int to_arrival;            //время до прибытия новой заявки

 int q_length;              //текущая длина очереди

 public:

 Machine();

 ~Machine();

 void Arrival();

 void Complete(int i);

 void Breakage(int i); 

 void Repair_End(int i);

 void Set_End(int i);

 int Busy();

 int FirstAvail();

 void run();

};

//Поиск доступного станка. Доступным считается станок, находящийся

//в состоянии простоя

int Machine::FirstAvail()

{

 for(int i=0;i<volume;i++)

  if ((serving[i]==NULL)&&(to_repair[i]==-1)&&(to_setting[i]==-1))

    return(i);

  return(-1);

}

 

int Machine::Busy()   //подсчет количества занятых станков

{

 int k=0;


 for(int i=0;i<volume;i++)

  if (serving[i]!=NULL) k++;

  return(k);

}

 

//Конструктор. Исходное состояние  - простой 

Machine::Machine()

{

  queue=NULL;

//Выделение памяти под  массивы

 serving=new Client *[volume];

 to_serve=new int[volume];

 to_setting=new int[volume];

 to_break= new int[volume];

 to_repair= new int[volume];

 to_arrival=(int)(get_exp(input_rate)*60);

 if (to_arrival==0) to_arrival=1;

//Инициализация массивов

 for(int i=0;i<volume;i++)

 {

  to_serve[i]=-1;

  to_setting[i]=-1;

  to_break[i]=(int)(get_normal(break_median, break_offset, 0.001)*60);

  if (to_break[i]==0) to_break[i]=1;

  to_repair[i]=-1;

 serving[i]=NULL;

 }

 q_length=0;

}

Machine::~Machine()

{

for(int i=0;i<volume;i++)

  if (serving[i]!=NULL) delete serving[i];

 delete [] serving;

 delete[] to_serve;

 delete[] to_setting;


 delete[] to_break;

 delete[] to_repair;

while(queue) queue=ListDelete<Client>(queue,queue);

}

void Machine::Arrival()      //поступление  новой заявки

{

 int k;

 Client *ptr=NULL;

 ListNode<Client> *ptr1=NULL;

//Разыгрываем новую длительность  интервала между поступлениями

 to_arrival=(int)(get_exp(input_rate)*60);

 if (to_arrival==0) to_arrival=1; 

 entered++;                  //инкремент счетчика поступлений

  ptr=new Client();          //создание новой заявки

  k=FirstAvail();

 if (k==-1)                  //поставить поступившую заявку на обслуживание

                             //невозможно

 {

  ptr1=new ListNode<Client>(ptr, NULL);

  if (queue==NULL) queue=ptr1;

  else ListAdd<Client>(queue, ptr1);

  q_length++;

 }

 else                        //новую заявку сразу ставим на обслуживание

                             //на k-й станок

 {

  serving[k]=ptr;

  to_serve[k]=(int)get_normal(serve_median, serve_offset, 0.001);

  if (to_serve[k]==0) to_serve[k]=1;

 }

 return; 

}

 

void Machine::Complete(int i)   //завершение обслуживания на i-м станке

{

 completed++;

 to_serve[i]=-1;

 if (serving[i]->interrupt==0) completed1++;

 else completed2++;

//запись статистики

 fprintf(sojourn, "%.3f\n",  ((float)serving[i]->time)/60);

 soj_ave=soj_ave*(1-1.0/completed)+(float)(serving[i]->time)/completed;

 delete serving[i];

 serving[i]=NULL;

//Станок переходит в состояние наладки

 to_setting[i]=get_uniform(set_median, set_offset);

 return;

}

 

void Machine::Breakage(int i)         //поломка i-го станка

{

 int k;

 k=FirstAvail();

 if (k==-1)                           //свободного станка нет, заявка

                                      //переходит в очередь

 {

  serving[i]->to_serve=to_serve[i];   //сохраняем время дообслуживания

                                      //в поле данных заявки

  serving[i]->interrupt=1;

//Заявка "от станка" заносится  в голову очереди

  queue=new ListNode<Client>(serving[i],queue);

  q_length++;

 }

 else                                 //свободный станок найден


 {

  serving[k]=serving[i];

  to_serve[k]=to_serve[i];

 }

 //Вышедший из строя станок переходит в состояние ремонта

 serving[i]=NULL;

 to_serve[i]=-1;

 to_repair[i]=(int)(get_erlang((float)repair_rate/100, repair_stages,0.001)*60);

 if (to_repair[i]==0) to_repair[i]=1;

 to_break[i]=-1;

 return;

}

 

void Machine::Repair_End(int i)   //завершение ремонта i-го станка

{

 to_repair[i]=-1;

 if (q_length==0) return;         //очередь пуста, ставить на обслуживание

                                  //нечего

//Очередь не пуста, заявку  из головы очереди ставим на  отремонтированный //станок

 serving[i]=queue->Data();

 if (serving[i]->to_serve>0)      //эта заявка ранее уже обслуживалась

{

 to_serve[i]=serving[i]->to_serve;

 serving[i]->to_serve=-1;

}

 else to_serve[i]=(int)get_normal(serve_median, serve_offset, 0.001);

 if (to_serve[i]==0) to_serve[i]=1;

 queue=queue->Next();             //сдвиг очереди

 q_length--;

//Разыгрываем новое время безаварийной работы

 to_break[i]=(int)(get_normal(break_median, break_offset, 0.001)*60);

 if (to_break[i]==0) to_break[i]=1;

}

 

void Machine::Set_End(int i)      //завершение наладки i-го станка

//Код этого метода такой  же, как и код предыдущего, только  время //безаварийной работы не  разыгрывается

{

 to_setting[i]=-1;

 if (q_length==0) return;

 serving[i]=queue->Data();

 if (serving[i]->to_serve>0)

 {

  to_serve[i]=serving[i]->to_serve; serving[i]-> to_serve=-1;

 }

 else to_serve[i]=(int)get_normal(serve_median, serve_offset,0.001);

 if (to_serve[i]==0) to_serve[i]==1;

 q_length--;

 queue=queue->Next(); 

}

 

void Machine::run()   //диспетчер

{

 int i;


 ListNode<Client> *ptr=NULL;

//Фиксируем сломавшиеся станки

 for(i=0;i<volume; i++)

 {

  if (serving[i]!=NULL) to_break[i]--;

  if (to_break[i]==0)  Breakage(i);

 }

 if (to_arrival>0) to_arrival--;

 if (to_arrival==0)  Arrival();

//Осуществляем, если нужно,  переходы станков в новые состояния

 for(i=0;i<volume; i++)

 {

  if (serving[i]!=NULL) to_serve[i]--;

  if (to_serve[i]==0) Complete(i);

  if (to_setting[i]>0) to_setting[i]--;

  if (to_setting[i]==0) Set_End(i);

  if (to_repair[i]>0) to_repair[i]--;

  if (to_repair[i]==0)  Repair_End(i);


 }

//Инкремент времени пребывания  у всех заявок, находящихся в  системе

//...в очереди

 ptr=queue;

 while(ptr)

 {

  ptr->Data()->time++;

  ptr=ptr->Next(); 

 }

//...и обслуживающихся

 for(i=0;i<volume;i++)

  if (serving[i]!=NULL) serving[i]->time++;

//Запись статистики

  fprintf(que, "%d\n",  q_length);

 que_ave=que_ave*(1-1.0/(total+1))+((float)q_length)/(total+1);

 ro_ave=ro_ave*(1-1.0/(total+1))+((float)Busy())/(volume*(total+1)); 

}

 

Листинг программы файл List.h

 

template <class Type>               //это постоянная «заставка»

                                               //к класам и функциям

                                               //c парметризированным типом

class ListNode  {              

  private:

    ListNode<Type> *next;          //указатель на следующий элемент списка

      Type *data;                            //указатель на данные хранящиеся в элементе списка

 public:

   ListNode(Type *d, ListNode<Type> *n);       //конструктор

     ~ListNode();                                                   //деструктор

        Type *Data();                                              //метод для чтения данных

           ListNode<Type> *Next();                        //метод для чтения указателя

                                                                             //на следующий элемент

  void  PutNext(ListNode<Type> *n);                //метод для записи указателя

                                                                             //на следующий элемент

  void Print();                                                       //печать содержимого элемента списка

};

template <class Type>

ListNode<Type>::ListNode(Type *d, ListNode<Type> *n) : next(n), data(d){

}

template <class Type>

ListNode<Type>::~ListNode(){

 delete data;

}

template <class Type>


Type *ListNode<Type>::Data(){

 return data;

}

template <class Type>

ListNode<Type> *ListNode<Type>::Next(){

  return next;

}

template <class Type>

void ListNode<Type>::PutNext(ListNode<Type> *n){

  next=n;

}

template <class Type>

void ListNode<Type>::Print(){

  data->Print();               //предпологается наличие метода Print() для класса

                                       //имя которого будет подставленно в пользовательском коде

}

//Описание класса-шаблона  завершено, далее идут функции-шаблона, работающие

//не с отдельным элементом,  а со всеми списком

 

template <class Type>

void ListAdd(ListNode<Type> *head, ListNode<Type> *li) {

                                    //добавление нового элемента li в хвост списка с головой head

ListNode<Type> *old, *v;

                                    //ищем внешний хвост списка

for (v=head; v!=NULL; v=v->Next())

  old=v;

    old->PutNext(li);   //добавляем в след за найденым хвостом новый элемент списка

}

template <class Type>

ListNode<Type> *ListDelete(ListNode<Type> *head, ListNode<Type> *li) {

                                             //удаление элемента li из списка с голоыой head

                                             //функция возвращает указатель на голову нового списка

                                             //int j;

 ListNode<Type> *old, *o1;

 if (li==head){

                                                   //удаляемый элемент может быть головой списка

                                                   //в этом случае голова у списка меняется

  o1=head->Next();

     delete li;

        return o1;

 }

//Удаляемый элемент не  являеться головой списка. Голова остаеться прежняя

 for (ListNode<Type>* v=head; v!=li; v=v->Next()) 

//поиск элемента предшедствующего  удаляемому

  old=v;

      o1=li->Next();

          old->PutNext(o1);  

//предшествующий элеиент  теперь «видит» элемент стоящий  в списке вслед

//за удаленным

  delete li;

     return head;

}                          

                                              //печать всех элементов списка с головой head

template <class Type>

void ListPrint(ListNode<Type> *head){

 for (ListNode<Type>* v=head; v!=NULL; v=v->Next())

    v->Print();                          //подсчет количества элементов в списке с головой head

 }

template <class Type>

int ListCount(ListNode<Type> *head){

 int i; i=0;

  for (ListNode<Type>* v=head; v!=NULL; v=v->Next()){

      v->Print();

           i++;

     }

 return i;

}


 

Листинг программы файл random.h

 

#include<stdio.h>

#include<math.h>

#include<stdlib.h>

float get_exp(float mu)    //генератор случайных чисел, распределенных

                           //экспоненциально

{

  int r_num; float root, right;

  r_num=rand();                        /*получение случайного целого

                                       /числа*/

  right=((float)r_num)/(RAND_MAX+1);   /*проекция на интервал (0;1)*/

  root=-log(1-right)/mu;               /*вычисление значения обратной

                                       /функции*/

  return(root);

}

 

int get_uniform(int a, int b)

{ //Генерация равномерно распределенной  величины a+b

 int x, y;

 x=rand()%(b+1);

 y=rand()%2;

 if (y==0) return(a-x);

 return(a+x);

}

 

float get_triangle(float A, float B, float C)

{

  int r_num; float root, right;

  r_num=rand();                      //получение случайного целого

                                    //числа

right=((float)r_num)/(RAND_MAX+1);   //проекция  на интервал (0;1).                     


//Константа RAND_MAX=32767 (215-1) определена  в cstdlib

  if (right<(C-A)/(B-A)) root=A+sqrt(right*(B-A)*(C-A));

  else root=B-sqrt((1-right)*(B-A)*(B-C));

  return(root);

}

 

float get_pareto(float A, float B)

{

  int r_num; float root, right;

  r_num=rand();                    /*получение случайного целого числа*/

  right=(float)r_num/RAND_MAX+1;   /*проекция на интервал (0;1)*/

  root=A/(pow(1-right, (float)1.0/B));    /*вычисление значения обратной функции*/

  return(root);

}

 

Листинг программы файл normal.h

 

#include<cstdio>

#include<cmath>

#include<cstdlib>

float get_normal(float mean, float disp, float eps);

float simpson(float A, float B, float mean, float disp);

float equ(float bottom_bound, float top_bound, float mean, float disp, float almost_all, float eps, float right);

float function(float mean, float disp, float x);

float get_normal(float mean, float disp, float eps)

{

  int r_num;

  float root, bottom_bound, top_bound, almost_all, right;

  /*вычисление конечных аппроксимаций пределов интегрирования в соответствии с заданной точностью*/

  bottom_bound=mean-disp*sqrt(-log(2*M_PI*eps*eps*disp*disp));

  top_bound=mean+disp*sqrt(-log(2*M_PI*eps*eps*disp*disp));

  /*вычисление интеграла в этих пределах*/

  almost_all=simpson(bottom_bound, top_bound, mean, disp);

  r_num=rand();

  right=(float)r_num/32768;

  root=equ(bottom_bound, top_bound, mean, disp, almost_all, eps, right);

Информация о работе Моделирование работы станка с поломками