Voici un échantillonneur récursif assez évident qui est dans le meilleur des cas (en termes de poids ), mais exponentiel dans le pire des cas.O(d)ωi
Supposons que nous ayons déjà sélectionné et souhaitons choisir . Nous devons calculer
et choisissez avec probabilité
Le dénominateur sera différent de zéro pour tout choix valide d'échantillons .x1,…,xi−1xi
w(x1,…,xi−1,xi)=∑xi+1∈{−1,1}⋯∑xd∈{−1,1}(∑j=1dωjxj)+
xi=1w(x1,…,xi−1,1)w(x1,…,xi−1,1)+w(x1,…,xi−1,−1).
x1,…,xi−1
Maintenant, bien sûr, la question est de savoir comment calculer .w(x1,…,xi)
Si nous avons ce , alors pour tout avec les entrées principales , et donc devient:
C:=∑ij=1ωjxj≥∑dj=i+1|ωj|ω⋅x≥0xx1:iw
∑xi+1⋯∑xdω⋅x=ω⋅(∑xi+1⋯∑xdx)=∑j=1iωj(∑xi+1⋯∑xdxj)2d−ixj+∑j=i+1dωj(∑xi+1⋯∑xdxj)0=2d−iC.
Dans le cas contraire, , nous avons cela et ainsi .C≤−∑dj=i+1|ωj|ω⋅x≤0w(x1,…,xi)=0
Sinon, nous devons récapituler, en utilisant .w(x1,…,xi)=w(x1,…,xi,1)+w(x1,…,xi,−1)
Supposons que la mémoire n'est pas un problème et que nous pouvons mettre en cache tous les sous-calculs dans , dans une arborescence - jusqu'au point où nous atteignons l'un des "beaux" cas, après quoi tout les appels prennent un temps constant. (Nous devrons quand même calculer tout cet arbre pour sélectionner .) Ensuite, une fois cet arbre de calculs construit, l'échantillonneur ne prendra que temps. La question est de savoir combien de temps il faut pour construire l'arbre, ou de façon équivalente sa taille.w(1)w(−1)x1wO(d)
Nous atteindrons bien sûr les "jolis" cas plus rapidement si les sont triés, .ωiω1≥ω2≥⋯≥ωd
Dans le meilleur des cas, . Ensuite, nous frappons immédiatement un "joli" cas pour ou , donc la construction de l'arborescence prend un temps constant et l'échantillonneur entier prend le temps .|ω1|>∑dj=2|ωj|w(1)w(−1)wO(d)
Dans le pire des cas (triés), . Alors la question est: quelle est la taille totale de l'arbre?ω1=ω2=⋯=ωd
Eh bien, les premiers chemins à terminer sont bien sûr et de longueur . L'arbre est donc complet jusqu'à cette profondeur, et contient donc au moins nœuds. (Il en a plus; vous pouvez probablement le trouver avec un argument comme ceux utilisés dans les problèmes de ruine du joueur, mais je ne l'ai pas trouvé en deux minutes de recherche sur Google et ne m'en soucie pas particulièrement - est mauvais suffisant....)(1,1,…,1)(−1,−1,…,−1)⌈d/2⌉O(2d/2)2d/2
Si votre paramètre n'a que quelques très volumineux , il s'agit probablement d'une approche raisonnablement pratique. Si les sont tous de même ampleur, c'est probablement encore exponentiel et trop cher pour les grands .ωiωid