{Fila com 1 servidor: Intervalo entre chegadas: Exponencial Ex. Posto bancario Duracao do servico: Exponencial com 1 caixa Usa a RAND2 como gerador de nos. aleatorios [0,1]. *********************************************************************** Variaveis principais usadas no programa CLIENTES_NA_FILA - Numero de clientes esperando na fila CLIENTES_RECEBENDO_SERVICO - Clientes sendo servidos (0 ou 1) CHEGADA(I) - Instante da chegada do (iesimo -1) cliente a ser atendido, assim CHEGADA(2) e' o instante de chegada do primeiro na fila de espera e CHEGADA(1) e' o instante da chegada do cliente sendo atendido INSTANTE_PROXIM0_EVENTO(I) - Instante da ocorrencia do proximo evento [1 (chegada) ou 2 (saida)] TIPO_PROXIMO_EVENTO - Tipo de proximo evento (1 ou 2) DURACAO_SERVICO - Duracao do servico do ultimo cliente a receber servico RELOGIO - Relogio de controle da simulacao NUMERO_EVENTOS - Numero de eventos (=2 ou seja, chegadas e servicos prestados) INSTANTE_ULTIMO_EVENTO - Instante da ocorrencia do ultimo evento usada para atualizar TEMPO_SERVIDOR_OCUPADO TEMPO_SERVIDOR_OCUPADO - Tempo total de ocupacao da caixa TEMPO_NO_SISTEMA - Tempo que um cliente fica no sistema SOMA_TEMPOS_NO_SISTEMA - Soma tempos no sistema de todos os clientes NO_SERVICOS_PRESTADOS - Numero de servicos prestados, ou seja, clientes atendidos MAIS_DE_4 - Numero de clientes que ficaram mais de 4 unidades de tempo na fila MAXIMO_NA_FILA - Maior numero de clientes na fila durante toda a simulacao INSTANTE_ULTIMO_EVENTO - Instante da ocorrencia do ultimo evento NUMERO_DE_CLIENTES - numero de clientes tratados pela simulacao RHO - Taxa de ocupacao do servidor PERC_MAIS_4 - Percentual de clientes que ficam mais de 4 unidades de tempo na fila TEMPO_TOTAL_NA_FILA - Soma dos tempos gasto pelos clientes na fila UNIDADE_DE_TEMPO - Unidade de medicao do tempo ***********************************************************************} uses crt; {Se estiver usando o Turbo Pascal para Windows, usar uses wincrt;} Label VOLTA; Var semente: double; {Variavel utilizada pela RAND2} G1,G2, U: Double; MEDIAEXP,ALFA,MEDIAEXP1,ALFA1: Real; {**********************************************************************} MAXIMO_NA_FILA,TIPO_PROXIMO_EVENTO,CLIENTES_RECEBENDO_SERVICO: Integer; NUMERO_DE_CLIENTES,NO_SERVICOS_PRESTADOS,MAIS_DE_4: Longint; NUMERO_EVENTOS,I: Integer; CLIENTES_NA_FILA: Longint; RELOGIO,TEMPO_NO_SISTEMA,TEMPO_SERVIDOR_OCUPADO,FMIN,DURACAO_SERVICO: Real; INSTANTE_ULTIMO_EVENTO,SOMA_TEMPOS_NO_SISTEMA,RHO,PERC_MAIS_4: Real; TEMPO_TOTAL_NA_FILA: Real; UNIDADE_DE_TEMPO: String[9]; INSTANTE_PROXIMO_EVENTO: Array[1..2] of Real; CHEGADA: Array[1..100] of Real; {**********************************************************************} {$I RAND2.PAS} {////////////////////////////////////////////////////////////////////// Funcao para a geracao de nos. aleatorios exponencialmente distribuidos ***********************************************************************} Function EXPONENCIAL(ALFA: Real; U: Double): Real; Begin EXPONENCIAL:= -(1/ALFA) * LN(U); End; {////////////////////////////////////////////////////////////////////// Inicializacao ***********************************************************************} Procedure INICIALIZACAO; Begin NUMERO_EVENTOS:=2; RELOGIO:=0.0; CLIENTES_NA_FILA:=0; CLIENTES_RECEBENDO_SERVICO:=0; TEMPO_SERVIDOR_OCUPADO:=0.0; MAXIMO_NA_FILA:=0; SOMA_TEMPOS_NO_SISTEMA:=0; MAIS_DE_4:=0; NO_SERVICOS_PRESTADOS:=0; TEMPO_TOTAL_NA_FILA:= 0.0; {*********************************************************************** Gera a primeira chegada Faz INSTANTE_PROXIMO_EVENTO[2] igual a infinito para indicar que uma partida e' impossivel com o sistema vazio ***********************************************************************} semente:= G1; U:= RAND2; G1:= semente; INSTANTE_PROXIMO_EVENTO[1]:= RELOGIO + EXPONENCIAL(ALFA,U); INSTANTE_PROXIMO_EVENTO[2]:= 1.0E30; End; {////////////////////////////////////////////////////////////////////// Rotina de avanco do tempo para determinar proximo evento e avancar relogio para o instante do proximo evento ***********************************************************************} Procedure AVANCA; Begin FMIN:=1.0E20; TIPO_PROXIMO_EVENTO:=0; For I:= 1 to NUMERO_EVENTOS do Begin If INSTANTE_PROXIMO_EVENTO[I] < FMIN Then Begin FMIN := INSTANTE_PROXIMO_EVENTO[I]; TIPO_PROXIMO_EVENTO:=I; End; End; If TIPO_PROXIMO_EVENTO = 0 Then Begin Writeln('LISTA DE EVENTOS FUTUROS VAZIA - ERRO'); HALT; End; RELOGIO:=INSTANTE_PROXIMO_EVENTO[TIPO_PROXIMO_EVENTO]; End; {////////////////////////////////////////////////////////////////////// Tratamento de uma chegada ***********************************************************************} Procedure CHEGADAS; {********************************************************************** Determina se o servidor esta' ocupado. Menor que 1 esta' livre. ***********************************************************************} Begin If CLIENTES_RECEBENDO_SERVICO < 1 Then Begin CLIENTES_RECEBENDO_SERVICO:= 1; CHEGADA[1]:=RELOGIO; {********************************************************************** Gera uma duracao de servico para a nova chegada e programa a partida desta nova chegada ***********************************************************************} semente:= G2; U:= RAND2; G2:= semente; DURACAO_SERVICO:= EXPONENCIAL(ALFA1,U); INSTANTE_PROXIMO_EVENTO[2]:=RELOGIO + DURACAO_SERVICO; {********************************************************************** Atualiza MAXIMO_NA_FILA e INSTANTE_ULTIMO_EVENTO ***********************************************************************} INSTANTE_ULTIMO_EVENTO:= RELOGIO; If CLIENTES_NA_FILA > MAXIMO_NA_FILA Then MAXIMO_NA_FILA := CLIENTES_NA_FILA; End {********************************************************************** O servidor esta' ocupado. Atualiza o estado do sistema e registra instante da nova chegada ***********************************************************************} Else Begin CLIENTES_NA_FILA:=CLIENTES_NA_FILA + 1; I:= CLIENTES_NA_FILA + 1; If I > 100 Then Begin Writeln('Fila maior que 100. Aumente dimensoes'); HALT; End; CHEGADA[I]:=RELOGIO; {********************************************************************** Atualiza estatisticas cumulativas TEMPO_SERVIDOR_OCUPADO e MAXIMO_NA_FILA ***********************************************************************} TEMPO_SERVIDOR_OCUPADO := TEMPO_SERVIDOR_OCUPADO + (RELOGIO - INSTANTE_ULTIMO_EVENTO); INSTANTE_ULTIMO_EVENTO := RELOGIO; IF CLIENTES_NA_FILA >= MAXIMO_NA_FILA Then MAXIMO_NA_FILA := CLIENTES_NA_FILA; End; {********************************************************************** Gera um intervalo entre chegadas e programa o proximo evento de chegada ***********************************************************************} semente:= G1; U:= RAND2; G1:= semente; INSTANTE_PROXIMO_EVENTO[1]:=RELOGIO+EXPONENCIAL(ALFA,U); End; {////////////////////////////////////////////////////////////////////// Rotina de servico ***********************************************************************} Procedure SERVICO; {********************************************************************** Atualiza estatisticas cumulativas TEMPO_SERVIDOR_OCUPADO, SOMA_TEMPOS_NO_SISTEMA, NO_SERVICOS_PRESTADOS e MAIS_DE_4MIN. CLIENTES_NA_FILA e' diminuida de modo que MAXIMO_NA_FILA nao muda. ***********************************************************************} Begin TEMPO_SERVIDOR_OCUPADO:= TEMPO_SERVIDOR_OCUPADO + (RELOGIO - INSTANTE_ULTIMO_EVENTO); INSTANTE_ULTIMO_EVENTO := RELOGIO; TEMPO_NO_SISTEMA:= RELOGIO - CHEGADA[1]; SOMA_TEMPOS_NO_SISTEMA:= SOMA_TEMPOS_NO_SISTEMA + TEMPO_NO_SISTEMA; NO_SERVICOS_PRESTADOS:= NO_SERVICOS_PRESTADOS + 1; If TEMPO_NO_SISTEMA > 4 Then MAIS_DE_4 := MAIS_DE_4 + 1; {********************************************************************** Verifica a condicao da fila ***********************************************************************} If CLIENTES_NA_FILA < 1 Then {********************************************************************** Fila vazia. Servidor desocupado. Proxima saida igual a infinito ***********************************************************************} Begin CLIENTES_RECEBENDO_SERVICO := 0; INSTANTE_PROXIMO_EVENTO[2]:=1.0E30; End {********************************************************************** Pelo menos 1 cliente na fila. Mover cada cliente 1 posicao ***********************************************************************} Else Begin For I:=1 to CLIENTES_NA_FILA do Begin CHEGADA[I]:=CHEGADA[I+1]; End; {********************************************************************** Atualiza estado do sistema ***********************************************************************} CLIENTES_NA_FILA:= CLIENTES_NA_FILA -1; TEMPO_TOTAL_NA_FILA:=TEMPO_TOTAL_NA_FILA + (RELOGIO - CHEGADA[1]); {********************************************************************** Gera nova duracao de servico para o cliente chegando para servico e programa proxima saida ***********************************************************************} semente:= G2; U:= RAND2; G2:= semente; DURACAO_SERVICO:= EXPONENCIAL(ALFA1,U); INSTANTE_PROXIMO_EVENTO[2]:=RELOGIO + DURACAO_SERVICO; End; End; {////////////////////////////////////////////////////////////////////// Impressao dos resultados ***********************************************************************} Procedure RESULTADOS; Begin RHO:=TEMPO_SERVIDOR_OCUPADO/RELOGIO; PERC_MAIS_4:=MAIS_DE_4/NO_SERVICOS_PRESTADOS; Writeln('Simulacao de um Sistema de Fila com 1 estacao de servico'); Writeln('--------------------------------------------------------'); Writeln('Intervalo entre chegadas (Exponencial) = ',MEDIAEXP:3:3, ' ',UNIDADE_DE_TEMPO); Writeln('Duracao do servico (Exponencial) = ',MEDIAEXP1:2:3, ' ',UNIDADE_DE_TEMPO); Writeln('--------------------------------------------------------'); Writeln('Total de clientes atendidos = ',NO_SERVICOS_PRESTADOS); Writeln('Taxa de ocupacao do servidor = RHO = ',RHO:0:3); Writeln('Maximo de clientes na fila = ',MAXIMO_NA_FILA); Writeln('Percentual de clientes que esperaram mais de 4 ',UNIDADE_DE_TEMPO, ' = ',PERC_MAIS_4*100:0:2,' %'); Writeln('Tempo medio gasto por cliente na fila = Wq = ', (TEMPO_TOTAL_NA_FILA/NO_SERVICOS_PRESTADOS):3:3,' ',UNIDADE_DE_TEMPO); Writeln('Tempo medio gasto por cliente no sistema = W = ', (SOMA_TEMPOS_NO_SISTEMA/NO_SERVICOS_PRESTADOS):3:3,' ',UNIDADE_DE_TEMPO); Writeln('Tempo total de simulacao = ',RELOGIO:6:3,' ',UNIDADE_DE_TEMPO); End; {////////////////////////////////////////////////////////////////////// ROTINA PRINCIPAL *********************************************************************** Recebe os parametros de entrada e sementes para a geracao de numeros aleatorios ************************************************************************} Begin CLRSCR; VOLTA: Writeln('Qual a semente ? (1 - 2147483646) - Intervalo entre Chegadas '); Readln(semente); G1:= semente; Writeln('Qual a semente ? (1 - 2147483646) - Duração do Atendimento '); Readln(semente); G2 := semente; IF G1 = G2 Then Begin Writeln('SEMENTES IGUAIS - ERRO!!'); GOTO VOLTA; End; Writeln('Qual a unidade de tempo a ser usada ?'); Readln(UNIDADE_DE_TEMPO); Writeln('Qual o intervalo, em ',UNIDADE_DE_TEMPO, ' ,entre chegadas - EXPONENCIAL ?'); Readln(MEDIAEXP); ALFA:=1.0/MEDIAEXP; Writeln('Qual a media, em ',UNIDADE_DE_TEMPO, ',da duracao do servico - EXPONENCIAL ?'); Readln(MEDIAEXP1); ALFA1:= 1.0/MEDIAEXP1; Writeln('Quantos clientes na simulacao ?'); Readln(NUMERO_DE_CLIENTES); CLRSCR; {**********************************************************************} INICIALIZACAO; While (NO_SERVICOS_PRESTADOS < NUMERO_DE_CLIENTES) do Begin AVANCA; If TIPO_PROXIMO_EVENTO = 1 Then CHEGADAS Else SERVICO; End; RESULTADOS; End.