martes, 16 de abril de 2013

Evolución Gramatical, Sistemas de Trading y R (2/2)

-->
En una entrada anterior de este blog vimos lo que era una gramática, y cómo se podían utilizar las gramáticas para crear automáticamente sistemas de trading. En esta entrada vamos a ver cómo se puede implementar todo esto con R. Aunque el código es lo suficientemente genérico para poder utilizar cualquier gramática, vamos a seguir con nuestro ejemplo de gramática para la generación de números enteros, para no complicar demasiado la cosa.

Lo primero que tenemos es que definir nuestra gramática. Para ello utilizamos una lista de R con las reglas de producción. Cada elemento de la lista es una regla, y dentro de cada regla, las distintas opciones van como elementos en un vector. Seguimos el convenio de encerrar los símbolos no terminales entre '<' y '>', y dentro de una misma regla de producción separamos los diferentes tokens mediante espacios (si no lo hiciésemos así, tendríamos que recurrir a un analizador léxico, y eso lo complicaría todo). A continuación declaramos el símbolo inicial, y finalmente dentro de un bucle while() aplicamos las reglas de producción iterativamente a los símbolos no terminales hasta que todos los símbolos que queden en la cadena sean terminales.

En este caso hemos utilizado la función sample() para seleccionar aleatoriamente qué regla de producción tenemos que aplicar. En un entorno de producción real deberíamos reemplazar esta regla por algún método de búsqueda inteligente, tipo algoritmo genético o enjambre de partículas. Pero este es tema para una futura entrada del blog.

# Definición de la gramática
nt <- list(
    entero = c("<entero> <digito>", "<digito>"),
    digito = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
)

# Símbolo inicial
programa <- c("<entero>")

fin <- FALSE

while (!fin) {

    fin <- TRUE
    nprograma <- c()

    for(i in 1:length(programa)) {

        token <- programa[i]

        if( grepl("<.+>", token) ) {

            # Se trata de un símbolo no terminal, hay que parsearlo

            # Quitamos los marcadores < y >
            token <- substr(token, 2, nchar(token)-1)

            # Seleccionamos la regla adecuada
            regla <- nt[names(nt)==token][[1]]

            # Seleccionamos aleatoriamente una producción
            prod <- sample(regla, 1)

            # Parseamos la producción a aplicar y la añadimos
            nprograma <- c(nprograma, unlist(strsplit(prod, " ")))

            # Tenemos que hacer otra iteración
            fin <- FALSE

        } else {

            # Se trata de un símbolo terminal, lo añadimos tal cual
            nprograma <- c(nprograma, token)

        }

    }

    programa <- nprograma

}

# Programa final
sistema <- paste(programa, collapse="")

print(sistema)

No hay comentarios:

Publicar un comentario