# Dados ponderados con caras n -- matlab campo con dice campo con vectorization camp codereview Relacionados El problema

## Weighted dice with n faces

3

### problema

Español

Aquí encontrará algún código que devuelve el valor de una función de densidad multivariable de Bernoulli, para un dados con las caras, donde cada cara tiene su peso (el peso debe ser real positivo, no necesariamente suma = 1) proporciona el resultado de el lanzamiento.

` ` function face = weighted_dice(faces, weight)     % face = dice(faces, weight)      % input: row vector. Faces and weight of the same dimension!     % output: face is the discrete face after tossing a virtual dice with given     % faces and weight.     if size(faces, 2) ~= size(weight, 2) || size(weight, 2)<= 1         error('Input of function dice not well defined. See help')     end      num_weight = size(weight, 2);     % weight = [w1,w2,w3, .. ,w_n]     % cumulative_weight = [0, w1, w1+w2, w1+w2+w3, ... , sum(weight)]      cumulative_weight = zeros(1, num_weight + 1);     for j=1:num_weight        cumulative_weight(j+1) = sum(weight(1:j));     end      % pick a random value unif. distrib. betw. 0 and the sum of the weights.     rand_w = unifrnd(0, cumulative_weight(end));     % check in which interval of the cumulative_weight is this element      for j=1:num_weight        if rand_w >= cumulative_weight(j) && rand_w < cumulative_weight(j+1)            break        end     end      % assign the interval found to the value of the face     face = faces(j);   ``

e.g.

` ` disp(weighted_dice(['a','b','c','d','e','f'], [0.1, 0.1, 0.5, 0.1, 0.1, 0.1]))  beans = zeros(1,6); for i=1:1000     val = weighted_dice(['a','b','c','d','e','f'], [0.1, 0.1, 0.5, 0.1, 0.1, 0.1]);     if val == 'a'         beans(1,1) = beans(1,1) + 1;     elseif val == 'b'         beans(1,2) = beans(1,2) + 1;     elseif val == 'c'         beans(1,3) = beans(1,3) + 1;     elseif val == 'd'         beans(1,4) = beans(1,4) + 1;     elseif val == 'e'         beans(1,5) = beans(1,5) + 1;     elseif val == 'f'         beans(1,6) = beans(1,6) + 1;     end end  disp(beans)  ` `

¿Alguna idea de cómo contactar los dos para ciclo en la función?

Original en ingles

Here you find some code that returns the value of a multivariate Bernoulli density function - for a dice with n faces, where each face has its weight (weight must be positive reals, not necessarily sum = 1) it provides the result of the tossing.

``function face = weighted_dice(faces, weight)     % face = dice(faces, weight)      % input: row vector. Faces and weight of the same dimension!     % output: face is the discrete face after tossing a virtual dice with given     % faces and weight.     if size(faces, 2) ~= size(weight, 2) || size(weight, 2)<= 1         error('Input of function dice not well defined. See help')     end      num_weight = size(weight, 2);     % weight = [w1,w2,w3, .. ,w_n]     % cumulative_weight = [0, w1, w1+w2, w1+w2+w3, ... , sum(weight)]      cumulative_weight = zeros(1, num_weight + 1);     for j=1:num_weight        cumulative_weight(j+1) = sum(weight(1:j));     end      % pick a random value unif. distrib. betw. 0 and the sum of the weights.     rand_w = unifrnd(0, cumulative_weight(end));     % check in which interval of the cumulative_weight is this element      for j=1:num_weight        if rand_w >= cumulative_weight(j) && rand_w < cumulative_weight(j+1)            break        end     end      % assign the interval found to the value of the face     face = faces(j); ``

E.g.

``disp(weighted_dice(['a','b','c','d','e','f'], [0.1, 0.1, 0.5, 0.1, 0.1, 0.1]))  beans = zeros(1,6); for i=1:1000     val = weighted_dice(['a','b','c','d','e','f'], [0.1, 0.1, 0.5, 0.1, 0.1, 0.1]);     if val == 'a'         beans(1,1) = beans(1,1) + 1;     elseif val == 'b'         beans(1,2) = beans(1,2) + 1;     elseif val == 'c'         beans(1,3) = beans(1,3) + 1;     elseif val == 'd'         beans(1,4) = beans(1,4) + 1;     elseif val == 'e'         beans(1,5) = beans(1,5) + 1;     elseif val == 'f'         beans(1,6) = beans(1,6) + 1;     end end  disp(beans) ``

Any idea how to vectorise the two for-cycle in the function?

## Lista de respuestas

1

La mejor respuesta

Si está tratando de acelerar el código, haría un par de cosas. Tienes algún procesamiento redundante, como este:

` ` cumulative_weight = zeros(1, num_weight + 1); for j=1:num_weight    cumulative_weight(j+1) = sum(weight(1:j)); end  ` `

que se realiza 1000 veces dentro de Pessed_dice, pero en realidad solo necesita hacerlo una vez. También me desharía de las etiquetas de la cara por completo, porque no le importa lo que se llaman las 6 caras, solo se preocupa por la distribución de los resultados. Finalmente, puede usar el HISTC MATLAB incorporado para generar los resultados de una manera vectorizada.

` ` function face_index = new_weighted_dice(cumulative_weight)     % cumulative_weight = cumulative distribution function to draw against     % output: face_index is the discrete face after tossing a virtual dice with given     % faces and weight.   % pick a random value unif. distrib. betw. 0 and the sum of the weights. rand_w = unifrnd(0, cumulative_weight(end)); % check in which interval of the cumulative_weight is this element  for j=1:num_weight    if rand_w >= cumulative_weight(j) && rand_w < cumulative_weight(j+1)        break    end end  % assign the interval found to the value of the face face_index = j; end   ``

%%% -------------- Script principal

` ` cumulative_weight = zeros(1, num_weight + 1); for j=1:num_weight    cumulative_weight(j+1) = sum(weight(1:j)); end val = zeros(1,1000); for i=1:1000     val(i) = new_weighted_dice(cumulative_weight) end  beans = histc(val, cumulative_weight);   ``

corto, limpio, rápido.

If you're trying to speed up the code, I would do a couple of things. You have some redundant processing, such as this:

``cumulative_weight = zeros(1, num_weight + 1); for j=1:num_weight    cumulative_weight(j+1) = sum(weight(1:j)); end ``

which is performed 1000 times inside weighted_dice, but you really only need to do it once. I would also get rid of the face labels altogether, because you don't care what the 6 faces are called, you just care about the distribution of results. Finally, you can use the MATLAB builtin histc to generate the results in a vectorized fashion.

``function face_index = new_weighted_dice(cumulative_weight)     % cumulative_weight = cumulative distribution function to draw against     % output: face_index is the discrete face after tossing a virtual dice with given     % faces and weight.   % pick a random value unif. distrib. betw. 0 and the sum of the weights. rand_w = unifrnd(0, cumulative_weight(end)); % check in which interval of the cumulative_weight is this element  for j=1:num_weight    if rand_w >= cumulative_weight(j) && rand_w < cumulative_weight(j+1)        break    end end  % assign the interval found to the value of the face face_index = j; end ``

%%%--------------main script

``cumulative_weight = zeros(1, num_weight + 1); for j=1:num_weight    cumulative_weight(j+1) = sum(weight(1:j)); end val = zeros(1,1000); for i=1:1000     val(i) = new_weighted_dice(cumulative_weight) end  beans = histc(val, cumulative_weight); ``

Short, clean, fast.

1

Si está dispuesto a renunciar a tener una función real 998877766555544337 , una forma muy sencilla de generar los datos que desea es

` ` beans = histc(cumulative_weight, rand(1000,1))  ` `

Nota: Esto genera una matriz de 7x1, y solo deseas las primeras 6 entradas. Además, no tengo la caja de herramientas de estadísticas en esta máquina, por lo que usé ` rand `, pero como está trabajando en el intervalo [0,1] son ​​equivalentes.

If you are willing to give up having an actual `weighted_dice()` function, then a very simple way to generate the data you want is

``beans = histc(cumulative_weight, rand(1000,1)) ``

Note: this generates a 7x1 array, and you only want the first 6 entries. Also, I don't have the stats toolbox on this machine, so I used `rand`, but since you're working on the interval [0,1] they are equivalent.

6  ¿Cómo hacer que mis operaciones de Groupby y Transponen eficientes?  ( How to make my groupby and transpose operations efficient )
Tengo un DataFrame 3,745,802 filas y 30 columnas. Me gustaría realizar cierto 9988776665544331 y 9988776655544332 terminará finalmente con más columnas ...

6  Cálculo de estacionamientos y estadísticas de carga para un servicio compartido de automóviles  ( Calculating parking and charging statistics for a car sharing service )
Estoy buscando ayuda para diseñar mi código de manera más eficiente y también en mantener la pendiente de mi curva de aprendizaje personal empinada: Para un...

1  Vectorizamos gradiente 2D con contenedores espacialmente variables  ( Vectorize 2d gradient with spatially varying bins )
El siguiente código lleva a algunos valores ssh y resuelve las ecuaciones para el movimiento geostrófico (diapositiva 8 aquí ). La parte principal del Có...

5  Vectorización para simulación de temperatura  ( Vectorization for temperature simulation )
Soy nuevo en Matlab y me gustaría saber consejos para reducir el tiempo de procesamiento de dicho programa. El esquema del código real es muy similar al códig...

2  Encuentra el primer umbral de cruce en la matriz NUTPY  ( Find first threshold crossing in numpy array )
Dado los siguientes datos generados artificialmente: t_steps = 30 data = np.array([ np.arange(t_steps) * .05, np.arange(t_steps) * .1, np.aran...

3  Generar vectores de la unidad aleatoria alrededor del círculo  ( Generate random unit vectors around circle )
Estoy tratando de generar un montón de vectores de unidad de distribución uniformemente alrededor del círculo de la unidad. Aquí está mi código, que está func...

4  Vectorizando un bucle de conversión de coordenadas polares en un proceso de coincidencia de huellas dactilares  ( Vectorizing a polar coordinate conversion loop in a fingerprint matching process )
Estoy trabajando en una técnica de coincidencia de huellas dactilares y se necesita mucho tiempo de computación para obtener el resultado. Estoy tratando de i...

5  Evaluando una serie de polinomios legendra  ( Evaluating a series of legendre polynomials )
La siguiente función representa el potencial electrostático, en coordenadas esféricas, debido a un anillo de carga \$ Q = 1 \$ y RADIUS \$ R = 1 \$, colocado ...

2  Escalado e incremento de elementos no cero de una matriz adorable  ( Scaling and incrementing non zero elements of a numpy matrix )
Tengo una matriz adorable C y desea crear una copia cPrime , que tiene algún funcionamiento de la matriz original a todos los valores no cero. En el código...

4  Crosstabulación vectorizada en Python para dos matrices con dos categorías cada una  ( Vectorized crosstabulation in python for two arrays with two categories each )
Tengo dos listas de Python, label y presence1 . Quiero hacer la tabulación cruzada y obtener el recuento para cada bloque de cuatro, como A, B, C y D en ...