La Lógica Difusa proporciona un mecanismo de inferencia que permite simular los procedimientos de razonamiento humano en sistemas basados en el conocimiento. La teoría de la lógica difusa proporciona un marco matemático que permite modelar la incertidumbre de los procesos cognitivos humanos de forma que pueda ser tratable por un computador.
En la teoría clásica de conjuntos crisp (es decir, los conjuntos de toda la vida, donde un elemento pertenece o no pertenece al conjunto) un conjunto C se define sobre X mediante la función característica fC.
Este conjunto mapea, a su vez, el universo X en un conjunto de dos elementos, 0 o 1, donde la función fC(x) es 1 si el elemento x pertenece al conjunto C y 0 si el elemento x no pertenece al conjunto C. Si generalizamos esta función para que los valores asignados a los elementos del conjunto caigan en un rango particular y así indicar el grado de pertenencia de los elementos a ese conjunto, tendremos una función de pertenencia de un determinado conjunto difuso. La función de pertenencia μA por la que se define un conjunto difuso A, sería:
μA=X→[0,1]Donde μA(x)=1 si x está totalmente en A, μA(x)=0 si x no está en A y 0<μA(x)<1 si x está parcialmente en A. Este valor entre 0 y 1 representa el grado de pertenencia (también llamado valor de pertenencia de un elemento x a un conjunto A.
Las tres operaciones básicas que se definen sobre conjuntos crisp (complemento, unión e intersección), pueden generalizarse de varias formas en conjuntos difusos. No obstante, existe una generalización particular que tiene especial importancia. Cuando se restringe el rango de pertenencia al conjunto [0,1], estas operaciones "estándar" sobre conjuntos difusos se comportan de igual modo que las operaciones sobre conjuntos crisp.
Su forma más básica es: 1−x
Tenemos tres formas principales de definir la unión:
También tenemos varias formas de definirla:
Mediante el uso de conjuntos difusos es posible dotar de significado matemático a proposiciones como "este coche es pequeño", "Pedro es alto" o "el crecimiento es lento". Las reglas difusas se utilizan para representar y razonar con conocimiento expresado en forma de primitivas enunciadas en lenguaje natural. La inferencia difusa puede definirse como el proceso de obtener un valor de salida para un valor de entrada empleando la teoría de conjuntos difusos.
Es posiblemente el método más ampliamente utilizado (propuesto por Ebrahim Mamdani). El proceso se realiza en cuatro pasos:
Vamos a crear un sistema de control difuso que modele cómo calcular la propina en un restaurante. Se considerará el servicio y la calidad de los alimentos, valorados entre 0 y 10. Y se dejará una propina de entre 0 y 25%.
La formulación de este problema sería:
Antecedentes (Entradas)
Conjunto difuso (es decir, rango de valores difusos): pobre, aceptable, excelente
Conjunto difuso: mala, buena, exquisita
Consecuentes (Salidas)
Fuzzy set: baja, media, alta
Reglas
Uso
import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
# New Antecedent/Consequent objects hold universe variables and membership
# functions
quality = ctrl.Antecedent(np.arange(0, 11, 1), 'quality')
service = ctrl.Antecedent(np.arange(0, 11, 1), 'service')
tip = ctrl.Consequent(np.arange(0, 26, 1), 'tip')
# Auto-membership function population is possible with .automf(3, 5, or 7)
quality.automf(3)
service.automf(3)
tip['low'] = fuzz.trimf(tip.universe, [0, 0, 13])
tip['medium'] = fuzz.trimf(tip.universe, [0, 13, 25])
tip['high'] = fuzz.trimf(tip.universe, [13, 25, 25])
Para ver gráficamente los conjuntos de membresía
# You can see how these look with .view()
quality['average'].view()
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/skfuzzy/control/term.py:74: UserWarning: Matplotlib is currently using module://matplotlib_inline.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show()
service.view()
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://matplotlib_inline.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show()
tip.view()
Ahora, para hacer que estos triángulos sean útiles, definimos la relación difusa entre las variables de entrada y salida. Para los propósitos de nuestro ejemplo, considere tres reglas simples:
La mayoría de las personas estarían de acuerdo con estas reglas, aunque las reglas sean confusas. El reto es mapear reglas difusas en un cálculo preciso de la propina. Esta es la principal ventaja de la lógica difusa.
rule1 = ctrl.Rule(quality['poor'] | service['poor'], tip['low'])
rule2 = ctrl.Rule(service['average'], tip['medium'])
rule3 = ctrl.Rule(service['good'] & quality['good'], tip['high'])
tipping_ctrl = ctrl.ControlSystem([rule1, rule2, rule3])
tipping = ctrl.ControlSystemSimulation(tipping_ctrl)
# Pass inputs to the ControlSystem using Antecedent labels with Pythonic API
# Note: if you like passing many inputs all at once, use .inputs(dict_of_data)
tipping.input['quality'] = 3
tipping.input['service'] = 7
# Crunch the numbers
tipping.compute()
print("Propina:", round(tipping.output['tip'],1),"%")
tip.view(sim=tipping)
Propina: 11.6 %
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://matplotlib_inline.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show()
En este ejemplo construiremos un sistema de control para el frenado de un coche. Como parámetros tendremos la velocidad (km/h) de nuestro coche y la distancia (m) a la que se sitúa el coche de delante.
import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
speed = ctrl.Antecedent(np.arange(0, 101, 1), 'speed')
distance = ctrl.Antecedent(np.arange(0, 151, 1), 'distance')
brake = ctrl.Consequent(np.arange(0, 101, 1), 'brake', defuzzify_method="bisector")
# Auto-membership function population is possible with .automf(3, 5, or 7)
speed.automf(names = ['slow','medium','fast'])
distance['close'] = fuzz.trimf(distance.universe, [0, 0, 75])
distance['medium'] = fuzz.trimf(distance.universe, [0, 75, 150])
distance['far'] = fuzz.trimf(distance.universe, [75, 150, 150])
# Custom membership functions can be built interactively with a familiar,
# Pythonic API
brake['low'] = fuzz.trimf(brake.universe, [0, 0, 30])
brake['medium'] = fuzz.trimf(brake.universe, [0, 30, 60])
brake['high'] = fuzz.trapmf(brake.universe, [30, 60, 100, 100])
speed.view()
distance.view()
brake.view()
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show() /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show() /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show()
rule1 = ctrl.Rule(distance['medium'] & speed['fast'], brake['high'])
rule2 = ctrl.Rule(distance['close'] & speed['medium'], brake['high'])
rule3 = ctrl.Rule(distance['medium'] & speed['medium'], brake['medium'])
rule4 = ctrl.Rule(distance['far'] & speed['slow'], brake['low'])
braking_ctrl = ctrl.ControlSystem([rule1, rule2, rule3, rule4])
breaking = ctrl.ControlSystemSimulation(braking_ctrl)
# Distancia
b = []
breaking.input['speed'] = 50
for d in range(0, 150):
breaking.input['distance'] = d
breaking.compute()
b.append(int(breaking.output['brake']))
plt.xlabel("Distance")
plt.ylabel("Breaking")
plt.plot(b)
[<matplotlib.lines.Line2D at 0x11f895b38>]
Vemos que a una velocidad fija de 50km/h la presión del frenado será mayor cuanto más cerca esté el coche de delante.
# Velocidad
b = []
breaking.input['distance'] = 90
for s in range(0, 100):
breaking.input['speed'] = s
breaking.compute()
b.append(int(breaking.output['brake']))
plt.xlabel("Speed")
plt.ylabel("Breaking")
plt.plot(b)
[<matplotlib.lines.Line2D at 0x11f716240>]
Para una distancia fija de 90m la presión de frenado será mayor cuanto mayor sea la velocidad.
breaking.input['speed'] = 70
breaking.input['distance'] = 90
brake.view(sim=breaking)
breaking.input['speed'] = 80
breaking.input['distance'] = 90
brake.view(sim=breaking)
breaking.input['speed'] = 90
breaking.input['distance'] = 90
brake.view(sim=breaking)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show() /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show() /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/skfuzzy/control/fuzzyvariable.py:122: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure. fig.show()
import numpy as np
import matplotlib.pyplot as plt
import skfuzzy as fuzz
# Generate trapezoidal membership function on range [0, 1]
x = np.arange(0, 5.05, 0.1)
mfx = fuzz.trapmf(x, [2, 2.5, 3, 4.5])
# Defuzzify this membership function five ways
defuzz_centroid = fuzz.defuzz(x, mfx, 'centroid') # Same as skfuzzy.centroid
defuzz_bisector = fuzz.defuzz(x, mfx, 'bisector')
defuzz_mom = fuzz.defuzz(x, mfx, 'mom')
defuzz_som = fuzz.defuzz(x, mfx, 'som')
defuzz_lom = fuzz.defuzz(x, mfx, 'lom')
# Collect info for vertical lines
labels = ['centroid', 'bisector', 'mean of maximum', 'min of maximum', 'max of maximum']
xvals = [defuzz_centroid, defuzz_bisector, defuzz_mom, defuzz_som, defuzz_lom]
colors = ['r', 'b', 'g', 'c', 'm']
ymax = [fuzz.interp_membership(x, mfx, i) for i in xvals]
# Display and compare defuzzification results against membership function
plt.figure(figsize=(8, 5))
plt.plot(x, mfx, 'k')
for xv, y, label, color in zip(xvals, ymax, labels, colors):
plt.vlines(xv, 0, y, label=label, color=color)
plt.ylabel('Fuzzy membership')
plt.xlabel('Universe variable (arb)')
plt.ylim(-0.1, 1.1)
plt.legend(loc=2)
plt.show()
Realiza un sistema de control difuso para el control de inventario basado en la demanda del mercado y el inventario actual. El sistema intentará ajustar el nivel de inventario para minimizar el costo de mantener el inventario y prevenir las fluctuaciones de la demanda. Algunas reglas difusas que podría incluir son: