2010-11-05 14 views
6

Quindi sto implementando un algoritmo euristico e ho trovato questa funzione.Funzione di densità di probabilità da una carta, implementata utilizzando C++, non funziona come previsto

Ho una matrice da 1 a n (da 0 a n-1 su C, w/e). Voglio scegliere un numero di elementi che copierò su un altro array. Dato un parametro y, (0 < y < = 1), voglio avere una distribuzione di numeri la cui media è (y * n). Ciò significa che ogni volta che chiamo questa funzione, mi dà un numero, tra 0 e n, e la media di questi numeri è y * n.

Secondo l'autore, "l" è un numero casuale: 0 < l < n. Sul mio codice di test attualmente sta generando 0 < = l < = n. E ho avuto il codice giusto, ma ora sto scherzando con questo per ora, e sono pigro per ricollegarlo.

Così ho codificato la prima parte della funzione, per y = 0,5 < y ho impostato a 0,2, e n a 100. Ciò significa che doveva restituire un numero compreso tra 0 e 99, con media 20. E i risultati non sono tra 0 e n, ma alcuni galleggiano. E il più grande è, più piccolo è questo galleggiante.

Questo è il codice di test C. "x" è il parametro "l".

//hate how code tag works, it's not even working now 
int n = 100; 
float y = 0.2; 
float n_copy; 

for(int i = 0 ; i < 20 ; i++) 
{ 
    float x = (float) (rand()/(float)RAND_MAX); // 0 <= x <= 1 
    x = x * n;        // 0 <= x <= n 
    float p1 = (1 - y)/(n*y); 
    float p2 = (1 - (x/n)); 
    float exp = (1 - (2*y))/y; 
    p2 = pow(p2, exp); 
    n_copy = p1 * p2; 
    printf("%.5f\n", n_copy); 
} 

e qui ci sono alcuni risultati (5 decimali troncato):

0.03354 
0.00484 
0.00003 
0.00029 
0.00020 
0.00028 
0.00263 
0.01619 
0.00032 
0.00000 
0.03598 
0.03975  
0.00704 
0.00176 
0.00001 
0.01333 
0.03396 
0.02795 
0.00005 
0.00860 

L'articolo è:

http://www.scribd.com/doc/3097936/cAS-The-Cunning-Ant-System

pagine 6 e 7.

o cercare " cAS: astuzia sistema ant "su google.

Quindi cosa sto sbagliando? non credo che l'autore abbia torto, perché ci sono più di 5 articoli che descrivono questa stessa funzione.

tutti i miei collegamenti a chi mi aiuta. Questo è importante per il mio lavoro.

Grazie :)

+1

Non utilizzare il codice. SO è strano, usa 4 spazi per indicare il codice. Basta copiare il codice, quindi selezionarlo tutto e quindi premere il pulsante 1010 per renderlo codice. –

+3

Questo perché le caselle di domande e risposte utilizzano Markdown: http://daringfireball.net/projects/markdown/syntax – zwol

risposta

4

dmckee è in realtà corretto, ma ho pensato che avrei elaborato di più e cercare di spiegare via parte della confusione qui. Potrei sicuramente fallire. f_s(l), la funzione che hai nella tua bella formula sopra, è la funzione di distribuzione della probabilità. Ti dice, per un dato input l tra 0 e n, la probabilità che l sia la lunghezza del segmento. La somma (integrale) per tutti i valori compresi tra 0 e n deve essere uguale a 1.

Il grafico nella parte superiore della pagina 7 confonde questo punto. Rappresenta lo l rispetto allo f_s(l), ma bisogna fare attenzione ai fattori esterni che mette a lato. Si noti che i valori nella parte inferiore vanno da 0 a 1, ma c'è un fattore di x n sul lato, il che significa che i valori l in realtà passano da 0 a n. Inoltre, sull'asse y c'è un x 1/n il che significa che questi valori in realtà non salgono a circa 3, vanno a 3/n.

Quindi cosa fai adesso? Bene, è necessario risolvere la funzione di distribuzione cumulativa integrando la funzione di distribuzione di probabilità su l che in realtà risulta non essere troppo male (l'ho fatto con Wolfram Mathematica Online Integrator usando x per l e usando solo l'equazione per y < = .5). Questo però utilizzava un integrale indefinito e tu sei davvero integrazione lungo x da 0 a l. Se impostiamo l'equazione risultante uguale a qualche variabile (per esempio z), l'obiettivo ora è risolvere per l in funzione di z. z qui è un numero casuale compreso tra 0 e 1. Puoi provare a utilizzare un risolutore simbolico per questa parte se desideri (vorrei). Quindi non solo hai raggiunto il tuo obiettivo di essere in grado di scegliere casualmente l s da questa distribuzione, hai anche raggiunto il nirvana.

Un po 'più lavoro

ti aiuto un po' di più. Ho provato a fare quello che ho detto per y < = .5, ma il sistema di algebra simbolico che stavo usando non era in grado di fare l'inversione (qualche altro sistema potrebbe essere in grado di farlo). Tuttavia, quindi ho deciso di provare a utilizzare l'equazione per.e < = 1. Questo risulta essere molto più semplice.Se cambio l a x in f_s(l) ottengo

y/n/(1 - y) * (x/n)^((2 * y - 1)/(1 - y)) 

L'integrazione di questo sopra x 0-l ho ottenuto (utilizzando di Mathematica in linea Integrator):

(l/n)^(y/(1 - y)) 

Non ottiene molto più bello di quello con questo genere di cose. Se regolo questo uguale a ze risolvere per l ottengo:

l = n * z^(1/y - 1)  for .5 < y <= 1 

Un rapido controllo è per y = 1. In questo caso, si ottiene l = n non importa quale z è. Fin qui tutto bene. Ora, si genera solo z (un numero casuale compreso tra 0 e 1) e si ottiene un l distribuito come desiderato per .5 < y < = 1. Ma aspetta, guardando il grafico a pagina 7 si nota che la probabilità la funzione di distribuzione è simmetrica. Ciò significa che possiamo utilizzare il risultato sopra riportato per trovare il valore per 0 < y < = .5. Abbiamo appena cambiamo l ->n-l e y ->1-y e ottenere

n - l = n * z^(1/(1 - y) - 1) 

l = n * (1 - z^(1/(1 - y) - 1))  for 0 < y <= .5 

In ogni caso, che dovrebbe risolvere il problema a meno che non ho fatto un errore da qualche parte. In bocca al lupo.

+0

Grazie, Justin. Avendo scritto la mia risposta sulle basi dell'intuizione e del titolo del post, sono andato in realtà, sai, a leggere il giornale - e sono contento di averlo fatto perché è pieno di tutti i tipi di cose buone che non avevo mai visto prima. In ogni caso, penso che tu abbia colto un paio di punti importanti qui. In particolare, la normalizzazione è superiore a [0, n), quando avrei ingenuamente aspettato oltre [0,1]. – dmckee

+0

@dmckee, si, penso che questa roba sia davvero bella. Ho letto un po 'su questi tipi di algoritmi, ma non molto. Voglio entrare di più in questa roba da solo. –

+0

Oh ragazzo ... ho visto quei fattori sul grafico, e ho capito l'asse x, ma il 'x 1/n' ho ignorato. Così ho letto il tuo testo, e ho ricordato i miei due anni di calcolo, ma devo dirti una cosa .. è in inglese, e non ho capito niente (im brasiliano, quindi il mio corso era in portoghese). Puoi aiutarmi a farlo nel modo più semplice? lo implementerò e voglio le migliori prestazioni, non troppi calcoli per ottenere un numero casuale di distribuzione normale. A proposito, questo è il mio ultimo incarico per la mia laurea, riguarda Ant Systems e QAP. – hfingler

0

Dato che per ogni valore di L, y, n come descritto, i termini che chiamano P1 e P2 sono entrambi in [0,1) e exp è in [1, ..) rendendo pow (p2, exp) anche in [0,1) quindi non vedo come otterresti un output con il range [0, n)

6

Puoi fraintendere ciò che ti aspetti da te.

Dato un PDF (correttamente normalizzato) e che desidera distribuire una distribuzione casuale coerente con esso, si crea la distribuzione cumulativa delle probabilità (CDF) integrando il PDF, quindi si inverte il CDF e si utilizza un predicato casuale uniforme come argomento della funzione invertita.


Un po 'più in dettaglio.

f_s(l) è il PDF ed è stato normalizzato su [0,n).

Ora è integrarlo per formare il CDF

g_s(l') = \int_0^{l'} dl f_s(l) 

Si noti che questo è un integrale definito a un endpoint specificato che ho chiamato l'. Il CDF è di conseguenza una funzione di l'. Supponendo di avere il diritto alla normalizzazione, g_s(N) = 1.0. In caso contrario, applichiamo un coefficiente semplice per risolverlo.

Quindi invertire la CDF e chiamare il risultato G^{-1}(x). Per questo probabilmente vorrai scegliere un particolare valore di gamma.

Quindi inserire un numero casuale uniforme su [0,n) e utilizzarli come argomento, x, su G^{-1}. Il risultato dovrebbe essere compreso tra [0,1) e dovrebbe essere distribuito in base allo f_s.

Come ha detto Justin, è possibile utilizzare un sistema di algebra per computer per la matematica.

+0

Quindi 'f_s (l)' è un CDF? Cosa devo fare per ottenere il numero casuale [0, n]? Scusate, non sono molto interessato alla probabilità, in realtà quasi non sono stato disapprovato (questa parola suona strana ... tradotta da google) sulla classe di probabilità. Ad ogni modo, non abbiamo imparato cose come questa ... Oh, grazie per la tua spiegazione :) – hfingler

+0

Quindi l'unico modo per ottenere il numero che voglio ([0, n] e con avg y), sta facendo quello che hai detto? Non penso che l'integrazione sarà una buona idea, poiché non è così semplice/veloce. Ho bisogno che questo sia il più veloce possibile, con il minor numero possibile di calcoli. Se DEVO farlo, penso che studierò alcune altre, più semplici, distribuzioni. – hfingler

+0

@polar: si desidera integrare e invertire * simbolicamente * se possibile, e implementare solo il risultato ('G^{- 1}') nel codice. Sicuramente ** non vuoi integrarti numericamente ad ogni passaggio! Se è necessario integrare numericamente, lo farebbe una sola volta e memorizzerà il risultato invertito come un istogramma normalizzato. Ci sono altre domande su quel dettaglio su come disegnare i numeri su un istogramma. Puoi anche trovare tutto questo nella maggior parte dei testi di analisi numerica. – dmckee

Problemi correlati