Estou tentando resolver o exercício a seguir, mas na verdade não tenho idéia de como começar a fazer isso. Encontrei um código no meu livro que parece com isso, mas é um exercício completamente diferente e não sei como relacioná-lo um com o outro. Como posso começar a simular chegadas e como sei quando elas terminam? Eu sei como armazená-los e calcular a, b, c, d de acordo com isso. Mas não sei como preciso simular a simulação de monte carlo. Alguém poderia me ajudar a começar? Sei que este não é um lugar onde suas perguntas sejam respondidas, mas apenas resolvidas. Mas o problema é que não sei por onde começar.
Um help desk de suporte de TI representa um sistema de filas com cinco assistentes atendendo chamadas de clientes. As chamadas ocorrem de acordo com um processo de Poisson com a taxa média de uma chamada a cada 45 segundos. Os tempos de serviço para o 1º, 2º, 3º, 4º e 5º assistentes são todas variáveis aleatórias exponenciais com os parâmetros λ1 = 0,1, λ2 = 0,2, λ3 = 0,3, λ4 = 0,4 e λ5 = 0,5 min-1, respectivamente (o O enésimo assistente de help desk possui λk = k / 10 min − 1). Além dos clientes que estão sendo assistidos, até dez outros clientes podem ser colocados em espera. Às vezes, quando essa capacidade é atingida, os novos chamadores recebem um sinal de ocupado. Use os métodos de Monte Carlo para estimar as seguintes características de desempenho,
(a) a fração de clientes que recebem um sinal de ocupado;
(b) o tempo de resposta esperado;
(c) o tempo médio de espera;
(d) a parcela de clientes atendidos por cada assistente de help desk;
EDIT: o que tenho até agora é (não muito):
pa = 1/45sec-1
jobs = rep(1,5); onHold = rep(1,10);
jobsIndex = 0;
onHoldIndex = 0;
u = runif(1)
for (i in 1:1000) {
if(u <= pa){ # new arrival
if(jobsIndex < 5) # assistant is free, #give job to assistant
jobsIndex++;
else #add to onHold array
onHoldIndex++;
}
}
fonte
Respostas:
Este é um dos tipos de simulação mais instrutivos e divertidos de executar: você cria agentes independentes no computador, permite que eles interajam, acompanhem o que fazem e estudam o que acontece. É uma maneira maravilhosa de aprender sobre sistemas complexos, especialmente (mas não limitado a) aqueles que não podem ser entendidos com análise puramente matemática.
A melhor maneira de construir essas simulações é com o design de cima para baixo.
No nível mais alto, o código deve parecer algo como
(Este e todos os exemplos subseqüentes são código executável
R
, não apenas pseudo-código.) O loop é uma simulação orientada a eventos :get.next.event()
encontra qualquer "evento" de interesse e passa uma descrição para eleprocess
, o que faz algo com ele (incluindo registrar qualquer informações sobre ele). Ele retornaTRUE
enquanto as coisas estiverem funcionando bem; ao identificar um erro ou no final da simulação, ele retornaFALSE
, encerrando o loop.Se imaginarmos uma implementação física dessa fila, como pessoas aguardando uma licença de casamento na cidade de Nova York ou uma carteira de motorista ou passagem de trem em quase qualquer lugar, pensamos em dois tipos de agentes: clientes e "assistentes" (ou servidores) . Os clientes se anunciam aparecendo; os assistentes anunciam sua disponibilidade acendendo uma luz ou sinal ou abrindo uma janela. Esses são os dois tipos de eventos a serem processados.
O ambiente ideal para tal simulação é um verdadeiro ambiente orientado a objetos no qual os objetos são mutáveis : eles podem mudar de estado para responder independentemente às coisas ao seu redor.
R
é absolutamente terrível para isso (até Fortran seria melhor!). No entanto, ainda podemos usá-lo se tomarmos alguns cuidados. O truque é manter todas as informações em um conjunto comum de estruturas de dados que podem ser acessadas (e modificadas) por muitos procedimentos separados e em interação. Adotarei a convenção de usar nomes de variáveis IN ALL CAPS para esses dados.O próximo nível do design de cima para baixo é codificar
process
. Ele responde a um único descritor de eventose
:Ele deve responder a um evento nulo quando
get.next.event
não houver eventos a serem relatados. Caso contrário,process
implementa as "regras de negócios" do sistema. Ele praticamente se escreve a partir da descrição na pergunta. Como funciona deve exigir pouco comentário, exceto para salientar que, eventualmente, precisaremos codificar sub-rotinasput.on.hold
erelease.hold
(implementar uma fila de espera do cliente) eserve
(implementar as interações cliente-assistente).O que é um "evento"? Ele deve conter informações sobre quem está agindo, que tipo de ação está sendo executada e quando está ocorrendo. Meu código, portanto, usa uma lista contendo esses três tipos de informações. No entanto,
get.next.event
só precisa inspecionar os horários. É responsável apenas por manter uma fila de eventos em queQualquer evento pode ser colocado na fila quando é recebido e
O evento mais antigo da fila pode ser facilmente extraído e passado para o chamador.
A melhor implementação dessa fila de prioridade seria uma pilha, mas isso é muito complicado
R
. Seguindo uma sugestão de The Art of R Programming, de Norman Matloff (que oferece um simulador de filas mais flexível, abstrato, mas limitado), usei um quadro de dados para armazenar os eventos e simplesmente pesquisá-lo pelo tempo mínimo entre seus registros.Há muitas maneiras pelas quais isso poderia ter sido codificado. A versão final mostrada aqui reflete uma escolha que eu fiz na codificação de como
process
reage a um evento "Assistant" e comonew.customer
funciona:get.next.event
apenas retira um cliente da fila de espera, depois senta e espera por outro evento. Às vezes, será necessário procurar um novo cliente de duas maneiras: primeiro, para ver se alguém está esperando na porta (por assim dizer) e, segundo, se alguém entrou quando não estávamos olhando.Claramente,
new.customer
enext.customer.time
são rotinas importantes , então vamos cuidar delas em seguida.CUSTOMERS
é uma matriz 2D, com dados para cada cliente em colunas. Possui quatro linhas (atuando como campos) que descrevem os clientes e registram suas experiências durante a simulação : "Chegou", "Servido", "Duração" e "Assistente" (um identificador numérico positivo do assistente, se houver, que serviu -los, e de outro modo-1
para sinais de ocupado). Em uma simulação altamente flexível, essas colunas seriam geradas dinamicamente, mas, devido à maneira como asR
pessoas gostam de trabalhar, é conveniente gerar todos os clientes desde o início, em uma única matriz grande, com seus tempos de chegada já gerados aleatoriamente.next.customer.time
pode dar uma olhada na próxima coluna desta matriz para ver quem vem em seguida. A variável globalCUSTOMER.COUNT
indica o último cliente a chegar. Os clientes são gerenciados com muita simplicidade por meio desse ponteiro, avançando para obter um novo cliente e olhando além (sem avançar) para espiar o próximo cliente.serve
implementa as regras de negócios na simulação.Isso é direto.
ASSISTANTS
é um quadro de dados com dois campos:capabilities
(fornecendo a taxa de serviço) eavailable
, que sinaliza na próxima vez em que o assistente estará livre. Um cliente é atendido gerando uma duração de serviço aleatória de acordo com os recursos do assistente, atualizando o horário em que o assistente se torna disponível e registrando o intervalo de serviço naCUSTOMERS
estrutura de dados. OVERBOSE
sinalizador é útil para teste e depuração: quando verdadeiro, emite um fluxo de frases em inglês que descreve os principais pontos de processamento.Como os assistentes são atribuídos aos clientes é importante e interessante. Pode-se imaginar vários procedimentos: atribuição aleatória, por alguma ordem fixa ou de acordo com quem está livre há mais tempo (ou mais curto). Muitos destes são ilustrados no código comentado:
O restante da simulação é realmente apenas um exercício de rotina para persuadir
R
a implementar estruturas de dados padrão, principalmente um buffer circular para a fila de espera. Como você não quer ficar louco com os globais, coloquei tudo isso em um único procedimentosim
. Seus argumentos descrevem o problema: o número de clientes a serem simulados (n.events
), a taxa de chegada de clientes, as capacidades dos assistentes e o tamanho da fila de espera (que pode ser definida como zero para eliminar a fila completamente).Retorna uma lista das estruturas de dados mantidas durante a simulação; o de maior interesse é a50 250
CUSTOMERS
matriz.R
torna bastante fácil plotar as informações essenciais nessa matriz de uma maneira interessante. Aqui está uma saída que mostra os últimos clientes em uma simulação mais longa de clientes.A experiência de cada cliente é plotada como uma linha do tempo horizontal, com um símbolo circular no momento da chegada, uma linha preta sólida para qualquer espera em espera e uma linha colorida pela duração da interação com um assistente (o tipo de cor e linha diferenciar entre os assistentes). Abaixo desse enredo de Clientes, há uma que mostra as experiências dos assistentes, marcando os horários em que eles estavam e não estavam envolvidos com um cliente. Os pontos finais de cada intervalo de atividade são delimitados por barras verticais.
Quando executada
verbose=TRUE
, a saída de texto da simulação se parece com:(Os números à esquerda são os horários em que cada mensagem foi emitida.) Você pode corresponder essas descrições às partes da plotagem Customers entre os tempos e .160 165
Podemos estudar a experiência dos clientes em espera, plotando as durações em espera pelo identificador do cliente, usando um símbolo especial (vermelho) para mostrar aos clientes que estão recebendo um sinal de ocupado.
(Todos esses gráficos não seriam um painel maravilhoso em tempo real para qualquer pessoa que gerencia essa fila de serviço!)
É fascinante comparar os gráficos e estatísticas que você obtém variando os parâmetros passados
sim
. O que acontece quando os clientes chegam muito rapidamente para serem processados? O que acontece quando a fila de espera é reduzida ou eliminada? O que muda quando os assistentes são selecionados de maneiras diferentes? Como os números e as capacidades dos assistentes influenciam a experiência do cliente? Quais são os pontos críticos em que alguns clientes começam a se afastar ou a ficar em espera por muito tempo?Normalmente, para questões óbvias de auto-estudo como essa, paramos aqui e deixamos os detalhes restantes como um exercício. No entanto, não quero decepcionar os leitores que podem ter chegado tão longe e estão interessados em tentar fazer isso sozinhos (e talvez modificá-lo e desenvolvê-lo para outros propósitos); portanto, em anexo abaixo está o código completo de funcionamento.
(O processamento neste site atrapalha a indentação em todas as linhas que contêm um símbolo , mas a indentação legível deve ser restaurada quando o código for colado em um arquivo de texto.)TEX $
fonte
R
deseja outra perspectiva (mas bastante semelhante) em simulações de fila. Enquanto escrevia esse pequeno simulador, fiquei pensando muito sobre o quanto aprendi estudando o código (na primeira edição do) texto de Andrew Tanenbaum Operating Systems / Design and Implementation. Também aprendi sobre estruturas práticas de dados, como pilhas, dos artigos de Jon Bentley no CACM e de sua série de livros sobre Programming Pearls . Tanenbaum e Bentley são grandes autores que todos deveriam ler.