8
votes

Comment générer une distribution de k shots sur n ennemis

Je développe un jeu de combat de l'espace en Java dans le cadre d'un effort continu pour apprendre la langue. Dans une bataille, j'ai k em> navires tirant leurs armes à feu dans une flotte de n em> de leurs ennemis néfastes. En fonction du nombre de leurs ennemis frappés par le nombre de coups de feu, (chaque navire tire un coup qui frappe un ennemi), certains seront endommagés et certains détruits. Je veux savoir combien d'ennemis ont été touchés une fois, combien ont été frappés deux fois et ainsi de suite, de sorte que, à la fin, j'ai une table qui ressemble à ceci, pour 100 coups de feu:

Number of hits | Number of occurences | Total shots
----------------------------------------------------
       1       |        30            |      30
       2       |        12            |      24
       3       |         4            |      12
       4       |         7            |      28
       5       |         1            |       5


12 commentaires

Êtes-vous sûr de ne pas trop compliquer des choses? Si vous échantillonnez d'une distribution uniforme à l'aide de quelque chose comme aléatoire.nextint puis, en moyenne, chaque ennemi sera touché le même nombre de fois. Ou cherchez-vous un algorithme plus adaptatif - dites asvolé la distribution envers les ennemis qui n'ont pas encore été abattus?


@Boristhespider Il veut plus que le nombre moyen de tirs --- il veut la distribution du nombre de tirs.


@Markotopolnik qui sera le même (dans l'attente) que la distribution échantillonnée de - si vous échantillonnez d'un uniforme, la distribution sera uniforme ...


@Boristhespider afin que le nombre de navires touche une fois == numéro frappé deux fois == ...? Hautement improbable.


Supposons qu'un seul ennemi est touché 5 fois. Est-il important pour votre application si l'ennemi numéro 73 est touché 5 fois ou numéro ennemi 10234?


@Markotopolnik Je vois ce que vous voulez dire, je disais simplement que le nombre de hits (dans l'attente) sur chaque navire est donné par la distribution que les navires sont échantillonnés. La distribution réelle ne peut être connue que si elle est explicite explicitement. Donc, si l'OP veut en moyenne deux hits par bateau, puis tirant deux fois plus de coups que des navires le feraient. Il n'ya pas de moyen de connaître une priori ce que la répartition réelle serait plus qu'elle est possible de connaître l'issue d'une pièce de monnaie a priori - il doit être observé .


@Marko Durron597 Peu importe que l'ennemi est frappé cinq fois, juste le nombre d'ennemis frappés cinq fois.


@Boristhespider La distribution est connue à l'avance. Tout comme il est connu à l'avance que la moitié des flips seront des têtes. OP ne pose pas de questions sur une pièce de monnaie particulière.


@Boristhespider Je suppose qu'un nombre connu de hits, la moyenne serait donc n / k . J'aimerais savoir, par exemple, combien d'entre eux sont touchés exactement deux fois, ce qui devrait être une sorte de distribution. Si je peux créer un CDF pour le nombre de navires frappé deux fois, je peux inverser le CDF et générer un nombre aléatoire pour randomiser le nombre de navires touchés deux fois de manière à se rapprocher de ce qui se ferait si je brute la simulation. J'essaie de comprendre ce que ressemble au CDF. (Ou le PDF. L'intégration est rapide.)


@Bolisthespider L'équivalent pour les rouges de pièces de monnaie serait une distribution binomiale qui me dit que les chances de voir k têtes dans n se retourne et peuvent être utilisés pour se rapprocher des résultats de la retouche pièces de monnaie sans le faire.


C'est une question vraiment cool! BTW, il pourrait être utile de demander à cela sur le débordement de la pile de mathématiques.


J'ai posté une solution exacte pour calculer la distribution de probabilité, si quelqu'un est intéressé, ainsi que du code Java pour l'exécuter. C'est assez inefficace et ne peut pas se rapprocher des chiffres que je veux calculer, mais c'était un exercice de codage amusant néanmoins.


4 Réponses :


2
votes

Vous devez jeter un coup d'œil à Distribution multinomalienne , contraignante sur le cas où tous les p i sont égaux à 1 / k (veillez à noter que l'article Wikipedia sonne la signification de votre k et n ).


Tentative précédente de réponse

Peut-être qu'une approche comme ce qui suit sera fructueuse:

  1. La probabilité que un navire particulier est touché par un tir particulier est 1/1 ;
  2. La probabilité qu'un navire donné soit frappé exactement une fois après K Shots: h 1 = 1/1 (1-1 / N) k-1 ;
  3. comme ci-dessus, mais exactement deux fois: h 2 = (1 / N) 2 (1-1 / N) k-2 < / sup> , et ainsi de suite;
  4. Nombre attendu de navires frappé exactement une fois: n h 1 et ainsi de suite.


14 commentaires

Et si nous supposons que le navire frappé par un tir est choisi uniformément aléatoire que la répartition des hits est binomial - P (nombre de hits sur un spécifique est i) = binom (k, i) * (1 / N) ^ I * (1-1 / N) ^ (ki)


Il manque toujours le terme binomial!


Substitution (2) dans (4), cela donnerait au nombre attendu de navires touchés exactement une fois comme N * (1 / N) * (1-1 / N) ^ (K-1) = (1-1 / n) ^ (k-1) , qui est toujours inférieur à un, et donc n'a pas beaucoup de sens.


@Ckersch, nous devrions inverser ce problème et poser cela comme le nombre attendu de répétitions dans une combinaison .


Le nombre de tirs sur un navire est binomial, mais les probabilités ne sont pas indépendantes, donc je ne peux donc pas la généraliser. Par exemple, si j'ai cinq coups de feu et que le premier navire est touché cinq fois, la probabilité que le reste soit frappé du tout est de zéro.


@Ckersch Une valeur attendue ci-dessous a du sens, mais vous avez raison, l'expression est fausse


@Ckersch, oui, c'est vrai. Nous parlons de deux distributions différentes ici - la distribution du nombre de coups de feu frappant un navire et la distribution de la distribution du nombre de navires touchées par un nombre différent de tirs.


@Ckersch Si vous voyez cela comme tirant une balle k moments d'un sac avec des balles n , alors vous prenez en compte la dépendance. Vous avez donc une combinaison avec des répétitions.


@Markotopolnik qui est vrai si j'essaie de comprendre combien de fois j'ai tiré une balle, mais pas si j'essaie de comprendre combien de balles je me suis sorti deux fois.


@ckersch vous êtes intéressé par le nombre attendu de M-répétitions dans une combinaison moyenne, avec m allant de 0 à k .


@Markotopolnik ou, plus précisément, la distribution du nombre de répétitions M, avec M allant de 0 à k, bien que dans la pratique, je n'ai pas besoin d'aller jusqu'à K, car la probabilité que le nombre soit supérieur qu'on va devenir négligeable bien avant cela.


Eh bien, je pense que ce que vous êtes vraiment intéressé est la (K + 1) - la distribution (K + 1) -Dimensionnelle des nombres de ces répétitions M-répétitions simultanément pour toutes les valeurs K. Par exemple, si N = 2 et K = 3, que la question est que la question est, quelle est la probabilité du résultat possible (nombre de navires de 0 fois-hit = 1, nombre de navires de 1 fois à l'heure = 0, nombre de Navires 2 fois-hit-hit = 0 et nombre de navires 3 fois-hit = 1) et la probabilité du seul autre résultat (nombre de navires à 0 fois-hit = 0, nombre de navires de 1 fois à succès = 1, nombre de navires à 2 titres = 1, et nombre de navires de 3 fois à l'heure = 0). Est-ce que je l'obtiens correctement?


@elias Oui, mais cela semblait être très compliqué, alors je vais bien avec légèrement la foulée et l'informatique 0 hit ships, 1 hit-ships et 2 navires de frappe séparément, tant que la distribution regarde à peu près la même chose.


@ckersch Si vous souhaitez calculer ces distributions marginales, vous ne prenez pas compte de la dépendance des variables aléatoires associées, c'est-à-dire que la somme n'est pas garantie d'être la valeur que vous souhaitez être



2
votes

Je suppose que chaque coup a probablement atteint un mauvais bateau. Si h = 0, tous les coups vont manquer. Si h = 1, tous les coups vont frapper quelque chose em>.

Maintenant, disons que vous tirez des balles B. La valeur attendue des navires touch est simplement hs = h * b, mais ce ne sont pas des navires uniques em> hit. P>

Nous avons donc une liste de navires qui ont une liste de navires. La chance de tout navire ennemi spécifique étant frappé de Naviers ennemis est 1 / N. Par conséquent, la chance d'être dans les premiers emplacements K mais pas d'autres emplacements n'est p> xxx pré>

Notez que la réponse de Marko Topolnik. Le problème est qu'il s'agit d'un navire spécifique étant dans les premiers fentes K, contrairement à être dans n'importe quelle combinaison de lentes K. Nous devons la modifier en prenant sur le compte le nombre de combinaisons de klogs K dans les emplacements totaux HS: p> xxx pré>

Nous avons le risque d'un navire spécifique étant dans K emplacements. Eh bien, maintenant, nous devons envisager toute la flotte de N Navires: P>

(3 choose 1) * (1/2)^1 * (1-1/2)^(3-1) * 2
3 * 0.5 * 0.25 * 2 = 0.75

(3 choose 2) * (1/2)^2 * (1-1/2)^(3-2) * 2
3 * 0.5^2 * 0.5 * 2 = 0.75

(3 choose 3) * (1/2)^3 * (1-1/2)^(3-3) * 2
1 * 0.5^3 * 1 * 2 = 0.25

0.75 + 0.75*2 + 0.25*3 = 3 == Hs  **TRUE**


0 commentaires

2
votes

Si vous avez des navires et tirez des coups de feu, chaque numéro de hits de chaque navire suivra une distribution binominale où p = 1 / s et n = A:

http://fr.wikipedia.org/wiki/binomial_distribution

Vous pouvez interroger cette distribution et demander:

  • Quelle est la probabilité qu'un navire soit frappé 0 fois?
  • Quelle est la probabilité qu'un navire soit frappé 1 fois?
  • Quelle est probablement que pour un navire d'être frappé 2 fois?
  • Quelle est la probabilité qu'un navire soit frappé (santé max) ou plus? (Astuce: il suffit de soustraire 1,0 de tout ci-dessous)

    et multipliez-les par le nombre de navires, s, pour obtenir le nombre de navires que vous vous attendez à être frappé 0, 1, 2, 3, etc.. Cependant, comme il s'agit d'une attente et non d'un résultat rodé au hasard, les batailles iront exactement de la même manière à chaque fois.

    Si vous avez un faible nombre de navires, un nombre élevé de tirs, vous pouvez rouler une fois la distribution binominale une fois par bateau. Ou si vous avez un faible nombre de tirs, un nombre élevé de navires, vous pouvez placer au hasard chaque coup. Je n'ai pas encore pensé de manière cool d'obtenir la distribution aléatoire (ou une approximation aléatoire de celle-ci) du nombre élevé de tirs et de nombres élevés de coups de feu, mais il serait génial d'en savoir qu'un :)


0 commentaires

1
votes

a compris une façon de résoudre ce problème, et finalement jeté pour l'écrire à Java. Cela donne une solution exacte pour calculer la probabilité de M code> N'ayant pas été touchée donnée k code> navires et n code> coups. C'est cependant assez coûteux. Premièrement, un résumé de ce que j'ai fait:

La protabilité est égale au nombre total de façons de photographier les navires avec exactement m code> non frappé par le nombre total de façons de tirer des navires. xxx pré>

total est k ^ n code>, car chaque tir peut toucher l'un des navires k code> p>

Pour obtenir le numérateur, commencez par ncr (k, m) code>. Ceci est le nombre de façons de choisir m code> navires pour ne pas être touché. Ceci multiplié par le nombre de moyens de frapper km code> sans manquer est la probabilité totale. P> xxx pré>

maintenant pour calculer le second terme du numérateur . C'est la somme de toutes les distributions des plans de combien de façons qu'il existe pour une certaine distribution de tir. Par exemple, si 2 navires sont touchés par 3 balles, et chaque navire est touché au moins une fois, ils peuvent être touchés de la manière suivante: p> xxx pré>

Les distributions de tir sont égales à la longueur des compositions de K. Dans ce cas, nous aurions [2,1] et [1,2], la longueur 2 compositions de 3. P>

pour la première composition, [2,1], nous pouvons calculer le nombre de façons de générer ceci en choisissant 2 coups sur les 3 tirs pour frapper le premier navire, puis 1 des 1 tirs restants pour frapper le second, c'est-à-dire NCR (3,2) * NCR (1,1) . Notez que nous pouvons simplifier cela à 3! / (2! * 1!) Code>. Ce motif s'applique à toutes les pattes de tir, de sorte que le nombre de manières qu'un certain motif, p code> peut se produire peut être écrit comme n! / Prodsum (j = 1, km, p_j!) code>, dans lequel la notation indique la somme du produit de 1 à km code>, j code> est un index et p_j code> représente le J code> thème terme dans p code>. p>

si nous définissons p code> comme jeu de toutes les longueurs km code> COMPOSITIONS DE N CODE>, La probabilité de M CODE> Navires non frappés est alors: p>

import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.math3.util.ArithmeticUtils;

class Prob{
    public boolean listsEqual(Integer[] integers, Integer[] rootComp){
        if(integers.length != rootComp.length){
            return false;
        }
        for (int i = 0; i < integers.length; i++){
            if(integers[i] != rootComp[i]){return false;};
        }       
        return true;
    }

    public Integer[] firstComp(int base, int length){
        Integer[] comp = new Integer[length];
        Arrays.fill(comp, 1);
        comp[0] = base - length + 1;
        return comp;        
    }

    public Integer[][] enumerateComps(int base, int length){
        //Provides all compositions of base of size length

        if(length > base){return null;};
        Integer[] rootComp = firstComp(base, length);
        ArrayList<Integer[]> compsArray = new ArrayList<Integer[]>();

        do {
            compsArray.add(rootComp);
            rootComp = makeNextComp(rootComp);
        } while(!listsEqual(compsArray.get(compsArray.size() - 1), rootComp));

        Integer[][] newArray = new Integer[compsArray.size()][length];

        int i = 0;
        for (Integer[] comp : compsArray){
            newArray[i] = comp;
            i++;
        }

        return newArray;
    }

    public double getProb(int k, int n, int m){
        //k = # of bins
        //n = number of objects
        //m = number of empty bins

        //First generate list of length k-m compositions of n

        if((n < (k-m)) || (m >= k)){
            return 0;
        }

        int[] comp = new int[n-1];

        Arrays.fill(comp, 1);

        comp[0] = n - (k-m) + 1;

        //Comp is now the first 
        Integer[][] L = enumerateComps(n, k-m);

        double num = 0;
        double den = Math.pow(k, n);
        double prodSum;
        int remainder;

        for(Integer[] thisComp : L){
            remainder = n;
            prodSum = 1;
            for(Integer thisVal : thisComp){
                prodSum = prodSum * ArithmeticUtils.binomialCoefficient(remainder, thisVal);

                remainder -= thisVal;
            }

            num += prodSum;
        }

        return num * ArithmeticUtils.binomialCoefficient(k, m) / den;
    }

    public Integer[] makeNextComp(Integer[] rootComp){
        Integer[] comp = rootComp.clone();

        int i = comp.length - 1;
        int lastVal = comp[i];
        i--;

        for(; i >=0 ; i--){
            if (comp[i] != 1){
                //Subtract 1 from comp[i]
                comp[i] -= 1;
                i++;
                comp[i] = lastVal + 1;
                i++;
                for(;i < comp.length; i++){
                    comp[i] = 1;
                };
                return comp;                
            }
        }
        return comp;
    }
}


public class numbersTest {
    public static void main(String[] args){
        //System.out.println(ArithmeticUtils.binomialCoefficient(100,50));
        Prob getProbs = new Prob();

        Integer k = 10; //ships
        Integer n = 10; //shots
        Integer m = 4; //unscathed

        double myProb = getProbs.getProb(k,n,m);

        System.out.printf("Probability of %s ships,  %s hits, and %s unscathed: %s",k,n,m,myProb);
    }
}


0 commentaires