Números aleatorios que se sumn a 100: Matlab

[Estoy dividiendo un número de población en matrices diferentes y quiero probar mi código usando números aleatorios por ahora.]

Pregunta rápida chicos y gracias por su ayuda de antemano –

Si uso;

100*rand(9,1) 

¿Cuál es la mejor manera de hacer que estos 9 números se sumen a 100?

Me gustaría tener 9 números aleatorios entre 0 y 100 que sumen 100.

¿Hay un comando incorporado que hace esto porque parece que no puedo encontrarlo?

Veo el error tan a menudo, la sugerencia de que para generar números aleatorios con una sum dada, uno solo usa un conjunto aleatorio uniforme, y simplemente escalarlos. Pero, ¿es el resultado verdaderamente uniforme al azar si lo haces de esa manera?

Pruebe esta simple prueba en dos dimensiones. Genere una gran muestra aleatoria, luego escale para sumr 1. Usaré bsxfun para escalar.

 xy = rand(10000000,2); xy = bsxfun(@times,xy,1./sum(xy,2)); hist(xy(:,1),100) 

Si fueran realmente uniformemente al azar, entonces la coordenada x sería uniforme, como lo haría la coordenada y. Cualquier valor sería igualmente probable que suceda. En efecto, para que dos puntos sumen a 1, deben estar a lo largo de la línea que conecta los dos puntos (0,1), (1,0) en el plano (x, y). Para que los puntos sean uniformes, cualquier punto a lo largo de esa línea debe ser igualmente probable.

xy histograma

Claramente, la uniformidad falla cuando uso la solución de escala. Cualquier punto en esa línea NO es igualmente probable. Podemos ver lo mismo que sucede en 3 dimensiones. Vea que en la figura 3-d aquí, los puntos en el centro de la región triangular están más densamente empaquetados. Esto es un reflection de la no uniformidad.

 xyz = rand(10000,3); xyz = bsxfun(@times,xyz,1./sum(xyz,2)); plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.') view(70,35) box on grid on 

xyzplot

De nuevo, la solución de escalado simple falla. Simplemente NO produce resultados verdaderamente uniformes sobre el dominio de interés.

¿Podemos hacerlo mejor? Bueno, sí. Una solución simple en 2-d es generar un único número aleatorio que designe la distancia a lo largo de la línea que conecta los puntos (0,1) y 1,0).

 t = rand(10000000,1); xy = t*[0 1] + (1-t)*[1 0]; hist(xy(:,1),100) 

Uniforme x + y = 1

Se puede demostrar que CUALQUIER punto a lo largo de la línea definida por la ecuación x + y = 1, en el cuadrado unitario, ahora es igualmente probable que se haya elegido. Esto se refleja en el histogtwig agradable y plano.

¿El truco de género sugerido por David Schwartz funciona en n-dimensions? Claramente lo hace en 2-d, y la figura a continuación sugiere que lo hace en 3 dimensiones. Sin una reflexión profunda al respecto, creo que funcionará para este caso básico en cuestión, en n-dimensiones.

 n = 10000; uv = [zeros(n,1),sort(rand(n,2),2),ones(n,1)]; xyz = diff(uv,[],2); plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.') box on grid on view(70,35) 

Sort truco

También se puede descargar la función randfixedsum del intercambio de archivos, la contribución de Roger Stafford. Esta es una solución más general para generar conjuntos aleatorios verdaderamente uniformes en el hipercubo de la unidad, con cualquier sum fija dada. Por lo tanto, para generar conjuntos aleatorios de puntos que se encuentran en la unidad 3-cubo, sujeto a la restricción que sumn 1.25 …

 xyz = randfixedsum(3,10000,1.25,0,1)'; plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.') view(70,35) box on grid on 

randfixedsum

Una manera simple es elegir 8 números aleatorios entre 0 y 100. Agregue 0 y 100 a la lista para dar 10 números. Ordenarlos A continuación, genere la diferencia entre cada par sucesivo de números. Por ejemplo, aquí hay 8 números aleatorios entre 0 y 100:

96, 38, 95, 5, 13, 57, 13, 20

Así que agrega 0 y 100 y ordena.

0, 5, 13, 13, 20, 38, 57, 95, 96, 100

Ahora resta:

5-0 = 5
13-5 = 8
13-13 = 0
20-13 = 7
38-20 = 18
57-38 = 19
95-57 = 38
96-95 = 1
100-96 = 4

Y ahí lo tienes, nueve números que sumn 100: 0, 1, 4, 5, 7, 8, 18, 19, 38. Que obtuve un cero y uno fue solo un poco de suerte.

No es demasiado tarde para dar la respuesta correcta

Hablemos de muestrear X1 … XN en el rango [0 … 1] de tal manera que Suma (X1, …, XN) sea igual a 1. Entonces usted podría reescalarlo a 100

Esto se llama distribución de Dirichlet , y debajo está el código para muestrear de él. El caso más simple es cuando todos los parámetros son iguales a 1, entonces todas las distribuciones marginales para X1, …, XN serían U (0,1). En general, con parámetros diferentes a 1s, las distribuciones marginales pueden tener picos.

—————– tomado de aquí ———————

El Dirichlet es un vector de variables gamma aleatorias a escala de unidad, normalizadas por su sum. Por lo tanto, sin verificación de errores, esto le dará eso:

 a = [1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0]; // 9 numbers to sample n = 10000; r = drchrnd(a,n) function r = drchrnd(a,n) p = length(a); r = gamrnd(repmat(a,n,1),1,n,p); r = r ./ repmat(sum(r,2),1,p); 

Tome una lista de números N – 1, cree una lista de números N + 1 insertando 0 y 100, ordene la lista y difúndalos hasta un total de N números.