Pregunta

Estoy escribiendo un programa que intenta duplicar el algoritmo discutido al comienzo de este artículo,

http://www-stat.stanford.edu/~cgates/persi/papers/mcmcrev.pdf

F es una función de Char a Char. Suponga que PL (f) es una medida de 'plausibilidad' de esa función. El algoritmo es:

Comenzando con una suposición preliminar en la función, digamos F, y una función entonces nueva F* -

  • Calcule pl (f).
  • Cambie a F* haciendo una transposición aleatoria de los valores F asigna a dos símbolos.
  • Calcular PL (f*); Si esto es más grande que PL (f), acepte f*.
  • Si no, voltee una moneda PL (F)/PL (F*); Si surge cabezas, acepta f*.
  • Si el lanzamiento de la moneda sube las colas, quédese en f.

Estoy implementando esto usando el siguiente código. Estoy usando C# pero traté de hacerlo algo más simplificado para todos. Si hay un mejor foro para esto, hágamelo saber.

 var current_f = Initial();    // current accepted function f
 var current_Pl_f = InitialPl();  // current plausibility of accepted function f

 for (int i = 0; i < 10000; i++)
        {
            var candidate_f = Transpose(current_f); // create a candidate function

            var candidate_Pl_f = ComputePl(candidate_f);  // compute its plausibility

            if (candidate_Pl_f > current_Pl_f)            // candidate Pl has improved
            {
                current_f = candidate_f;            // accept the candidate
                current_Pl_f = candidate_Pl_f; 
            }
            else                                    // otherwise flip a coin
            {
                int flip = Flip(); 

                if (flip == 1)                      // heads
                {
                    current_f = candidate_f;        // accept it anyway
                    current_Pl_f = candidate_Pl_f; 
                }
                else if (flip == 0)                 // tails
                {
                    // what to do here ?
                }
            }
        }

Mi pregunta es básicamente si este parece el enfoque óptimo para implementar ese algoritmo. Parece que podría estar atascado en algunos máximos locales locales / mínimos locales a pesar de implementar este método.

EDITAR - Aquí está el método esencialmente Whats Behind Transpose (). Utilizo una tabla de diccionario / hash de tipo << char, char >> que las funciones candidatas usan para buscar una transformación de char -> char. Entonces, el método de transposición simplemente intercambia dos valores en el diccionario que dicta el comportamiento de la función.

    private Dictionary<char, char> Transpose(Dictionary<char, char> map, params int[] indices)
    {
        foreach (var index in indices)
        {
            char target_val = map.ElementAt(index).Value;   // get the value at the index

            char target_key = map.ElementAt(index).Key;     // get the key at the index

            int _rand = _random.Next(map.Count);   // get a random key (char) to swap with

            char rand_key = map.ElementAt(_rand).Key;

            char source_val = map[rand_key]; // the value that currently is used by the source of the swap

            map[target_key] = source_val; // make the swap

            map[rand_key] = target_val;
        }

        return map; 
    }

Tenga en cuenta que una función candidata que utiliza el diccionario subyacente es básicamente solo:

public char GetChar(char in, Dictionary<char, char> theMap)
{
     return theMap[char]; 
}

Y esta es la función que calcula PL (f):

    public decimal ComputePl(Func<char, char> candidate, string encrypted, decimal[][] _matrix)
    {
        decimal product = default(decimal);

        for (int i = 0; i < encrypted.Length; i++)
        {
            int j = i + 1;

            if (j >= encrypted.Length)
            {
                break;
            }

            char a = candidate(encrypted[i]);
            char b = candidate(encrypted[j]);

            int _a = GetIndex(_alphabet, a); // _alphabet is just a string/char[] of all avl chars 
            int _b = GetIndex(_alphabet, b);

            decimal _freq = _matrix[_a][_b]; 

            if (product == default(decimal))
            {
                product = _freq;
            }
            else
            {
                product = product * _freq;
            }
        }

        return product;
    }

No hay solución correcta

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top