Herramientas de usuario

Herramientas del sitio


ai:techniques:fuzzy_logic

Lógica difusa

Lógica difusa (Fuzzy logic) en general

La lógica difusa aparece debido a las limitaciones de la lógica convencional la cual sólo conseguimos dos soluciones extremas true o false. La lógica difusa se utiliza para encontrar más niveles entre estos dos extremos imitando así el modus operandi del ser humano realizando una toma de decisiones realista y proporcional al problema que se le plantee.
La implementación de la lógica difusa en un juego consta de tres pasos:

  1. Fuzzification (Ofuscación), que consiste en la conversión de un problema a un formato que pueda ser tratado mediante lógica difusa (conjuntos difusos).
  2. Aplicación de reglas difusas, es la combinación de los datos anteriores para elegir qué opción es la adecuada para resolver el problema.
  3. Defuzzification (Desofuscación); una vez tenemos seleccionada la acción a realizar, mediante la defuzzification se elige en qué medida es realizada.

Conjuntos difusos (Fuzzy Sets)

En algunos juegos sus elementos pueden adquirir cualidades, como por ejemplo inteligencia, daño, fuerza, hambre… Estas cualidades (o características) se consiguen en un grado de intensidad, un personaje puede estar poco o muy dañado; en lógica difusa lo que decimos es que existe un conjunto de elementos por cada una de estas características compuesto por esos elementos que las pueden adquirir, ese es el concepto de conjuntos difusos.

Cada conjunto difuso representa una de característica y un componente del conjunto lo es en cierto grado según cuanto tenga de esa característica, dicho grado se representa como un valor dentro de un rango, por ejemplo, en un rango de daño entre 0 y 1 un personaje que está dañado en 0,8 lo está más que aquel que está en 0,3. A este valor se le llama grado de membresía al conjunto (en este caso al conjunto daño).

Un elemento puede estar en varios conjuntos difusos a la vez (un personaje puede estar herido y hambriento) y, al contrario que en la lógica natural, un personaje puede estar en conjuntos opuestos, eso sí, en distinto grado en cada uno. Por ejemplo, nosotros no diremos que un personaje está dañado y sano a la vez, pero en términos de lógica difusa sí que podemos decir que un personaje tiene un grado de membresía al conjunto salud de 0,7 y al de daño de 0,3.

Fuzzification

Consiste en convertir datos correspondientes a los elementos que queremos tratar (generalmente números reales) en grados de membresía a los conjuntos difusos a los cuales han de pertenecer. Por ejemplo, coger el peso de una person en kilos y encontrar el grado en el que la persona tiene sobrepeso, peso ideal o delgadez.
Podemos representar el grado de membresía de un elemento a un conjunto mediante una función matemática y su gráfica correspondiente. Tomando por ejemplo la siguiente gráfico: Esta gráfica podría representar perfectamente el grado de membresía de un individuo a un conjunto difuso que indique el sobrepeso, este grado estaría en el eje de coordenadas vertical (entre 0 y 1) y el peso global estaría en el eje horizontal. Imaginemos que X_0 es 175kg y X_1 es 195kg, esto significaría que si el peso de una persona no llega a 175kg no tiene sobrepeso, pero si lo pasa tiene un grado de sobrepeso, un grado que sería sobrepeso al 100% si pasa de 195kg.
Para encontrar el grado de membresía de un elemento al conjunto difuso del sobrepeso deberemos aplicar la siguiente fórmula, que nos dará el valor entre 0 y 1 de y para la x dada (el peso del individuo). Dicha función, evidentemente, puede ser calculada mediante código:

double FuzzyGrade (double value, double x0, double x1) {
  double result = 0;
  double x = value;
  if(x <= x0)
    result = 0;
  else if(x >= x1)
    result = 1;
  else
    result = (x/(x1-x0))-(x0/(x1-x0));	
  return result;
}

Podemos representar la membresía a los conjuntos difusos utilizando distintas gráficas:

Cada una de ella con sus funciones correspondientes: Estas gráficas pueden ser combinadas para representar el grado de membresía a los conjuntos difusos respecto al peso a los que una persona puede pertenecer:

Por ejemplo, en los juegos de rol la forma de la derecha de combinar las gráficas solapandolas se utiliza para definir la personalidad de un personaje, de un extremo a otro podemos indicar cuan bueno o malo es (en nomenclaturas de juego de rol sería algo así como: neutral, neutral bueno, bueno, extremadamente bueno, neutral malvado, malvado, y extremadamente malvado).
Hemos de tener en cuenta que para conseguir reacciones de personajes que no sean bruscas es aconsejable seguir estos consejos:

  1. Solapar las funciones al rededor del 25% y no más.
  2. Es conveniente que el solapamiento de un de un grupo difuso no se haga con más de dos grupos.

Hedges

Las funciones de los extremos (hedges) se utilizan para modificar el grado de membresía. La idea principal es ampliar, como nosotros lo hacemos lingüísticamente, el concepto que rodea un conjunto difuso.
Los extremos más característicos son el “muy” y el “poco”, con ellos podemos decir que una persona es “muy inteligente” o “poco inteligente” y se definen como:
grado(muy A) = grado(A)^2
grado(poco A) = grado(A)^0.5

Variables difusas

Una variable difusa es el compuesto que forman los distintos conjuntos difusos que forman un concepto o dominio:
Velocidad = {lento, normal, rápido}
IQ = {cortito, normal, inteligente}

Operadores de lógica difusa

De la misma forma que en la lógica tradicional existen operadores (AND, OR, XOR, NOT) en lógica difusa también, sólo que no se tratan de igual forma. En lógica difusa tenemos la conjunción (AND), disjunción (OR) y la negación (NOT).
Partiendo de un ejemplo que muestre el coeficiente intelectual de una persona (IQ), podemos decir qué grado de inteligencia tiene, teniendo, por ejemplo, un individuo que es 0,75 inteligente (clever), 0,25 normal (average) y 0 cortito (dumb): Definimos…

  • Conjunción

grado(A and B) = Minimo (grado(A), grado(B))

  • Disjunción

grado(A or B) = Maximo (grado(A), grado(B))

  • Negación

grado(not A) = 1 - grado(A)

Reglas difusas

Cuando en lógica convencional tenemos la siguiente regla:

IF yo.Fuerte AND enemigo.Flojo THEN yo.atacar

la acción a realizar es fácil de elegir, si el personaje que decide es fuerte y el enemigo es flojo él atacará, pero si no es fuerte no atacará. En cambio en lógica difusa, siendo la misma condición, existen grados de fortaleza, si yo.Fuerte = 0,3 y enemigo.Flojo = 0,6, la regla es cierta al 0,3, entonces ataca o no ataca?

El tomar una decisión puede hacerse de distintas formas, se puede poner un punto de corte, por ejemplo 0,5, y si la regla supera ese valor entonces se toma como cierta. En el caso de arriba 0,3 no supera al 0,5 por lo que no se atacaría. También se puede tomar una decisión aleatoria dando una probabilidad de que sea cierta del valor dado, es decir, en la condición anterior habría una probabilidad de 30% de atacar y un 70% de no atacar.

Otras veces pueden haber varias reglas que pueden llevar al personaje a atacar, por ejemplo:

IF yo.Fuerte AND enemigo.Flojo THEN yo.atacar
IF yo.Grande AND enemigo.Verde THEN yo.atacar
IF yo.Poder > 10 AND yo.Salud > 5 THEN yo.atacar

Como antes, tenemos varias opciones en el momento de tomar una decisión, por ejemplo elegiríamos atacar si dos de las condiciones dan al menos 0,5, o podríamos coger la media del resultado de las reglas y si esta supera este punto de corte atacar, o dar la probabilidad de atacar a dicha media y escoger una decisión aleatoria.

Otra forma de decidir si seguir una decisión o no al utilizar varias reglas es utilizar una variable difusa adicional que nos indique la conveniencia de la decisión. Pongamos por ejemplo el de un soldado que ha de decidir si utilizar o no su arma en estos momentos para disparar al enemigo, el arma que lleva es un lanza-misiles, un arma que tarda un tiempo considerable en ser recargada y a la vez es fácil fallar si la distancia del enemigo es muy grande. Aquí tenemos tres factores a tener en cuenta correspondientes a tres variables difusas:

  1. Cuanta munición tenemos disponible (ammo status): poca (low), cantidad correcta (ok) o bastante cantidad (loads).
  2. Cuan lejos está el enemigo (distance to target): cerca (close), a media distancia (medium) o lejos (far).
  3. Cuanto nos interesa disparar (desirability), la adicional: no es conveniente (undesirable), conviene (desirable) o es muy conveniente (very desirable).

Diseñamos las reglas para el arma que lleva el soldado. Como nuestro soldado tardará bastante en recargarla es conveniente que el enemigo esté lejos, pero tampoco ha de estarlo mucho porque si no será muy probable fallar el tiro; por lo que se ha decidido que utilizar el lanzamisiles es la acción más conveniente si el enemigo está a una distancia media y nuestra munición disponible es suficiente como para que después podamos volver a disparar.

Regla 1 : IF Target_Far AND Ammo_Loads THEN Desirable 
Regla 2 : IF Target_Far AND Ammo_Okay THEN Undesirable 
Regla 3 : IF Target_Far AND Ammo_Low THEN Undesirable 
Regla 4 : IF Target_Medium AND Ammo_Loads THEN VeryDesirable 
Regla 5 : IF Target_Medium AND Ammo_Okay THEN VeryDesirable 
Regla 6 : IF Target_Medium AND Ammo_Low THEN Desirable 
Regla 7 : IF Target_Close AND Ammo_Loads THEN Undesirable 
Regla 8 : IF Target_Close AND Ammo_Okay THEN Undesirable 
Regla 9 : IF Target_Close AND Ammo_Low THEN Undesirable

Pongámonos en el lugar del soldado y analicemos la situación. Digamos que el enemigo está a una distancia de 200 píxels y tenemos disponibles 8 misiles.

  • 200 píxels, respecto a la variable lógica correspondiente a la distancia del enemigo, es un grado de membresía de 0.33 de Target_Far, 0.00 de Target_Close y 0.67 de Target_Medium.
  • 8 misiles respecto al Ammo_Status, es 0.00 de Ammo_Loads, 0.78 de Ammo_Ok y 0.20 de Ammo_Low.

Esto nos dá unos valores para las reglas anteriormente dadas:

  1. 0.33 AND 0.00 → MIN = 0.00 (desirable)
  2. 0.33 AND 0.78 → MIN = 0.33 (undesirable)
  3. 0.33 AND 0.20 → MIN = 0.20 (undesirable)
  4. 0.67 AND 0.00 → MIN = 0.00 (very desirable)
  5. 0.67 AND 0.78 → MIN = 0.67 (very desirable)
  6. 0.67 AND 0.20 → MIN = 0.20 (desirable)
  7. 0.00 AND 0.00 → MIN = 0.00 (undesirable)
  8. 0.00 AND 0.78 → MIN = 0.00 (undesirable)
  9. 0.00 AND 0.20 → MIN = 0.00 (undesirable)

Con los cuales podemos montar la matriz difusa asociativa (fuzzy associative matrix (FAM)):

Para decidir qué valor tomar en la variable difusa desirability lo que haremos será hacer un OR por cada uno de los valores agrupados por sus grupos correspondientes. Es decir, hacer los máximos:

  • Undesirable → MAX (0.33, 0.20, 0.00, 0.00, 0.00) → 0.33
  • Desirable → MAX (0.20) → 0.20
  • Very_Desirable = MAX (0.00, 0.67) → 0.67

Lo que podemos representar gráficamente como:
A partir de estos valores elegiremos la acción a realizar, esto se explica en el siguiente apartado.

Defuzzification

Consiste en convertir los valores conseguidos mediante las reglas difusas a un único valor, este será el que utilicemos para tomar una decisión. Existen distintas técnicas de defuzzification entre las cuales encontramos:

Mean of Maximum

Se escogen los valores más altos y se hace una media entre ellos. En el caso del soldado corresponden a los de Very Desirable que es una función que en y va creciendo de 0 a 0.67, y en x va desde 50 a 100 siendo el 66 el valor donde se queda constante (esto lo encontramos substituyendo en la fórmula de la función), es decir el primero más alto y por lo tanto, el 100 es el segundo más alto.
MOM = {66 + 100}/2 = 83


Este método tiene el inconveniente que no tiene en cuenta los demás grupos difusos.

Average of Maxima

Consiste en dar a cada conjunto difuso un valor representativo y aplicar la siguiente fórmula:
sum{}{}{(valorRepresentativo x gradoMembresía)}/sum{}{}{gradoMembresía}

Si por ejemplo, para el caso del soldado damos como valores representativos a Undesirable 12.5, a Desirable 50 y a Very Desirable 87.5 (son el punto medio de la porción de x donde se encuentra la y máxima del correspondiente grupo) el valor que nos daría sería:

{12.5 x 0.33 + 50 x 0.2 + 87.5 x 0.67}/{0.33 + 0.2 + 0.67} = 60.6

El valor representativo lo elige el programador, y puede elegirse según qué uso se le quiera dar. Un ejemplo sería el de un personaje que ha de elegir si atacar a un monstruo, huir o pasar de él, tras aplicar las reglas difusas para los conjuntos difusos huir, seguir hacia delante, atacar llega a los grados 0.7, 0.4 y 0.3 respectivamente y los valores representativos serían -10 para huir, 1 pasar de él y seguir hacia delante y 10 atacar. Corresponden a las velocidades que el personaje puede correr, -10 es correr hacia atrás a máxima velocidad y 10 correr hacia delante a máxima velocidad. El resultado sería -2.5, es decir que huiría, corriendo a una velocidad de 2.5.

{-10 x 0.7 + 1 x 0.4 + 10 x 0.3}/{0.7 + 0.4 + 0.3} = -2.5

Este es el método más recomendado de utilizar en la programación de juegos ya que dá un resultado más concreto que el Mean of Maximum. Existe otro llamado Centroid, su resultado es más exacto que este pero su cálculo es mucho más costoso.

Cómo interpretar el resultado?

El dilema que tenía nuestro personaje del apartado anterior sobre utilizar o no su lanzamisiles ya tiene una solución dependiendo del método de defuzzification (83 o 60.6). Como hemos indicado a partir de este valor podríamos decidir si utilizar o no el lanzamisiles aunque también puede tener otros usos, como por ejemplo si repetimos el proceso con cada arma de la que dispone el soldado este valor sería el que indicaría cual es el arma más conveniente a utilizar en el caso actual.

Método de Comb

A medida que agregamos variables el número de reglas que necesitaremos incrementa exponencialmente; para el ejemplo anterior del soldado necesitamos 9 reglas para 3 variables difusas (3 variables x 3 conjuntos), imaginemos que añadimos otra variable más, necesitaríamos 27 reglas, y así iría incrementandose (125, 625…). El método de Comb consiste en minimizar el número de reglas mediante equivalencias, haciendo que de 9 reglas pasen a 6, de 125 a 15, de 625 a 20 y así.
El método de Comb parte de la igualdad lógica [(P AND Q) then R] = [(P then R) OR (Q then R)].
Esto significa que las reglas que son IF a_1 AND ... AND a_n THEN c pueden ser reescritas como IF a_1 THEN c  OR ... OR  IF a_n THEN c

Por lo que unas reglas como

corner-entry AND going-fast THEN brake
corner-exit AND going-fast THEN accelerate
corner-entry AND going-slow THEN accelerate
corner-exit AND going-slow THEN accelerate
-----------
Posible resultado : Brake = 0.1    Accelerate = 0.6

Pueden ser expresadas como:

corner-entry THEN brake
corner-exit THEN accelerate
going-fast THEN brake
going-slow THEN accelerate
-----------
Posible resultado : Brake = 0.4    Accelerate = 0.9

En efecto el resultado es distinto, pero cuando se hace una defuzzification del resultado la elección será la misma: realizar una pequeña aceleración. Por ejemplo en el anterior caso del soldado pasaríamos de las anteriores 9 reglas a sólo estas 6:

IF Target_Close THEN Undesirable 
IF Target_Medium THEN VeryDesirable 
IF Target_Far THEN Undesirable 
IF Ammo_Low THEN Undesirable 
IF Ammo_Okay THEN Desirable 
IF Ammo_Loads THEN VeryDesirable

Esto daría como resultado

  • Target_Close → 0.00 (undesirable)
  • Target_Medium → 0.67 (very desirable)
  • Target_Far → 0.33 (undesirable)
  • Ammo_Low → 0.20 (undesirable)
  • Ammo_Okay → 0.78 (desirable)
  • Ammo_Loads → 0.00 (very desirable)

Por lo que

  • Undesirable → MAX (0.00, 0.33, 0.20) = 0.33
  • Desirable → MAX (0.78) = 0.78
  • VeryDesirable → MAX (0.67, 0.00) = 0.67

Y aplicando el Average of Maxima:

{12.5 x 0.33 + 50 x 0.78 + 87.5 x 0.67} / {0.33 + 0.78 + 0.67} = 57.1

Un resultado muy parecido al anterior.

Documentos

ai/techniques/fuzzy_logic.txt · Última modificación: 2020/05/09 09:25 (editor externo)