Número de combinações / permutações semi-aleatórias, devido a um conjunto de restrições

8

Fundo:

Existem cerca de 60 alunos no colégio interno em que trabalho. O conselheiro pediu ao meu colega e a mim que apresentássemos uma maneira melhor de arranjar assentos para o jantar do que à mão. Ele gostaria de tarefas para o resto do ano letivo. Ele também nos pediu para tentar resolver alguns dos problemas que ouvia de alunos e professores.

Restrições:

  • A maioria dos estudantes não é dos EUA; portanto, quando estão cercados por pessoas da mesma nacionalidade (ou seja, à mesa do jantar), falam o idioma em que são fluentes, em vez de praticar inglês,
  • As reclamações são feitas quando os alunos se sentam em uma determinada mesa "muitas" vezes no total,
  • ou se eles se sentarem na mesma mesa mais de duas vezes seguidas,
  • e alguns dos alunos não se dão bem, então não podem se sentar juntos.

Entrada:

No tempo de execução, o programa é fornecido com:

  • Um conjunto de pessoas,
  • Um conjunto de tabelas e
  • Cada mesa tem um número diferente de assentos (a repetição é permitida)

O tamanho dos dois conjuntos e o tamanho de cada tabela não muda entre cada atribuição.

Testes:

Estou usando 18 pessoas de diferentes nacionalidades e 4 tabelas de tamanho 3 a 6, inclusive. Escolhi números que achei que faziam sentido para esse conjunto de dados:

  • Não mais de três pessoas da mesma nacionalidade podem sentar-se juntas de cada vez
  • Nenhuma pessoa pode sentar-se à mesa mais de 4 vezes

Resultados:

Eu funcionei o gerador cerca de 15 vezes sem alterar os dados de entrada. A cada vez, ele vem de 6 a 12 "semanas" de tarefas.

Questões:

(menos para o mais importante)

  1. Por que obtenho um número diferente de atribuições geradas toda vez que executo o programa? O conjunto de dados não está mudando entre as execuções.
  2. Como encontro o ...
    • número mínimo de pessoas da mesma nacionalidade que podem se sentar em uma determinada mesa,
    • número mínimo de vezes em que se sentam em uma determinada mesa, enquanto
    • maximizar o número de atribuições geradas?
  3. Como garanto que esses são realmente os números corretos?

Editar:

Cada vez que gero uma nova tarefa, convoco Collections.shuffle(List)a lista de pessoas para randomizar seu pedido. Depois, passo a lista de tabelas e pessoas para um método de backtracking baseado na implementação das oito rainhas do kapilid no github para atribuir pessoas às tabelas.

Matthew D
fonte
honestamente, você pode tentar mathematics.se, essa é uma matemática bastante complexa.
Ryathal
@MatthewD Sua pergunta está bem aqui, e como você já encontrou uma resposta, não vejo por que devemos migrá-la. Se você quiser uma resposta mais matemática, poderá publicá-la novamente em Matemática , mas certifique-se de tornar a pergunta adequada para o site (leia as perguntas frequentes para obter mais informações), não copie e cole. Geralmente, não gostamos de ter a mesma pergunta (ou versões muito semelhantes) em vários sites, mas a sua parece estar no tópico de ambos os sites. poderia funcionar em matemática com alterações mínimas.
yannis

Respostas:

4

Atualizar:

Percebi que não respondi diretamente às suas perguntas. Suponho que ajude a ler toda a pergunta antes de disparar uma resposta ...

  1. Você não especifica qual algoritmo está usando para gerar os arranjos de assentos. Presumivelmente, existe algum elemento de variabilidade / aleatoriedade para criar atribuições diferentes para a duração do termo. Essa aleatoriedade é provavelmente o motivo pelo qual você obtém resultados diferentes a cada execução. Eu marcaria isso como working as designedum bug.

  2. uma. Você não especifica o algoritmo, portanto não sabemos realmente. Também não sabemos as contagens para cada nacionalidade. Pela lógica simples, 0 ou 1 seria o mínimo absoluto em uma mesa, mas suspeito que isso não seja muito útil para você. Em última análise, depende do número de cada nacionalidade e de como elas ocupam as outras tabelas.
    b. Execute seu programa, jogue os resultados em um banco de dados ou planilha e conte para você. Ou altere o programa para acompanhar essas coisas.
    c. A resposta aqui dependerá do número de cada nacionalidade e das outras restrições que você forneceu. O tamanho da tabela também o afetará. A resposta para esta parte é realmente apenas uma multiplicação do número de permutações potenciais. Felizmente (para mim), este é um site sobre programação, não estatísticas.

  3. Você tem dois problemas para enfrentar aqui. Primeiro, é validar que suas restrições refletem com precisão a realidade da situação. Converse com o conselheiro para verificar se suas restrições estão corretas. O segundo é verificar se seus resultados atendem às suas restrições. Escreva alguns métodos que verifiquem as tabelas de assentos retornadas quanto às restrições que você forneceu. E / ou inspecione manualmente os gráficos para verificar se estão bem.


Esta pergunta SO tem uma pergunta semelhante e sugere que isso equivale ao problema da embalagem do compartimento ou ao problema da mochila

Os convidados deste SO Question Seat com base em parâmetros priorizados parecem abordar exatamente o que você está procurando.

Esta pergunta do SO discute os problemas que o autor teve ao solucionar esse problema usando o algoritmo de empacotamento de lixeira. Sugiro que você leia as respostas para ter uma ideia melhor de como contorná-las.

E para a referência obrigatória xkcd, aqui está um link de seus fóruns discutindo a otimização do plano de assentos e usando um algoritmo genético modificado para resolver o problema.

Se este é um cenário real, então boa sorte. E se isso é apenas uma lição de casa, você tem material mais do que suficiente para avançar.

Comunidade
fonte
Obrigado pelos links! :) (Veja minha edição para saber como eu estou gerando atribuições)
Matthew D
@ MatthewD - parece que a aleatoriedade que você está vendo / perguntando é intencional e esperada. Sem suas outras restrições, existem 60! permutações da lista de alunos que você está usando para preencher as tabelas. Suas outras restrições reduzirão o número máximo de permutações, mas esse é um ponto de partida bastante grande.
Esse link que você sugeriu "seleciona a tabela com menos membros indesejáveis". Eu fiz isso, e agora ele está constantemente gerando soluções, não importa quantas semanas eu digo para gerar. Vou brincar com a forma como a implementei, além de ver quantas vezes ela falha em encontrar uma combinação perfeita, mas até agora parece que está funcionando. Muito obrigado!
Matthew D
Uma das respostas nas perguntas do SO declarou que é um problema difícil de NP, que é educado por "pode ​​não ser (completamente) solucionável". Se é nisso que você acaba se deparando, pode simplesmente enganar o problema para que ele resolva, informe o conselheiro sobre isso e siga em frente.