Новости           

Программы

Turbo Pascal

Игры

Документация

"Странности"

FAQ

Ссылки

Благодарности

Гостевая книга

От автора

Моделирование очередей обслуживания 

              В первом примере моделируется обслуживание в бакалейной лав-
         ке. Предположим, что лавка открыта 10 часов в день с пиковыми ча-
         сами с 12 до 13 и с 17 до 18 часов. Период с 12 до 13 часов имеет
         нагрузку  в  два раза,  а с 17 до 18 - в три раза больше обычной.
         При моделировании один генератор "порождает"  покупателей, второй
         генератор определяет время обслуживания покупателя,  а третий ре-
         шает,  в какую очередь пойдет покупатель. Цель моделирования сос-
         тоит  в  том,  чтобы  помочь управляющему найти оптимальное число
         очередей, которые должны работать в обычный день при условии, что
         число  людей в очереди в любое время не превышало бы 10 и кассиры
         не ожидали бы покупателей.
              Ключ к  данному типу моделирования состоит в создании многих
         процессов. Хотя Турбо Паскаль непосредственно не поддерживает па-
         раллельности,  вы можете моделировать с помощью множества процес-
         сов или с помощью главной программы  с  циклами.  Далее  показана
         программа с ее глобальными данными для моделирования очередей без
         поддержки процедур и функций:

              var
                gueues, count: array[0..9] of integer;
                open: array[0..9] of boolean;
                cust, time: integer;
                a1, a2: integer;
                y, x: integer;
                change: boolean;
                GraphDiver, GraphMode: integer;

              begin
                {переключение на графику,  используя режим 4 CGA/EGA}
                GraphDriver := CGA;
                GraphMode := CGAC1;
                InitGraph(GraphDriver, GraphMode, '');
                SetColor(2);
                SetLineStyle(SolidLn, 0, NormWidth);

                a1:=1; a2:=203; {инициализация переменных  генератора
                                 случайных чисел}
                change := FALSE;
                cust := 0;
                time := 0;

                for x:=0 to 9 do begin
                 gueues[x]:=0; {инициализация очереди }
                 open[x]:=FALSE; { нет покупателей или очередей в
                                   начале дня }

                 count[x]:=0; {счетчик очереди }
                end;

                OutTextXy(155, 190, '1             10');
                OutTextXy(8,190,'Check-out lines: ');

              { теперь начинается день открытием первой очереди }
              open[0] := TRUE;

                repeat
                 AddCust;
                 AddQueue;
                 Display;
                 CheckOut;
                 Display;
                 if (time>30) and (time<50) then AddCust;
                 if (time>70) and (nime<80) then begin
                   AddCust;
                   AddCust;
                 end;
                 time := time+1;
                until time>100; { конец дня }
                ReadLn;
                RestoreCrtMode;
              end.

              Элемент Graph.P включен,  чтобы программа могла использовать
         графические функции.

              Главный цикл управляет всем моделированием:

              repeat
                AddCust;
                AddQueue;
                Display;
                CheckOut;
                Display;
                if (time>30) and (time<50) then AddCust;
                if (time>70) and (time<80) then begin
                 AddCust;
                 AddCust;
                end;
                time := time+1;
              until time>100;  { конец дня }

              Функция AddCust использует либо Ran1,  либо Ran2 для генера-
         ции  числа  покупателей,  встающих  в очереди при каждом запросе.
         Функция AddQuece используется для помещения покупателей в очереди
         в соответствии с результатом Ran2, а также открывает новые очере-
         ди, если все существующие переполнены. Функция Display отображает
         программу моделирования.  Checkout использует Ran2 для назначения
         каждого покупателя в очередь с соответствующим увеличением  счет-
         чика очереди;  каждый вызов уменьшает счетчик на 1. Когда счетчик
         покупателей равен 0, очередь становится пустой.
              Переменная time  (время)  изменяет интенсивность,  с которой
         генерируются покупатели,  для того, чтобы отследить часовые пики.
         Каждый проход по циклу представляет одну десятую часа.
              На рис.7-4,  7-5 и 7-6 показаны  состояния  очередей,  когда
         time=28,  time=60 и time=88, что соответствует нормальному време-
         ни,  концу первого пика и концу второго пика, соответственно. От-
         метим, что в конце второго пика требуется максимум пять очередей,
         Если моделирующая программа написана правильно,  то в  бакалейной
         лавке оставшиеся пять очередей не нужны.

              gueue 1: 10      time: 28
              gueue 2: 8
              gueue 3: 0
              gueue 4: 0
              gueue 5: 0
              gueue 6: 0
              gueue 7: 0
              gueue 8: 0
              gueue 9: 0
              gueue 10: 0

                Очередь          ¦
                                 ¦
                                 ¦ ¦
                                 ¦ ¦
                                 ¦ ¦
                                 ¦ ¦
                                 ¦ ¦
                                 ¦ ¦
                               1                     10

              Рис.7-4. Состояние очередей, когда time=28:


              gueue 1: 6    time: 60
              gueue 2: 8
              gueue 3: 8
              gueue 4: 1
              gueue 5: 0
              gueue 6: 0
              gueue 7: 0
              gueue 8: 0
              gueue 9: 0
              gueue 10: 0

              Очередь              ¦ ¦
                                   ¦ ¦
                                 ¦ ¦ ¦
                                 ¦ ¦ ¦
                                 ¦ ¦ ¦
                                 ¦ ¦ ¦ ¦

                               1                 10

              Рис.7-5. Состояние очередей, когда time=60:



              gueue 1: 8    time: 80
              gueue 2: 9
              gueue 3: 6
              gueue 4: 6
              gueue 5: 7
              gueue 6: 0
              gueue 7: 0
              gueue 8: 0
              gueue 9: 0
              gueue 10: 0

              Очередь               ¦
                                  ¦ ¦
                                  ¦ ¦     ¦
                                  ¦ ¦ ¦ ¦ ¦
                                  ¦ ¦ ¦ ¦ ¦
                                  ¦ ¦ ¦ ¦ ¦
                                  ¦ ¦ ¦ ¦ ¦

                                 1                     10

              Рис.7-6. Состояние очередей, когда time=88:

              Вы можете непосредственно управлять различными переменными в
         программе. Во-первых, вы можете изменить путь и число прибывающих
         покупателей.  Вы также можете изменить функцию AddCost, чтобы она
         возвращала число покупателей в пиковые часы с большим или меньшим
         постепенным увеличением или уменьшением.  Программа предполагает,
         что  покупатели  случайным  образом выбирают,  в какую очередь им
         встать.  Такой подход справедлив для одних покупателей,  а другие
         будут выбирать самую короткую очередь.  Вы можете учесть это, из-
         менив функцию AddQueue так, чтобы она в некоторых случаях помеща-
         ла покупателей в самую короткую очередь,  а в некоторых - случай-
         ным образом.  При моделировании не учитываются такие случайности,
         как упавшая булка или буйный покупатель в очереди,  которые вызы-
         вают временные остановки очереди.
              Целиком программа выглядит следующим образом:

              program simulation; {моделирование очередей в бакалейной
                                  лавке }

              uses
                Graph;
              var
                gueues, count: array[0..9] of integer;
                open: array[0..9] of boolean;
                cust, time: integer;
                a1, a2: integer;
                y,x: integer;
                change: boolean;
                GraphDriver, GraphMode: integer;

              function Ran1: real;
              var
                t: real;
              begin
                t := (a1*32749+3) mod 32749;
                a1 := Trunc(t);
                Ran1 := Abs(t/32749);
              end; {Ran1}

              function Ran2: real;
              var
                t: real;
              begin
                t := (a2*10001+3) mod 17417;
                a2 := Trunc(t);
                Ran2 := Abs(t/17417);
              end; {Ran2}

              function CombRandom: real;
              {random selection of generators} 2
              var
                f: real;

              begin
                f := Ran2;
                if f>0.5 then CombRandom := Random
                else CombRandom:=Ran1;{случайный выбор генераторов}
              end; {CombRandom}

              { добавление покупателей в очередь }
              procedure AddCust;
              var
                f, r: real;

              begin
                if change then f:=Random {переключение между двумя }
                else f := Ran2;              {генераторами }

                if f>0.5 then
                 if f>0.6 then cust:=cust+1 {добавить одного покупателя}
                 else if f>0.7 then cust:=cust+2 {два покупателя}
                 else if f<0.8 then cust:=cust+3 {три покупателя }
                 else cust := cust+4; {четыре покупателя }
              end; {AddCust}
              { обслуживание покупателя }
              Procedure CheckOut;
              var
                t: integer;

              begin
                for t := 0 to 9 do
                begin
                 if gueues[t]<>0 then
                 begin
                   {получить время обслуживания }
                   while count[t]=0 do count[t]:=Trunc(Ran1+5);
                   {новый покупатель требует времени обслуживания }
                   count[t]:=count[t]-1;
                   if count[t]=0 then gueues[t]:=gueues[t]-1;
                   {удаление покупателя}
                 end;
                 if gueues[t]=0 then open[t]:=FALSE;{закрытие очереди}
                end;
              end; {CheckOut}

              {возвращается TRUE,  если очередь переполнена }
              function AllFull: Boolean;
              var
                t: integer;

              begin
                AllFull := TRUE;
                for t := 0 to 9 do
                 if (gueues[t]<10) and open[t] then AllFull:=FALSE;
              end; {AllFull}

              {данная процедура вводит новые очереди }
              procedure AddQueue;

              var
                t, line: integer;
                done: Boolean;

              begin
                done := FALSE;
                while cust<>0 do
                begin
                 if AllFull then
                 begin
                   t:=0;
                   repeat
                     if not open[t] then
                     begin
                       open[t]:=TRUE;
                       done:=TRUE;
                       end;
                     t:=T+1;
                     until done or (t=9);
                   end
                   else
                   begin
                     Line:=Trunc(Ran2*10);
                     if open[line] and (gueues[line]<10) then
                     begin
                       gueues[line]:=gueues[line]+1;
                       cust:=cust-1;
                     end;
                   end;
                   if AllFull and open[9] then cust:=0; {all full}
                 end;
              end; {AddQueue}

              {очистить символы длины, начиная с позиции Х, У }
              procedure ClrVed(x,y,len: integer);
              var
                i: integer;
                s: string[80];
              begin
                for i := 1 to len do
                 s := concat(Chr(219), Chr(219));
                SetColor(0);
                OutTextXy(x, y, s);
                SetColor(2);
              end; {ClrVid}

              {отображение экрана результатов моделирования очереди }
              procedure Display;
              var
                t: integer;
                value: string[80];
              begin
                cirVid(170, 10, 3);
                str(time, value);
                OutTextXy(120, 10, 'Time: ');
                OutTextXy(170, 10, value);
                for t := 0 to 9 do
                begin
                 {erase old line}
                 SetColor(0);
                 Line((t*10)+160, 180, (t*10)+160, 180);

                 {нарисовать   новое   состояние моделирования }
                 SetColor(2);
                 Circle((t*10)+160, 180, 3);
                 Line((t*10)+160, 180, (t*10)+160, 180-gueues[t]*10);

                 {дать также текстовый вывод }
                 OutTextXy(8, t*10, 'gueue');
                 str(t+1, value);
                 value       := concat(value, ':');
                 OutTextXy(56, t*10, value);
                 ClrVid(80, t*10, 3);
                 str(gueues[t], value);
                 OutTextXy(80, t*10, value);
                 end;
              end; {Display}

              begin
                {переключение на графику,  используя режим 4 CGA/EGA }
                GraphDriver := CGA;
                GraphMode := CGAC1;
                InitGraph(GraphDriver, GraphMode, '');
                SetColor(2);
                SetLineStyle(SolidLn, 0, NormWidth);

              a1:=1; a2:=203; {инициализация переменных генератора
                              случайных чисел }

                change:=FALSE;
                cust:=0;
                time:=0;

                for x := 0 to 9 do begin
                 gueues[x]:=0; {инициализировать очереди }
                 open[x]:=FALSE;{нет покупателей или очередей в начале
                                    дня }
                 count[x]:=0; {счетчик очереди }
                end;

                OutTextXy(155, 190, '1         10');
                OutTextXy(8, 190, 'Check-out lines; ');

              {теперь начинается день
               открытием первого пункта обслуживания
               }
              open[0]:=TRUE;

              repeat
                AddCust;
                AddQueue;
                Display;
                CheckOut;
                Display;
                if (time>30) and (time<50) then AddCust;
                if (time>70) and (time<80) then begin
                 AddCust;
                 AddCust;
                end;
                time:=time+1;
               until time>100; { конец дня }
               ReadLn;
               RestoreCrtMode;
              end.
              

(с)Все права защищены

По всем интересующим вопросампрошу писать на электронный адрес

    Rambler's Top100 PROext: Top 1000
    Rambler's Top100 Яндекс цитирования
Hosted by uCoz