2 votos

programación genética función de aptitud

Estoy intentando escribir una función fitness en programación genética para ampliar el área ocupada por los puntos dentro del polígono. Hay algunos puntos cerca del centro del polígono, quiero ampliar estos puntos desde el centro hasta que esté justo dentro del polígono.

Utilizaba la diferencia entre el área ocupada por los puntos dentro del polígono y el área de fuera del polígono e intentaba minimizarla en la función de aptitud. Pero no se como usar esto para cambiar las coordenadas de los puntos y luego recalcular la diferencia de área y hacerlo iterativamente. He dado cómo la entrada y la salida debe ser similar.

Gracias de antemano.

Este es el código que he escrito hasta ahora.

require(rgp)
require(splancs)
require(grDevices)
functionSet1 <- functionSet("+", "*", "-", "/","^")
inputVariableSet1 <- inputVariableSet("x","y")
constantFactorySet1 <- constantFactorySet(function() rnorm(1))

outpolygon<-matrix(c(3.061188,2.517408,0.523754,-0.258800,0.981104,4.036885,
                     3.061188,4.069070,4.069070,2.695074,0.485581,-2.129055,
                     -2.653607,4.069070),nrow=7,byrow=F)
inpoints<-matrix(c(2.637644,-0.4456578,2.160003,0.8553066,1.501256,1.3137518,2.352020,-0.2643815,
                   1.254139,1.2241712,1.918191,0.6595725,1.453478,0.9153824,1.900110,1.0607272,
                   1.648038,0.6847361,2.194931,2.2842159),nrow=10,byrow=T)

plot(-10:10,xlim=c(-5,5),ylim=c(-5,5))
polygon(outpolygon[,1],outpolygon[,2])
points(inpoints[,1],inpoints[,2])

fitnessFunction1 <-  function(f){
  if(all(point.in.polygon(inpoints[,1],inpoints[,2],outpolygon[,1],outpolygon[,2])!=0)){
    rmse(areapl(inpoints[chull(inpoints[,1],inpoints[,2]),]),areapl(cbind(outpolygon[,1],outpolygon[,2])[chull(outpolygon[,1],outpolygon[,2]),]))
  }else{
    rmse(1000,0)
  }
}

gpResult1 <- geneticProgramming(functionSet=functionSet1,
                                inputVariables=inputVariableSet1,
                                constantSet=constantFactorySet1,
                                fitnessFunction=fitnessFunction1,    
                                stopCondition=makeTimeStopCondition(10))

best1 <- gpResult1$population[[which.min(sapply(gpResult1$population,
                                                fitnessFunction1))]]

enter image description here enter image description here

2voto

OliasailO Puntos 145

Hay varias formas de hacerlo. La forma más fácil sería en realidad con un GA, no un GP. En este caso, usted tendría una matriz de enteros divididos en cuadrantes tales que:

[funcx1, valx1, funcy1, valy1, funcx2, valx2, funcy2, valy2, ... , funcxn, valxn, funcyn, valyn]

Tu función de ajuste tomaría el módulo de la funcxi y obtendría la función correspondiente. Luego, aplicarías el número en valxi de esa función al valor x correspondiente. Dados los puntos devueltos, calcularías el área como has dicho y castigarías al individuo si sobrepasa el área correspondiente (constante negativa o factor por grado sobre).

Alternativamente, si por alguna razón tiene que acudir a un médico de cabecera, existen dos vías principales. Si desea que el código sea genérico (es decir, usted aplicar el mismo trozo de código evolucionado para cada punto; nota: esto es mucho más difícil), necesitarías más no-terminales (es decir, funciones). Probablemente añadiría if-statements como mínimo. Las funciones definidas automáticamente (ADF) también estarían bien y algún tipo de función de agrupación como progn de Lisp. Basta con decir que el método GA es mucho más fácil.

La otra vía es utilizar una GP más estructurada y añadir en su lugar una función de asignación.

GPnonterminales: +, -, *, /, ^, = (todas las funciones vectoriales)

GPterminales: punto1, punto2, ..., punton, puntoaleatorio()

Utilizando una estructura Lispy, tu código sería algo así:

(* (= (= punto2 (* randompoint() (= punto2 randompoint()))) punto1) randompoint())

Luego, al evaluarlo, se harían todas las asignaciones desde las hojas hasta root con sobrescritura de los puntos inferiores por otros superiores. Así, en el ejemplo anterior, el punto2 se asignaría como un punto aleatorio (probablemente malo). El resultado se multiplicaría por un punto aleatorio y luego se sobrescribiría la asignación original hecha al punto2 con el resultado. Ese mismo resultado se asignaría al punto 1 y, finalmente, se multiplicaría por un punto aleatorio. Sin embargo, como no hay más asignaciones, el valor final se descartaría.

La razón por la que esto es "más estructurado" es que tienes que asegurarte de que la asignación nunca se produce en otra cosa que no sea un punto. Los GP basados en la gramática o guiados por la gramática son particularmente buenos en esto. Le remito a este artículo de Whigham (1995) que las explica:

http://sc.snu.ac.kr/courses/2007/fall/pg/aai/GP/whigham/whigham95grammaticallybased.pdf

Si utiliza un GP, en cualquier caso, usted va a tener que escribir algunas funciones para recorrer la lista para el formato que he descrito anteriormente. También sugiero el uso de puntos y funciones vectoriales en lugar de x e y para que tenga menos terminales para realizar un seguimiento de (y sus árboles de programa será más pequeño / proceso más rápido). Ah, y asegúrate de que la función randompoint() devuelve un punto específico (es decir, asegúrate de evaluarla antes de lo pones en el cromosoma o el código dará resultados inconsistentes -- muy malo, eso). Y haz que el rango de esos posibles puntos sea razonable (es decir, no vayas a 100 si estás en un espacio de 10 al cuadrado).

Te queda un poco de camino por recorrer, pero espero que esto te oriente en la dirección correcta.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X