8
votes

Affectation des tâches de travailleur

Dans une simulation, les travailleurs doivent se déplacer autour d'une carte effectuant des tâches.

Chaque simulation 'tick', ils peuvent déplacer un carré.

Effectuer la tâche une fois qu'ils sont adjacents à cela prend 10 ticks.

Les carrés de tâches ne peuvent pas être transmis. Les carrés avec des travailleurs ne peuvent pas être passés. Plus d'un travailleur peut travailler sur un carré.

Les travailleurs ne sont pas en compétition les uns avec les autres; L'objectif est de compléter toutes les tâches le plus rapidement possible.

ajouté: Idéalement, l'algorithme doit être simple à conceptualiser et à mettre en œuvre simple. N'est-ce pas ce que tout le monde veut? C'est un grand avantage si son E.G E.G. Le modèle peut être mis à jour et réutilisé plutôt que recalculé de zéro souvent. Idéalement, il sera capable d'utiliser Optima local afin de ne pas essayer de brutter un problème de NP, mais d'éviter d'être gourmands et de réfléchir un peu, plutôt que des errances essentiellement aléatoires où les travailleurs paient peu des plans des autres. < / p>

Voici un exemple:

Entrez la description de l'image ici

Les travailleurs 1 et 2 doivent compléter les tâches sur les carrés A, B, C et D.

Comment décidez-vous quel travailleur fait quelle tâche?

Il semble évident que 1 devrait faire A et 2 devraient faire c.

1 est de 4 carrés d'A, alors vous aurez fini de le faire en 14 ticks. Où devrait-il aller ensuite et pourquoi?

Et quoi s'il y avait une autre tâche - E - est placé directement au-dessus de B?

Quelle est la logique qu'un travailleur utilise pour décider où procéder ensuite?

Qu'est-ce que j'ai essayé:

Ceci étant un jeu de RTS de Hobby, j'ai essayé de le faire si des travailleurs inutiles passent à la tâche la plus proche ou de passer à la tâche la plus proche qu'aucun autre travailleur.

Cette approche gourmande s'est révélée entrer dans l'inefficacité et que les tests de joueurs indiquent que cela clarifie son intenable. Étant donné que l'exploitation minière / bâtiment / agriculture stratégique est la clé du jeu, et parce que je ne veux pas que le joueur de micro-gérance et acheminez tous les travailleurs, je recherche un algorithme assez équitable et raisonnablement optimal que les travailleurs peuvent utiliser à la place.


7 commentaires

Cela ressemble à une variation de The Tsp .


Il est plus lié à Multi Agent et distribué AI que le TSP. Il a de nombreux paramètres comme combien chaque travailleur peut voir, avez-vous un nœud central ou pas et tant d'autres choses. Vous devez déterminer les spécifications d'environnement, puis proposer une solution.


Suis-je raison pour que de nouvelles tâches puissent apparaître à tout moment, quelles que soient les autres tâches et que vous souhaitez des tâches de mise à jour rapidement lorsque cela se produit?


@Jordangray absolument. Les tâches peuvent également être supprimées de la liste des tâches par l'utilisateur.


J'ai une question. Puisqu'il n'y a pas de solution directe pour votre problème (c'est TS) pourriez-vous peut-être élaborer sur vos meilleurs et les plus pires scénarios pour différents travailleurs? Par exemple, quel est le montant maximum de nœuds qu'un travailleur devra frapper? Combien de travailleurs simultanés regardons-nous?


Cross posté après ne pas avoir reçu les réponses qu'ils voulaient: GameDev.StaCKeXchange.com/questions / 61726 / ...


Essayez toutes les possibilités!


8 Réponses :


11
votes

Même avec un ouvrier, il s'agit d'un problème d'optimisation complet de NP-complet (il devient alors le problème du vendeur itinérant) alors oublions donc "optimal".

Si vous savez que le travailleur 1 traitera des tâches A1, A2, ..., travailleur 2 traitera les tâches B1, B2, ... et ainsi de suite, vous pouvez, après cette décision, essayez de résoudre le problème. Problèmes de vendeurs de voyage indépendants un par un, et vous obtenez les horaires et les chemins de tous vos travailleurs.

Cependant, le problème est que vous ne pouvez pas savoir combien de temps il faut pour compléter un ensemble de tâches A1, A2, ... pour un travailleur avant d'avoir résolu le problème du vendeur itinérant pour cet ensemble, car le temps de marche a une incidence sur le temps de la marche. temps total pour effectuer les tâches.

Parce que c'est juste un jeu et que les travailleurs peuvent être supposés être des penseurs optimaux, j'utiliserais un processus stochastique:

  1. attribue toutes les tâches à tous les travailleurs au hasard
  2. Utilisez un algorithme gourmand pour calculer une limite supérieure sur le temps de marche pour chaque travailleur du groupe de travail du travailleur
  3. Essayez un déplacement aléatoire, puis déplacez une tâche d'un travailleur à l'autre ou échangez des tâches entre deux travailleurs
  4. Acceptez ce mouvement basé sur la recherche tabu ou les principes de recuit simulés, selon que le mouvement diminue la limite supérieure de temps d'exécution maximal (temps de marche + temps d'exécution de la tâche), de sorte que l'objectif est de faire la fin de la dernière tâche tôt possible
  5. Après n itérations, arrêtez-vous et calculez de meilleures solutions aux sous-programmes de vendeurs itinérants E.g. en utilisant une recherche stochastique ou explicitement si les problèmes sont petits (par exemple moins de 10 tâches par travailleur)

2 commentaires

+1 J'étais sur le point de suggérer la même chose.


J'aime cette réponse d'un point de vue scientifique. Avec les connaissances supplémentaires dont nous parlons de jeu, je suis un peu désactivé si cette idée s'amusera aux joueurs à cause de plusieurs raisons. "Incertain" signifie que je doute un peu et peut-être que j'ai raison, peut-être pas. J'aime toujours l'approche du problème en général.



3
votes

Parce que c'est un jeu RTS, j'essaierais de choisir une approche simple, rapide et facile à comprendre.

  1. Il doit être rapide parce que la performance compte
  2. Il doit être facile à comprendre pourquoi un travailleur va ici et là parce que dans un jeu, vous voulez que des minions se comportent comme prévu. N'essayez pas de penser aux joueurs.

    Tout d'abord, bien sûr, j'essaierais l'approche gourmande. Mais vous avez déjà mentionné que cela ne fonctionne pas.

    Ensuite, j'essayerais quelque chose comme un algorithme gourmand de second ordre. Chaque travailleur choisit la tâche la plus proche A, puis choisit les tâches les plus proches B à côté de A. Ils essaient (!) Pour choisir des tâches, personne n'a choisi jusqu'à présent. Quelque chose comme ça.

    Gardez-le petit et simple. Et vous pensez: Peu importe quel algorithme vous avez choisi, là sera un cas où il échoue de manière misérablement. Après tout, il y a Pas de déjeuner gratuit .


0 commentaires

5
votes

Cela sonne bien beaucoup comme le problème du vendeur (déjà mentionné) Problème de vente (TSP, http://fr.wikipedia.org/ wiki / travell_salesman_problem ) pour plusieurs agents. Ce qui est en fait un problème similaire à plusieurs sacs à dos (MKP, http://fr.wikipedia.org/wiki/knapsack_problem#multiple_knapsack_problem < / a>) ou même emballage bin ( http://fr.wikipedia.org/wiki/bin_packing_problem ).

Il existe un groupe d'algorithmes qui pourraient convenir à cette situation, et on l'appelle «optimisation de la colonie des fourmis» (ACO, HTTP : //fr.wikipedia.org/wiki/ant_colony_optimization_algorithms ).

combiner les deux, il existe des implémentations qui utilisent ACO pour résoudre des problèmes MKP; Cela semble être un bon moyen d'aller dans ce cas, par exemple:

http://www.researchgate.net/publication/221246039_Probabilistic_Model_of_Ant_Colony_Optimization_for_Multiple_Knapsack_Problem


0 commentaires

3
votes

Je suggérerais quelque chose de similaire à APPROCHE TOBIMCAMOBI 'S, mais plus raffinée:

  • Initialisez un travail vide pour chaque travailleur et une heure z il faudra pour terminer cette file d'attente.
  • Donnez à chaque tâche une propriété d , définie sur 0. Cela signifie combien cette tâche "est déjà traitée" en fonction du plan actuel.
  • Répéter jusqu'à ce que tous les travailleurs ont au moins un emploi et ( z > une valeur fixe ou une quantité de temps donnée a passé):
    • Prenez l'un des travailleurs w avec minimal z .
      • SET p à la position de la dernière entrée de la file d'attente w S ou w s la file d'attente est vide.
      • boucle sur les tâches non dans cette file d'attente des travailleurs en ordre de distance avec p
        • Calculez Distance / D
        • Si vous trouvez un minimum pour cette valeur, ajoutez cette tâche à la file d'attente du travailleur, ajoutez la distance à la tâche + 7 à z et ajoutez 1 / z à d . Casser la boucle.

          Avant de l'exécuter, vous devez trier les travailleurs en fonction de la distance à la tâche la plus proche. Sinon, la première tâche est donnée assez au hasard et la première tâche est la plus importante.

          Vous pouvez mettre à jour cela chaque fois qu'un travail ou un travailleur est ajouté. Réutiliser certaines des valeurs précédentes (peut-être stocker des résultats intermédiaires, comme l'ajout de la correspondance z aux tâches de la file d'attente du travailleur), cette mise à jour doit être plutôt rapide.

          Cela doit également être mis à jour une fois de temps en temps, car cet algorithme devient assez inexact une fois que vous allez assez loin dans l'avenir.

          Le Distance / d La formule peut également avoir besoin de quelque résled, mais je suppose que des tests aideraient beaucoup ici.

          La définition de "minimum" est à vous de décider. Je recommanderais de prendre un Minumum local, peut-être vérifier 5 tâches supplémentaires au maximum. Trouver le minimum mondial semble inutilement coûteux.


1 commentaires

La façon dont vous avez présenté votre réponse est un modèle à d'autres réponses! :RÉ



7
votes

Au lieu d'assigner gourmandeusement les travailleurs à la tâche la plus proche, essayez d'assigner la tâche de gourmandise à son ouvrier «le plus proche», c'est-à-dire que le travailleur dont le chemin passe de près et a suffisamment de temps perdu pour le gérer. De cette façon, vous avez une notion (gourmande) du plus petit temps nécessaire pour compléter toutes les tâches.

Par exemple: P>

D est la «tâche la plus éloignée», même sans définir ce terme encore, donc attribuer D à 1. Il est de 15 + 10 unités, donc définissez t code> = 25 et le relâché sur 2 à 25. p>

Voici le coût de la distance Tâche suivante, en prenant en compte les itinéraires les plus courts. p> xxx pré>

mais voici le coût réel en fonction de l'idée gourmande; l'augmentation du temps maximum t code>. p> xxx pré>

car c a le coût le plus élevé (c'est la tâche la plus dangereuse d'une perspective gourmande), Attribuez C à 2. P>

Les coûts suivants sont les suivants: P>

    A   B   slack    A  B
1  10  22     0     10 22
2  21  11  (-)7     14  4


0 commentaires

2
votes

(Remarque: après tout cela, je vous rends compte que vous avez dit que vous avez dit 14 ticks car par "adjacent" que vous pensais "au-dessus de" pendant que je l'ai interprété comme "à côté" ... Alors gardez à l'esprit mes calculs sont basés sur mes calculs. cela, mais cela ne devrait pas changer le résultat de beaucoup.)

Mon premier instinct serait de créer d'abord une file d'attente indépendante pour chaque travailleur en fonction du temps optimal à compléter, en supposant qu'aucun autre travailleur n'existe et ne traite pas des conflits plus tard ( Notez que, selon mon interprétation, lorsque 1 est terminé avec A, alors B est plus proche que d que d, mais une chose essentielle que nous voulons empêcher est 1 prise B): P>

1 [A=13, D=24]
2 [C=17, B=28]


0 commentaires

3
votes

Je suppose que la gourmandise "en temps réel" s'avère être mauvaise, car les travailleurs se retrouvent sur la chasse à l'oie sauvage vers des tâches qui seront complètes ou presque donc au moment de leur arrivée. Je vais donc proposer un algorithme de planification: un moyen d'attribuer intelligemment chaque travailleur à une séquence de tâches où l'Union des séquences est une couverture.

Comme d'autres ont déclaré que le TSP est intégré à cette condition de planification, c'est donc un NP Problème dur. P>

Mais il y a un algorithme d'approximation de temps polynomial facile pour le TSP qui produit un chemin d'accès maximal de 2x de longueur optimale. Il suffit de calculer une arborescence minimale étendue comprenant tous les sites de travail plus l'un des travailleurs. Ensuite, le chemin évident traversant chaque bord une fois dans chaque direction touche chaque nœud. P>

Bien sûr, lors de la mise en route Vous pouvez "abeilles-line" passé déjà visité des nœuds. Cela signifie simplement émettre la séquence de tâches en parcourant le MST en pré-commande. En raison de l'inégalité du triangle, ce chemin est souvent un peu meilleur que 2 fois optimal. (Je suppose que les mesures diagonales sont autorisées ici. Sinon, ce n'est pas vrai, mais l'algorithme fonctionne toujours bien.) P>

Donc, une approche de la planification est la suivante: P>

  1. Compute un MST pour chaque travailleur et tous les sites de travail. li>
  2. Utilisez le MST associé à chaque travailleur w pour calculer un chemin de pré-commande: s_w, t_wi, i = 1, 2 .... Ici, s_w est l'emplacement de départ du travailleur W. et les T_WI sont des emplacements de tâches dans la commande w aura leur visiter. li>
  3. Faites maintenant une simple simulation entraînée par des événements pour créer un plan comme ci-dessous. (Il s'agit d'une simulation "intérieure" dans la simulation de jeu, juste pour construire un plan.) Li> ol>

    Dans l'algorithme ci-dessous, les événements incluent une heure d'apparition projetée et sont placées sur la file d'attente d'événement avec cette fois-ci comme clé. P>

    Let Arrive(W, T, L) be an arrival event of worker W 
      at task T starting from previous location L, traveling the shortest path
    Let Complete(W, T) be a completion event for worker W of task T
    
    For each worker W, place Arrive(W, T_W1, S_W) on the queue
    While events are left on the queue
      Remove an event E
      If E is an arrival Arrive(W, TW_i, L) 
        If TW_i has no worker yet, 
          Assign TW_i to W
          Schedule a future event Complete(W, TW_i) 10 time units in the future.
        Else // T has a worker
          Schedule Arrive(W, TW_{i+1}, L), if TW_{i+1} exists
      Else E is a completion Complete(W, TW_i)
        Schedule Arrive(W, TW_{i+1}, TW_i), if TW_{i+1} exists
    


2 commentaires

Une explication très claire; Je l'ai travaillé dans ma tête pour quelques scénarios et cela semble fonctionner. C'est l'approche que je vais mettre en œuvre.


@Will Cool. Revenez s'il vous plaît pour dire comment il s'est avéré!



1
votes

Je suppose que l'apparition des travailleurs a besoin de ressembler à ce qu'un humain ferait (l'algorithme doit affecter chaque travail en tant que potentiel humain). Si l'algorithme ne le fait pas, un joueur se demandera ce que l'IA est faire et probablement essayer de parcourir manuellement (même s'il est moins optimal). Je pense que toute solution "globe optimale" ne ressemblerait probablement pas à ce qu'un humain ferait ...

Donc, je dirais que votre algorithme initial (volonté) pourrait avoir une légère amélioration du travail. Laissez chaque travailleur se diriger vers le travail de vaccant le plus proche, mais simulez-le là-bas et arrêtez la simulation lorsque le travailleur atteint le travail ou un autre travailleur est gratuit qui est plus proche (alors que le travailleur prendra ce travail). Si aucun emploi de vaccant ne peut être atteint, choisissez le travail occupé le plus proche et y aidez-y.


0 commentaires