"""
Archivo para el manejo de la función de diseño de controladores difusos, sirve de intermediario entre la interfaz grafica y la clase creada para manejar el controlador difuso definida en rutinas_fuzzy.py
"""
from handlers.modificadorMf import update_definicionmf, validacion_mf
from rutinas.rutinas_fuzzy import FuzzyController
from rutinas.rutinas_fuzzy import FISParser
from PySide2 import QtCore, QtGui, QtWidgets
import numpy as np
import copy
import json
[documentos]def FuzzyHandler(self):
"""
Función principal para el manejo de diseño de controladores difusos, se crean las señales a ejecutar cuando se interactuá con los widgets
"""
self.EntradasTab = self.main.fuzzyTabWidget.widget(1)
self.SalidasTab = self.main.fuzzyTabWidget.widget(2)
self.ReglasTab = self.main.fuzzyTabWidget.widget(3)
self.PruebaTab = self.main.fuzzyTabWidget.widget(4)
self.RespuestaTab = self.main.fuzzyTabWidget.widget(5)
self.main.guardarFuzzButton.setDisabled(True)
self.main.guardarComoFuzzButton.setDisabled(True)
self.main.exportarFuzzButton.setDisabled(True)
# Ocultado de los tabs
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
self.main.fuzzyTabWidget.removeTab(3)
self.main.fuzzyTabWidget.removeTab(2)
self.main.fuzzyTabWidget.removeTab(1)
# Listas que definen al controlador difuso
self.InputList = []
self.OutputList = []
self.RuleList = []
self.RuleEtiquetas = []
# Lista para para controlar un desplazamiento de ventana
self.vector_rotacion = [-0.25, 0, 0.25, 0.5, 0.75, 1, 1.25]
self.rotacion_windowIn = 2
self.rotacion_windowOut = 2
# Objeto de la clase FuzzyController
self.fuzzInitController = FuzzyController
# Objeto de la clase FISParser, para cargar y exportar .FIS
self.parser = FISParser
# Almacenado de widgets en listas para acceder a ellos por indices
crear_vectores_de_widgets(self)
# Ocultado de widgets
for i_f, o_f, it_f, ot_f, f2d, f3d in zip(
self.inframes,
self.outframes,
self.intestframes,
self.outtestframes,
self.respuesta2dframes,
self.respuesta3dframes,
):
i_f.hide()
o_f.hide()
it_f.hide()
ot_f.hide()
f2d.hide()
f3d.hide()
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/sinEsquema.png")
)
self.main.estrucNumberInputs.currentIndexChanged.connect(
lambda: imagen_entradas(self)
)
self.main.estrucNumberOutputs.currentIndexChanged.connect(
lambda: imagen_salidas(self)
)
self.main.fuzzyEsquemasCheck.clicked["bool"].connect(lambda: check_esquema_show(self))
self.main.fuzzyEsquemas.currentIndexChanged.connect(lambda: show_esquema(self))
self.main.generarFuzzyButton.clicked.connect(lambda: crear_tabs(self))
self.main.guardarFuzzButton.clicked.connect(lambda: guardar_controlador(self))
self.main.cargarFuzzButton.clicked.connect(lambda: cargar_controlador(self))
self.main.guardarComoFuzzButton.clicked.connect(lambda: guardarcomo_controlador(self))
self.main.exportarFuzzButton.clicked.connect(lambda: exportar_fis(self))
self.main.inputNumber.currentIndexChanged.connect(lambda: seleccion_entrada(self))
self.main.inputNombre.editingFinished.connect(lambda: nombre_entrada(self))
self.main.inputNombre.focusIn.connect(lambda: cerrar_prueba(self))
self.main.inputEtiquetasNum.editingFinished.connect(
lambda: numero_de_etiquetas_in(self)
)
self.main.inputEtiquetasNum.focusIn.connect(lambda: cerrar_prueba(self))
self.main.inputRange.editingFinished.connect(lambda: rango_in(self))
self.main.inputRange.focusIn.connect(lambda: cerrar_prueba(self))
self.main.etiquetaNumIn.currentIndexChanged.connect(
lambda: seleccion_etiqueta_in(self)
)
self.main.etiquetaNombreIn.editingFinished.connect(lambda: nombre_etiqueta_in(self))
self.main.etiquetaNombreIn.focusIn.connect(lambda: cerrar_prueba(self))
self.main.etiquetaMfIn.currentIndexChanged.connect(lambda: seleccion_mf_in(self))
self.main.etiquetaDefinicionIn.editingFinished.connect(lambda: definicion_in(self))
self.main.etiquetaDefinicionIn.focusIn.connect(lambda: cerrar_prueba(self))
self.main.outputNumber.currentIndexChanged.connect(lambda: seleccion_salida(self))
self.main.outputNombre.editingFinished.connect(lambda: nombre_salida(self))
self.main.outputNombre.focusIn.connect(lambda: cerrar_prueba(self))
self.main.outputEtiquetasNum.editingFinished.connect(
lambda: numero_de_etiquetas_out(self)
)
self.main.outputEtiquetasNum.focusIn.connect(lambda: cerrar_prueba(self))
self.main.outputRange.editingFinished.connect(lambda: rango_out(self))
self.main.outputRange.focusIn.connect(lambda: cerrar_prueba(self))
self.main.defuzzMethodOut.currentIndexChanged.connect(lambda: defuzz_metodo(self))
self.main.etiquetaNumOut.currentIndexChanged.connect(
lambda: seleccion_etiqueta_out(self)
)
self.main.etiquetaNombreOut.editingFinished.connect(lambda: nombre_etiqueta_out(self))
self.main.etiquetaNombreOut.focusIn.connect(lambda: cerrar_prueba(self))
self.main.etiquetaMfOut.currentIndexChanged.connect(lambda: seleccion_mf_out(self))
self.main.etiquetaDefinicionOut.editingFinished.connect(lambda: definicion_out(self))
self.main.etiquetaDefinicionOut.focusIn.connect(lambda: cerrar_prueba(self))
self.main.fuzzyTabWidget.currentChanged.connect(lambda: rule_list_visualizacion(self))
self.main.rulelistWidget.currentRowChanged.connect(
lambda: seleccionar_etiquetas(self)
)
self.main.ruleAgregarButton.clicked.connect(lambda: rule_list_agregar(self))
self.main.ruleEliminarButton.clicked.connect(lambda: rule_list_eliminar(self))
self.main.ruleCambiarButton.clicked.connect(lambda: rule_list_cambiar(self))
self.main.ruleCrearButton.clicked.connect(lambda: crear_controlador(self))
for slider in self.intestsliders:
slider.valueChanged.connect(lambda: prueba_input(self))
[documentos]def cerrar_prueba(self):
""" Función para cerrar las pestañas de pruebas ante cambios en el controlador difuso """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
[documentos]def imagen_entradas(self):
""" Función para establecer la imagen del numero de entradas """
ni = self.main.estrucNumberInputs.currentIndex() + 1
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada" + str(ni) + ".png")
)
[documentos]def imagen_salidas(self):
""" Función para establecer la imagen del numero de salidas """
no = self.main.estrucNumberOutputs.currentIndex() + 1
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida" + str(no) + ".png")
)
[documentos]def check_esquema_show(self):
""" Función para mediar entre entradas y salidas genéricas y esquemas de control """
if not self.main.fuzzyEsquemasCheck.isChecked():
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/sinEsquema.png")
)
imagen_entradas(self)
imagen_salidas(self)
else:
show_esquema(self)
[documentos]def show_esquema(self):
""" Función para establecer la imagen del esquema de control seleccionado """
if self.main.fuzzyEsquemas.currentIndex() == 0:
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/pidDifuso.png")
)
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada3.png")
)
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida1.png")
)
elif self.main.fuzzyEsquemas.currentIndex() == 1:
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/piDifuso.png"))
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada2.png")
)
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida1.png")
)
elif self.main.fuzzyEsquemas.currentIndex() == 2:
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/pdDifuso.png"))
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada2.png")
)
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida1.png")
)
elif self.main.fuzzyEsquemas.currentIndex() == 3:
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/GainScheduler.png"))
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada2.png")
)
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida3.png")
)
elif self.main.fuzzyEsquemas.currentIndex() == 4:
self.main.imagenEsquemas.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/pidplusDifuso.png"))
self.main.imagenInputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/entrada1.png")
)
self.main.imagenOutputs.setPixmap(
QtGui.QPixmap(":/imagenes/imagenes/salida1.png")
)
[documentos]def crear_tabs(self):
""" Función para iniciar el entorno de diseño para entradas y salidas genéricas """
if not self.main.fuzzyEsquemasCheck.isChecked():
self.setWindowTitle(
"Laboratorio Virtual - Nuevo controlador sin guardar*"
)
self.main.inputNumber.blockSignals(True)
self.main.outputNumber.blockSignals(True)
self.main.inputNombre.setReadOnly(False)
self.main.outputNombre.setReadOnly(False)
# Vaciado de información previa
self.current_file = ""
self.InputList = []
self.OutputList = []
self.RuleList = []
self.RuleEtiquetas = []
# Habilitar guardado de archivos
self.main.guardarFuzzButton.setEnabled(True)
self.main.guardarComoFuzzButton.setEnabled(True)
self.main.exportarFuzzButton.setEnabled(True)
# Se ocultan todos los tabs y se muestran solo Entradas, Salidas y Reglas
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
self.main.fuzzyTabWidget.removeTab(3)
self.main.fuzzyTabWidget.removeTab(2)
self.main.fuzzyTabWidget.removeTab(1)
self.main.fuzzyTabWidget.addTab(self.EntradasTab, "Entradas")
self.main.fuzzyTabWidget.addTab(self.SalidasTab, "Salidas")
self.main.fuzzyTabWidget.addTab(self.ReglasTab, "Reglas")
NumeroEntradas = int(self.main.estrucNumberInputs.currentText())
NumeroSalidas = int(self.main.estrucNumberOutputs.currentText())
self.main.inputNumber.clear()
self.main.outputNumber.clear()
# Creación de funciones de membresía genéricas
for i in range(NumeroEntradas):
self.main.inputNumber.insertItem(i, str(i + 1))
temp_dic = inputDic_creator(self, i)
self.InputList.append(temp_dic)
ini_range_etiquetas = np.arange(-20, 21, 20 / 2).tolist()
window = 0
for j in range(self.InputList[i]["numeroE"]):
self.InputList[i]["etiquetas"][j] = EtiquetasDic_creator(
self, j, ini_range_etiquetas[window:window + 3]
)
window += 1
for i in range(NumeroSalidas):
self.main.outputNumber.insertItem(i, str(i + 1))
temp_dic = outputDic_creator(self, i)
self.OutputList.append(temp_dic)
ini_range_etiquetas = np.arange(-20, 21, 20 / 2).tolist()
window = 0
for j in range(self.OutputList[i]["numeroE"]):
self.OutputList[i]["etiquetas"][j] = EtiquetasDic_creator(
self, j, ini_range_etiquetas[window:window + 3]
)
window += 1
self.main.inputNumber.blockSignals(False)
self.main.outputNumber.blockSignals(False)
# Se inicializa el controlador con la información actual
self.fuzzController = self.fuzzInitController(self.InputList, self.OutputList)
seleccion_entrada(self)
seleccion_salida(self)
self.fuzzController.graficar_mf_in(self, 0)
self.fuzzController.graficar_mf_out(self, 0)
else:
# En caso de que se seleccione un esquema y no entradas y salidas genéricas
cargar_esquema(self)
[documentos]def outputDic_creator(self, i):
"""
Función para crear salidas genéricas
:param i: Numero de salida
:type i: int
:return: Diccionario con la información de la salida
:rtype: dict
"""
outputDic = {
"nombre": "salida" + str(i + 1),
"numeroE": 3,
"etiquetas": [0] * 3,
"rango": [-10, 10],
"metodo": "centroid",
}
return outputDic
[documentos]def EtiquetasDic_creator(self, j, erange):
"""
Función para crear etiquetas genéricas
:param j: Numero de etiqueta
:type j: int
:param erange: Definición de la función de membresía
:type erange: list
:return: Diccionario con la información de la etiqueta
:rtype: dict
"""
etiquetaDic = {
"nombre": "etiqueta" + str(j + 1),
"mf": "trimf",
"definicion": round_list(erange),
}
return etiquetaDic
[documentos]def cargar_esquema(self):
""" Función para iniciar el entorno de diseño a partir de un esquema de control seleccionado """
# Carga del archivo correspondiente al esquema seleccionado
path = self.resource_path(
"Esquemas/" + self.main.fuzzyEsquemas.currentText() + ".json"
)
with open(path, "r") as f:
self.InputList, self.OutputList, self.RuleEtiquetas = json.load(f)
self.main.inputNombre.setReadOnly(True)
self.main.outputNombre.setReadOnly(True)
self.current_file = ""
# Habilitar guardado de archivos
self.main.guardarFuzzButton.setEnabled(True)
self.main.guardarComoFuzzButton.setEnabled(True)
self.main.exportarFuzzButton.setEnabled(True)
self.main.inputNumber.blockSignals(True)
self.main.outputNumber.blockSignals(True)
# Se ocultan todos los tabs y se muestran solo Entradas, Salidas y Reglas
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
self.main.fuzzyTabWidget.removeTab(3)
self.main.fuzzyTabWidget.removeTab(2)
self.main.fuzzyTabWidget.removeTab(1)
self.main.fuzzyTabWidget.addTab(self.EntradasTab, "Entradas")
self.main.fuzzyTabWidget.addTab(self.SalidasTab, "Salidas")
self.main.fuzzyTabWidget.addTab(self.ReglasTab, "Reglas")
self.main.inputNumber.clear()
self.main.outputNumber.clear()
for i in range(len(self.InputList)):
self.main.inputNumber.insertItem(i, str(i + 1))
for i in range(len(self.OutputList)):
self.main.outputNumber.insertItem(i, str(i + 1))
self.main.inputNumber.blockSignals(False)
self.main.outputNumber.blockSignals(False)
# Se inicializa el controlador con la información actual
self.fuzzController = self.fuzzInitController(self.InputList,
self.OutputList,
self.RuleEtiquetas)
self.RuleList = copy.deepcopy(self.fuzzController.rulelist)
seleccion_entrada(self)
seleccion_salida(self)
self.fuzzController.graficar_mf_in(self, 0)
self.fuzzController.graficar_mf_out(self, 0)
self.setWindowTitle(
"Laboratorio Virtual - Nuevo controlador sin guardar*"
)
[documentos]def guardar_controlador(self):
""" Función manejar el guardado del controlador diseñado """
if len(self.current_file) > 0 and not '.fis' in self.current_file:
with open(self.current_file, "w") as f:
json.dump([self.InputList, self.OutputList, self.RuleEtiquetas], f, indent=4)
else:
guardarcomo_controlador(self)
[documentos]def guardarcomo_controlador(self):
""" Función manejar el guardado en un nuevo archivo del controlador diseñado """
path_guardar = QtWidgets.QFileDialog.getSaveFileName(filter="JSON (*.json)")
if len(path_guardar[0]) > 1:
self.current_file = path_guardar[0]
with open(path_guardar[0], "w") as f:
json.dump([self.InputList, self.OutputList, self.RuleEtiquetas], f, indent=4)
self.setWindowTitle(
"Laboratorio Virtual - " + path_guardar[0].split("/")[-1]
)
[documentos]def exportar_fis(self):
""" Función manejar el exportado del controlador diseñado a formato .FIS """
path_guardar = QtWidgets.QFileDialog.getSaveFileName(filter="FIS (*.fis)")
if len(path_guardar[0]) > 1:
self.current_file = path_guardar[0]
temp_parser = self.parser(self.current_file, self.InputList, self.OutputList, self.RuleEtiquetas)
temp_parser.json_to_fis()
self.setWindowTitle("Laboratorio Virtual - " +
path_guardar[0].split("/")[-1])
[documentos]def cargar_controlador(self):
""" Función manejar el cargado de controladores previamente diseñados, se aceptan formatos .JSON y .FIS """
self.path_cargar = QtWidgets.QFileDialog.getOpenFileName(filter="JSON/FIS (*.json *.fis)")
if len(self.path_cargar[0]) > 1:
if '.json' in self.path_cargar[0]:
with open(self.path_cargar[0], "r") as f:
self.InputList, self.OutputList, self.RuleEtiquetas = json.load(f)
else:
temp_parser = self.parser(self.path_cargar[0])
try:
self.InputList, self.OutputList, self.RuleEtiquetas = temp_parser.fis_to_json()
except TypeError:
self.error_dialog.setInformativeText("No se permiten salidas negadas")
self.error_dialog.exec_()
return
# Habilitar guardado de archivos
self.main.guardarFuzzButton.setEnabled(True)
self.main.guardarComoFuzzButton.setEnabled(True)
self.main.exportarFuzzButton.setEnabled(True)
self.main.inputNombre.setReadOnly(False)
self.main.outputNombre.setReadOnly(False)
self.current_file = copy.deepcopy(self.path_cargar[0])
self.main.inputNumber.blockSignals(True)
self.main.outputNumber.blockSignals(True)
# Se ocultan todos los tabs y se muestran solo Entradas, Salidas y Reglas
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
self.main.fuzzyTabWidget.removeTab(3)
self.main.fuzzyTabWidget.removeTab(2)
self.main.fuzzyTabWidget.removeTab(1)
self.main.fuzzyTabWidget.addTab(self.EntradasTab, "Entradas")
self.main.fuzzyTabWidget.addTab(self.SalidasTab, "Salidas")
self.main.fuzzyTabWidget.addTab(self.ReglasTab, "Reglas")
self.main.inputNumber.clear()
self.main.outputNumber.clear()
for i in range(len(self.InputList)):
self.main.inputNumber.insertItem(i, str(i + 1))
for i in range(len(self.OutputList)):
self.main.outputNumber.insertItem(i, str(i + 1))
self.main.inputNumber.blockSignals(False)
self.main.outputNumber.blockSignals(False)
# Se inicializa el controlador con la información actual
self.fuzzController = self.fuzzInitController(self.InputList,
self.OutputList,
self.RuleEtiquetas)
self.RuleList = copy.deepcopy(self.fuzzController.rulelist)
seleccion_entrada(self)
seleccion_salida(self)
self.fuzzController.graficar_mf_in(self, 0)
self.fuzzController.graficar_mf_out(self, 0)
self.setWindowTitle(
"Laboratorio Virtual - " + self.path_cargar[0].split("/")[-1]
)
[documentos]def seleccion_entrada(self):
""" Función para desplegar la información de la entrada seleccionada """
ni = self.main.inputNumber.currentIndex()
self.main.inputNombre.setText(self.InputList[ni]["nombre"])
self.main.inputEtiquetasNum.setText(str(self.InputList[ni]["numeroE"]))
self.main.inputRange.setText(str(self.InputList[ni]["rango"]))
self.main.etiquetaNumIn.clear()
for j in range(self.InputList[ni]["numeroE"]):
self.main.etiquetaNumIn.insertItem(j, str(j + 1))
self.main.etiquetaNombreIn.setText(self.InputList[ni]["etiquetas"][0]["nombre"])
self.main.etiquetaMfIn.setCurrentText(self.InputList[ni]["etiquetas"][0]["mf"])
self.main.etiquetaDefinicionIn.setText(
str(self.InputList[ni]["etiquetas"][0]["definicion"])
)
self.fuzzController.graficar_mf_in(self, ni)
[documentos]def seleccion_salida(self):
""" Función para desplegar la información de la salida seleccionada """
no = self.main.outputNumber.currentIndex()
self.main.outputNombre.setText(self.OutputList[no]["nombre"])
self.main.outputEtiquetasNum.setText(str(self.OutputList[no]["numeroE"]))
self.main.outputRange.setText(str(self.OutputList[no]["rango"]))
self.main.defuzzMethodOut.setCurrentText(self.OutputList[no]["metodo"])
self.main.etiquetaNumOut.clear()
for j in range(self.OutputList[no]["numeroE"]):
self.main.etiquetaNumOut.insertItem(j, str(j + 1))
self.main.etiquetaNombreOut.setText(self.OutputList[no]["etiquetas"][0]["nombre"])
self.main.etiquetaMfOut.setCurrentText(self.OutputList[no]["etiquetas"][0]["mf"])
self.main.etiquetaDefinicionOut.setText(
str(self.OutputList[no]["etiquetas"][0]["definicion"])
)
self.fuzzController.graficar_mf_out(self, no)
[documentos]def nombre_entrada(self):
""" Función para manejar el cambio de nombre de la entrada seleccionada """
if self.main.inputNombre.text().strip() == '':
self.error_dialog.setInformativeText(
"El nombre no puede estar vació")
self.error_dialog.exec_()
self.main.inputNombre.setFocus()
return
ni = self.main.inputNumber.currentIndex()
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
old_name = self.InputList[ni]["nombre"]
flag = 0
for i in self.InputList:
if (
i["nombre"] == self.main.inputNombre.text() and
old_name != self.main.inputNombre.text()
):
flag = 1
# Chequeo en caso de nombre repetido, se concatena un "1" en caso positivo
if not flag:
self.InputList[ni]["nombre"] = self.main.inputNombre.text()
else:
self.InputList[ni]["nombre"] = self.main.inputNombre.text() + "1"
self.main.inputNombre.setText(self.InputList[ni]["nombre"])
self.fuzzController.cambiar_nombre_input(self, ni, self.InputList[ni]["nombre"])
# Se actualizan la reglas con el nuevo nombre
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
self.main.inputNombre.clearFocus()
[documentos]def nombre_salida(self):
""" Función para manejar el cambio de nombre de la salida seleccionada """
if self.main.outputNombre.text().strip() == '':
self.error_dialog.setInformativeText(
"El nombre no puede estar vació")
self.error_dialog.exec_()
self.main.outputNombre.setFocus()
return
no = self.main.outputNumber.currentIndex()
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
old_name = self.OutputList[no]["nombre"]
flag = 0
for o in self.OutputList:
if (
o["nombre"] == self.main.outputNombre.text() and
old_name != self.main.outputNombre.text()
):
flag = 1
# Chequeo en caso de nombre repetido, se concatena un "1" en caso positivo
if not flag:
self.OutputList[no]["nombre"] = self.main.outputNombre.text()
else:
self.OutputList[no]["nombre"] = self.main.outputNombre.text() + "1"
self.main.outputNombre.setText(self.OutputList[no]["nombre"])
self.fuzzController.cambiar_nombre_output(self, no, self.OutputList[no]["nombre"])
# Se actualizan la reglas con el nuevo nombre
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
self.main.outputNombre.clearFocus()
[documentos]def numero_de_etiquetas_in(self):
""" Función para manejar el numero de etiquetas para la entrada seleccionada """
try:
_ = int(self.main.inputEtiquetasNum.text())
if _ < 1:
raise ValueError
except ValueError:
self.error_dialog.setInformativeText(
"El numero de etiquetas debe ser un valor entero mayor o igual a 1")
self.error_dialog.exec_()
self.main.inputEtiquetasNum.setFocus()
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
ni = self.main.inputNumber.currentIndex()
ne = int(self.main.inputEtiquetasNum.text())
# En caso de que el nuevo numero de etiquetas sea menor que el actual se procede a eliminar un numero
# de etiquetas igual a la diferencia entre el nuevo valor y el valor actual.
if self.InputList[ni]["numeroE"] > ne:
self.main.etiquetaNumIn.blockSignals(True)
# Eliminación de las reglas que dependían de las etiquetas a eliminar
for n in range(self.InputList[ni]["numeroE"] - 1, ne - 1, -1):
new_list = []
for i, sets in enumerate(copy.deepcopy(self.RuleEtiquetas)):
for rule in sets[0]:
if (
rule[0] == self.InputList[ni]["etiquetas"][n]["nombre"] and
rule[1] == ni
):
break
else:
new_list.append(self.RuleEtiquetas[i])
break
self.RuleEtiquetas = copy.deepcopy(new_list)
self.main.etiquetaNumIn.removeItem(n)
# Eliminación de las etiquetas
for _ in range(ne, self.InputList[ni]["numeroE"]):
self.InputList[ni]["etiquetas"].pop()
self.InputList[ni]["numeroE"] = ne
self.RuleEtiquetas = copy.deepcopy(new_list)
self.main.etiquetaNumIn.setCurrentIndex(ne - 1)
self.main.etiquetaNombreIn.setText(
self.InputList[ni]["etiquetas"][ne - 1]["nombre"]
)
self.main.etiquetaDefinicionIn.setText(
str(self.InputList[ni]["etiquetas"][ne - 1]["definicion"])
)
self.main.etiquetaMfIn.setCurrentText(
self.InputList[ni]["etiquetas"][ne - 1]["mf"]
)
# En caso de que el nuevo numero de etiquetas sea mayor que el actual se procede a agregar un numero
# de etiquetas igual a la diferencia entre el nuevo valor y el valor actual.
if self.InputList[ni]["numeroE"] < ne:
self.main.etiquetaNumIn.blockSignals(True)
rmin, rmax = self.InputList[ni]["rango"]
# Creación de funciones de membresía trimf genéricas
if (ne - self.InputList[ni]["numeroE"]) == 1:
ini_range_etiquetas = [
self.vector_rotacion[self.rotacion_windowIn] * (rmax-rmin) + rmin,
self.vector_rotacion[self.rotacion_windowIn + 1] * (rmax-rmin) + rmin,
self.vector_rotacion[self.rotacion_windowIn + 2] * (rmax-rmin) + rmin,
]
self.rotacion_windowIn += 1
if self.rotacion_windowIn > 4:
self.rotacion_windowIn = 0
else:
step = (rmax-rmin) / ((ne - self.InputList[ni]["numeroE"]) - 1)
ini_range_etiquetas = np.arange(rmin - step, rmax + step + 1, step).tolist()
window = 0
for j in range(self.InputList[ni]["numeroE"], ne):
self.main.etiquetaNumIn.insertItem(j, str(j + 1))
self.InputList[ni]["etiquetas"].append(
EtiquetasDic_creator(self, j, ini_range_etiquetas[window:window + 3])
)
window += 1
self.InputList[ni]["numeroE"] = ne
# Se actualizan las etiquetas en el controlador
self.fuzzController.cambio_etiquetas_input(self, self.InputList, ni)
# Se actualizan la reglas con las nuevas etiquetas o la falta de ellas
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
self.main.inputEtiquetasNum.clearFocus()
self.main.etiquetaNumIn.blockSignals(False)
[documentos]def numero_de_etiquetas_out(self):
""" Función para manejar el numero de etiquetas para la salida seleccionada """
try:
_ = int(self.main.outputEtiquetasNum.text())
if _ < 1:
raise ValueError
except ValueError:
self.error_dialog.setInformativeText(
"El numero de etiquetas debe ser un valor entero mayor o igual a 1")
self.error_dialog.exec_()
self.main.outputEtiquetasNum.setFocus()
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
no = self.main.outputNumber.currentIndex()
ne = int(self.main.outputEtiquetasNum.text())
# En caso de que el nuevo numero de etiquetas sea menor que el actual se procede a eliminar un numero
# de etiquetas igual a la diferencia entre el nuevo valor y el valor actual.
if self.OutputList[no]["numeroE"] > ne:
self.main.etiquetaNumOut.blockSignals(True)
# Eliminación de las reglas que dependían de las etiquetas a eliminar
for n in range(self.OutputList[no]["numeroE"] - 1, ne - 1, -1):
new_list = []
for o, sets in enumerate(copy.deepcopy(self.RuleEtiquetas)):
for rule in sets[1]:
if (
rule[0] == self.OutputList[no]["etiquetas"][n]["nombre"] and
rule[1] == no
):
break
else:
new_list.append(self.RuleEtiquetas[o])
break
self.RuleEtiquetas = copy.deepcopy(new_list)
self.main.etiquetaNumOut.removeItem(n)
# Eliminación de las etiquetas
for _ in range(ne, self.OutputList[no]["numeroE"]):
self.OutputList[no]["etiquetas"].pop()
self.OutputList[no]["numeroE"] = ne
self.RuleEtiquetas = copy.deepcopy(new_list)
self.main.etiquetaNumOut.setCurrentIndex(ne - 1)
self.main.etiquetaNombreOut.setText(
self.OutputList[no]["etiquetas"][ne - 1]["nombre"]
)
self.main.etiquetaDefinicionOut.setText(
str(self.OutputList[no]["etiquetas"][ne - 1]["definicion"])
)
self.main.etiquetaMfOut.setCurrentText(
self.OutputList[no]["etiquetas"][ne - 1]["mf"]
)
# En caso de que el nuevo numero de etiquetas sea mayor que el actual se procede a agregar un numero
# de etiquetas igual a la diferencia entre el nuevo valor y el valor actual.
if self.OutputList[no]["numeroE"] < ne:
self.main.etiquetaNumOut.blockSignals(True)
rmin, rmax = self.OutputList[no]["rango"]
# Creación de funciones de membresía trimf genéricas
if (ne - self.OutputList[no]["numeroE"]) == 1:
ini_range_etiquetas = [
self.vector_rotacion[self.rotacion_windowOut] * (rmax-rmin) + rmin,
self.vector_rotacion[self.rotacion_windowOut + 1] * (rmax-rmin) + rmin,
self.vector_rotacion[self.rotacion_windowOut + 2] * (rmax-rmin) + rmin,
]
self.rotacion_windowOut += 1
if self.rotacion_windowOut > 4:
self.rotacion_windowOut = 0
else:
step = (rmax-rmin) / ((ne - self.OutputList[no]["numeroE"]) - 1)
ini_range_etiquetas = np.arange(rmin - step, rmax + step + 1, step).tolist()
window = 0
for j in range(self.OutputList[no]["numeroE"], ne):
self.main.etiquetaNumOut.insertItem(j, str(j + 1))
self.OutputList[no]["etiquetas"].append(
EtiquetasDic_creator(self, j, ini_range_etiquetas[window:window + 3])
)
window += 1
self.OutputList[no]["numeroE"] = ne
# Se actualizan las etiquetas en el controlador
self.fuzzController.cambio_etiquetas_output(self, self.OutputList, no)
# Se actualizan la reglas con las nuevas etiquetas o la falta de ellas
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
self.main.outputEtiquetasNum.clearFocus()
self.main.etiquetaNumOut.blockSignals(False)
[documentos]def rango_in(self):
""" Función para manejar el rango para la entrada seleccionada """
try:
_ = json.loads(self.main.inputRange.text())
if len(_) > 2 or len(_) < 2:
raise ValueError
except ValueError:
self.error_dialog.setInformativeText(
"Rango no valido, el rango debe estar entre corchetes y los valores separados por coma.\n i.g., [-10, 10]"
)
self.error_dialog.exec_()
self.main.inputRange.setFocus()
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
ni = self.main.inputNumber.currentIndex()
self.InputList[ni]["rango"] = json.loads(self.main.inputRange.text())
# Se actualiza el rango y las etiquetas
self.fuzzController.update_rango_input(self, self.InputList, ni)
self.fuzzController.cambio_etiquetas_input(self, self.InputList, ni)
self.main.inputRange.clearFocus()
[documentos]def rango_out(self):
""" Función para manejar el rango para la salida seleccionada """
try:
_ = json.loads(self.main.outputRange.text())
if len(_) > 2 or len(_) < 2:
raise ValueError
except ValueError:
self.error_dialog.setInformativeText(
"Rango no valido, el rango debe estar entre corchetes y los valores separados por coma.\n i.g., [-10, 10]"
)
self.error_dialog.exec_()
self.main.outputRange.setFocus()
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
no = self.main.outputNumber.currentIndex()
self.OutputList[no]["rango"] = json.loads(self.main.outputRange.text())
# Se actualiza el rango y las etiquetas
self.fuzzController.update_rango_output(self, self.OutputList, no)
self.fuzzController.cambio_etiquetas_output(self, self.OutputList, no)
self.main.outputRange.clearFocus()
[documentos]def defuzz_metodo(self):
""" Función para manejar el metodo de defuzzificacion para la salida seleccionada """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
no = self.main.outputNumber.currentIndex()
self.OutputList[no]["metodo"] = self.main.defuzzMethodOut.currentText()
metodo = self.OutputList[no]["metodo"]
# Se actualiza el metodo de defuzzificacion
self.fuzzController.cambiar_metodo(self, no, metodo)
[documentos]def seleccion_etiqueta_in(self):
""" Función para desplegar la información de la etiqueta seleccionada de la entrada actual """
ni = self.main.inputNumber.currentIndex()
ne = self.main.etiquetaNumIn.currentIndex()
self.main.etiquetaNombreIn.setText(self.InputList[ni]["etiquetas"][ne]["nombre"])
self.main.etiquetaMfIn.blockSignals(True)
self.main.etiquetaMfIn.setCurrentText(self.InputList[ni]["etiquetas"][ne]["mf"])
self.main.etiquetaDefinicionIn.setText(
str(self.InputList[ni]["etiquetas"][ne]["definicion"])
)
self.main.etiquetaMfIn.blockSignals(False)
[documentos]def seleccion_etiqueta_out(self):
""" Función para desplegar la información de la etiqueta seleccionada de la salida actual """
no = self.main.outputNumber.currentIndex()
ne = self.main.etiquetaNumOut.currentIndex()
self.main.etiquetaNombreOut.setText(self.OutputList[no]["etiquetas"][ne]["nombre"])
self.main.etiquetaMfOut.blockSignals(True)
self.main.etiquetaMfOut.setCurrentText(self.OutputList[no]["etiquetas"][ne]["mf"])
self.main.etiquetaDefinicionOut.setText(
str(self.OutputList[no]["etiquetas"][ne]["definicion"])
)
self.main.etiquetaMfOut.blockSignals(False)
[documentos]def nombre_etiqueta_in(self):
""" Función para manejar el cambio de nombre de la etiqueta seleccionada de la entrada actual """
if self.main.etiquetaNombreIn.text().strip() == '':
self.error_dialog.setInformativeText(
"El nombre no puede estar vació")
self.error_dialog.exec_()
self.main.etiquetaNombreIn.setFocus()
return
ni = self.main.inputNumber.currentIndex()
ne = self.main.etiquetaNumIn.currentIndex()
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
old_name = self.InputList[ni]["etiquetas"][ne]["nombre"]
flag = 0
for i in self.InputList[ni]["etiquetas"]:
if (
i["nombre"] == self.main.etiquetaNombreIn.text() and
old_name != self.main.etiquetaNombreIn.text()
):
flag = 1
# Chequeo en caso de nombre repetido, se concatena un "1" en caso positivo
if not flag:
self.InputList[ni]["etiquetas"][ne]["nombre"] = self.main.etiquetaNombreIn.text()
else:
self.InputList[ni]["etiquetas"][ne]["nombre"] = (
self.main.etiquetaNombreIn.text() + "1"
)
self.main.etiquetaNombreIn.setText(self.InputList[ni]["etiquetas"][ne]["nombre"])
self.fuzzController.cambio_etinombre_input(self, self.InputList, ni, ne, old_name)
# Se actualizan la reglas con el nuevo nombre de la etiqueta
if len(self.RuleList) > 0:
actualizar_RulesEtiquetas_in(self,
ni,
self.main.etiquetaNombreIn.text(),
old_name)
self.main.etiquetaNombreIn.clearFocus()
[documentos]def actualizar_RulesEtiquetas_in(self, ni, new_name, old_name):
"""
Función para actualizar el nombre en las reglas previamente creadas con el nuevo nombre de una etiqueta
:param ni: Numero de entrada
:type ni: int
:param new_name: Nuevo nombre para la etiqueta a cambiar
:type new_name: str
:param old_name: Antiguo nombre de la etiqueta a cambiar
:type old_name: str
"""
for sets in self.RuleEtiquetas:
for rule in sets[0]:
if rule[0] == old_name and rule[1] == ni:
rule[0] = new_name
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
[documentos]def nombre_etiqueta_out(self):
""" Función para manejar el cambio de nombre de la etiqueta seleccionada de la salida actual """
if self.main.etiquetaNombreOut.text().strip() == '':
self.error_dialog.setInformativeText(
"El nombre no puede estar vació")
self.error_dialog.exec_()
self.main.etiquetaNombreOut.setFocus()
return
no = self.main.outputNumber.currentIndex()
ne = self.main.etiquetaNumOut.currentIndex()
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
old_name = self.OutputList[no]["etiquetas"][ne]["nombre"]
flag = 0
for i in self.OutputList[no]["etiquetas"]:
if (
i["nombre"] == self.main.etiquetaNombreOut.text() and
old_name != self.main.etiquetaNombreOut.text()
):
flag = 1
# Chequeo en caso de nombre repetido, se concatena un "1" en caso positivo
if not flag:
self.OutputList[no]["etiquetas"][ne]["nombre"] = self.main.etiquetaNombreOut.text(
)
else:
self.OutputList[no]["etiquetas"][ne]["nombre"] = (
self.main.etiquetaNombreOut.text() + "1"
)
self.main.etiquetaNombreOut.setText(
self.OutputList[no]["etiquetas"][ne]["nombre"]
)
self.fuzzController.cambio_etinombre_output(self, self.OutputList, no, ne, old_name)
# Se actualizan la reglas con el nuevo nombre
if len(self.RuleList) > 0:
actualizar_RulesEtiquetas_out(
self, no, self.main.etiquetaNombreOut.text(), old_name
)
self.main.etiquetaNombreOut.clearFocus()
[documentos]def actualizar_RulesEtiquetas_out(self, no, new_name, old_name):
"""
Función para actualizar el nombre en las reglas previamente creadas con el nuevo nombre de una etiqueta
:param no: Numero de salida
:type no: int
:param new_name: Nuevo nombre para la etiqueta a cambiar
:type new_name: str
:param old_name: Antiguo nombre de la etiqueta a cambiar
:type old_name: str
"""
for sets in self.RuleEtiquetas:
for rule in sets[1]:
if rule[0] == old_name and rule[1] == no:
rule[0] = new_name
self.fuzzController.rulelist = []
self.RuleList = self.fuzzController.crear_reglas(self.RuleEtiquetas)
[documentos]def seleccion_mf_in(self):
""" Función para manejar el cambio de función de membresía para la etiqueta seleccionada """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
ni = self.main.inputNumber.currentIndex()
ne = self.main.etiquetaNumIn.currentIndex()
# Se guarda el nombre de la función de membresía anterior
old_mf = self.InputList[ni]["etiquetas"][ne]["mf"]
definicion = self.InputList[ni]["etiquetas"][ne]["definicion"]
self.InputList[ni]["etiquetas"][ne]["mf"] = self.main.etiquetaMfIn.currentText()
# Se guarda el nombre de la función de membresía seleccionada
new_mf = self.InputList[ni]["etiquetas"][ne]["mf"]
# Se obtiene una definicion aproximada entre la antigua función de membresía y la seleccionada
new_definicion, tooltip = update_definicionmf(self, old_mf, definicion, 'trimf')
new_definicion, tooltip = update_definicionmf(self, 'trimf', new_definicion, self.main.etiquetaMfIn.currentText())
new_definicion = round_list(new_definicion)
self.main.etiquetaDefinicionIn.setText(str(new_definicion))
self.main.etiquetaDefinicionIn.setToolTip(tooltip)
# Se actualiza la nueva definicion a mostrar
definicion_in(self)
[documentos]def definicion_in(self):
"""
Función para manejar el cambio de definicion de la función de membresía correspondiente a la etiqueta actual
"""
try:
deinificion_in_validator(self)
except AssertionError:
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
ni = self.main.inputNumber.currentIndex()
ne = self.main.etiquetaNumIn.currentIndex()
self.InputList[ni]["etiquetas"][ne]["definicion"] = json.loads(
self.main.etiquetaDefinicionIn.text())
# Se actualiza la nueva definicion en el controlador
self.fuzzController.update_definicion_input(self, self.InputList, ni, ne)
self.main.etiquetaDefinicionIn.clearFocus()
[documentos]def deinificion_in_validator(self):
""" Función para validar las definiciones de las funciones de membresía """
mf = self.main.etiquetaMfIn.currentText()
try:
_ = json.loads(self.main.etiquetaDefinicionIn.text())
try:
# Función externa para la validacion
validacion_mf(self, _, mf)
except AssertionError:
self.main.etiquetaDefinicionIn.setFocus()
raise AssertionError
except ValueError:
self.error_dialog.setInformativeText(
"Formato de definicion invalido para la función de membresía: " + mf +
"\nDebe estar entre corchetes con valores separados por comas")
self.error_dialog.exec_()
self.main.etiquetaDefinicionIn.setFocus()
raise AssertionError
[documentos]def seleccion_mf_out(self):
""" Función para manejar el cambio de función de membresía para la etiqueta seleccionada """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
no = self.main.outputNumber.currentIndex()
ne = self.main.etiquetaNumOut.currentIndex()
# Se guarda el nombre de la función de membresía anterior
old_mf = self.OutputList[no]["etiquetas"][ne]["mf"]
definicion = self.OutputList[no]["etiquetas"][ne]["definicion"]
self.OutputList[no]["etiquetas"][ne]["mf"] = self.main.etiquetaMfOut.currentText()
# Se guarda el nombre de la función de membresía seleccionada
new_mf = self.OutputList[no]["etiquetas"][ne]["mf"]
# Se obtiene una definicion aproximada entre la antigua función de membresía y la seleccionada
new_definicion, tooltip = update_definicionmf(self, old_mf, definicion, 'trimf')
new_definicion, tooltip = update_definicionmf(self, 'trimf', new_definicion, self.main.etiquetaMfOut.currentText())
new_definicion = round_list(new_definicion)
self.main.etiquetaDefinicionOut.setText(str(new_definicion))
self.main.etiquetaDefinicionOut.setToolTip(tooltip)
# Se actualiza la nueva definicion a mostrar
definicion_out(self)
[documentos]def definicion_out(self):
"""
Función para manejar el cambio de definicion de la función de membresía correspondiente a la etiqueta actual
"""
try:
deinificion_out_validator(self)
except AssertionError:
return
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
no = self.main.outputNumber.currentIndex()
ne = self.main.etiquetaNumOut.currentIndex()
self.OutputList[no]["etiquetas"][ne]["definicion"] = json.loads(
self.main.etiquetaDefinicionOut.text())
# Se actualiza la nueva definicion en el controlador
self.fuzzController.update_definicion_output(self, self.OutputList, no, ne)
self.main.etiquetaDefinicionOut.clearFocus()
[documentos]def deinificion_out_validator(self):
""" Función para validar las definiciones de las funciones de membresía """
mf = self.main.etiquetaMfOut.currentText()
try:
_ = json.loads(self.main.etiquetaDefinicionOut.text())
try:
# Función externa para la validacion
validacion_mf(self, _, mf)
except AssertionError:
self.main.etiquetaDefinicionOut.setFocus()
raise AssertionError
except ValueError:
self.error_dialog.setInformativeText(
"Formato de definicion invalido para la función de membresía: " + mf +
"\nDebe estar entre corchetes con valores separados por comas")
self.error_dialog.exec_()
self.main.etiquetaDefinicionOut.setFocus()
raise AssertionError
[documentos]def round_list(lista):
"""
Función para redondear los dígitos de una lista
:param lista: Lista con valores a redondear
:type lista: list
:return: Lista con valores redondeados
:rtype: list
"""
return list(np.around(np.array(lista), 3))
[documentos]def rule_list_visualizacion(self):
""" Función para mostrar las reglas creadas para el controlador actual en un listWidget """
if self.main.fuzzyTabWidget.currentIndex() == 3:
self.main.rulelistWidget.blockSignals(True)
self.main.rulelistWidget.clear()
for regla in self.RuleList:
self.main.rulelistWidget.addItem(str(regla))
# Se ocultan los widgets necesarios en función del numero de entradas y salidas
for i, o in zip(self.inframes, self.outframes):
i.hide()
o.hide()
for i, o in zip(self.inlists, self.outlists):
i.clear()
o.clear()
self.main.rulelistWidget.setCurrentRow(0)
# Se muestran los widgets necesarios en función del numero de entradas
for i, entrada in enumerate(self.InputList):
self.inframes[i].show()
self.inlabels[i].setText(entrada["nombre"])
for etiqueta in entrada["etiquetas"]:
self.inlists[i].addItem(etiqueta["nombre"])
self.inlists[i].addItem("None")
self.inlists[i].setCurrentRow(0)
# Se muestran los widgets necesarios en función del numero de salidas
for o, salida in enumerate(self.OutputList):
self.outframes[o].show()
self.outlabels[o].setText(salida["nombre"])
for etiqueta in salida["etiquetas"]:
self.outlists[o].addItem(etiqueta["nombre"])
self.outlists[o].addItem("None")
self.outlists[o].setCurrentRow(0)
self.main.rulelistWidget.blockSignals(False)
seleccionar_etiquetas(self)
[documentos]def seleccionar_etiquetas(self):
"""
Función para seleccionar las etiquetas correspondientes a cada entrada/salida de la regla seleccionada
"""
if len(self.RuleEtiquetas) > 0:
ni = len(self.InputList)
no = len(self.OutputList)
ruleindex = self.main.rulelistWidget.currentRow()
Etiquetasin, Etiquetasout, logica = self.RuleEtiquetas[ruleindex]
# Chequeo de AND o OR
if logica:
self.main.andradioButton.setChecked(True)
else:
self.main.orradioButton.setChecked(True)
# Determinando que etiquetas corresponden a cada entrada
for index in range(ni):
for Etiquetasin2 in Etiquetasin:
if Etiquetasin2[1] == index:
item = self.inlists[index].findItems(
Etiquetasin2[0], QtCore.Qt.MatchExactly
)
self.inlists[index].setCurrentItem(item[-1])
if Etiquetasin2[2]:
self.innots[index].setChecked(True)
else:
self.innots[index].setChecked(False)
break
else:
item = self.inlists[index].findItems("None", QtCore.Qt.MatchExactly)
self.inlists[index].setCurrentItem(item[-1])
self.innots[index].setChecked(False)
# Determinando que etiquetas corresponden a cada salida
for index in range(no):
for Etiquetasout2 in Etiquetasout:
if Etiquetasout2[1] == index:
item = self.outlists[index].findItems(
Etiquetasout2[0], QtCore.Qt.MatchExactly
)
self.outlists[index].setCurrentItem(item[-1])
self.outweights[index].setValue(Etiquetasout2[2])
break
else:
item = self.outlists[index].findItems("None", QtCore.Qt.MatchExactly)
self.outlists[index].setCurrentItem(item[-1])
[documentos]def rule_list_agregar(self):
"""
Función para crear una nueva regla a partir de las etiquetas seleccionadas para cada entrada y salida
"""
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
ni = len(self.InputList)
no = len(self.OutputList)
Etiquetasin = []
Etiquetasout = []
# Información de la entrada para la regla
for i, entrada in enumerate(self.InputList):
if self.inlists[i].currentItem().text() != "None":
Etiquetasin.append(
[self.inlists[i].currentItem().text(), i, self.innots[i].isChecked()]
)
# Información de la salida para la regla
for o, salida in enumerate(self.OutputList):
if self.outlists[o].currentItem().text() != "None":
Etiquetasout.append(
[self.outlists[o].currentItem().text(), o, self.outweights[o].value()]
)
# Si la regla es valida, se agrega al controlador y al listWidget
if len(Etiquetasin) > 0 and len(Etiquetasout) > 0:
self.RuleEtiquetas.append(
copy.deepcopy(
[Etiquetasin, Etiquetasout, self.main.andradioButton.isChecked()]))
self.RuleList.append(
self.fuzzController.agregar_regla(self,
Etiquetasin,
Etiquetasout,
self.main.andradioButton.isChecked()))
self.main.rulelistWidget.addItem(str(self.RuleList[-1]))
self.main.rulelistWidget.setCurrentRow(len(self.RuleList) - 1)
else:
self.error_dialog.setInformativeText(
"Regla no valida, debe contener al menos una entrada y una salida"
)
self.error_dialog.exec_()
[documentos]def rule_list_eliminar(self):
""" Función para eliminar una regla """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
if self.main.rulelistWidget.count():
index_rule = self.main.rulelistWidget.currentRow()
self.fuzzController.eliminar_regla(index_rule)
self.main.rulelistWidget.takeItem(self.main.rulelistWidget.currentRow())
del self.RuleList[index_rule]
del self.RuleEtiquetas[index_rule]
[documentos]def rule_list_cambiar(self):
""" Función para modificar una regla """
self.main.fuzzyTabWidget.removeTab(5)
self.main.fuzzyTabWidget.removeTab(4)
index_rule = self.main.rulelistWidget.currentRow()
ni = len(self.InputList)
no = len(self.OutputList)
Etiquetasin = []
Etiquetasout = []
# Información de la entrada para la nueva regla
for i, entrada in enumerate(self.InputList):
if self.inlists[i].currentItem().text() != "None":
Etiquetasin.append(
[self.inlists[i].currentItem().text(), i, self.innots[i].isChecked()]
)
# Información de la salida para la nueva regla
for o, salida in enumerate(self.OutputList):
if self.outlists[o].currentItem().text() != "None":
Etiquetasout.append(
[self.outlists[o].currentItem().text(), o, self.outweights[o].value()]
)
# Si la nueva regla es valida, se elimina la anterior y se agrega al controlador y al listWidget
if len(Etiquetasin) > 0 and len(Etiquetasout) > 0:
del self.RuleEtiquetas[index_rule]
self.RuleEtiquetas.insert(
index_rule,
copy.deepcopy(
[Etiquetasin, Etiquetasout, self.main.andradioButton.isChecked()]
),
)
regla = self.fuzzController.cambiar_regla(self,
Etiquetasin,
Etiquetasout,
index_rule,
self.main.andradioButton.isChecked())
self.main.rulelistWidget.takeItem(index_rule)
self.main.rulelistWidget.insertItem(index_rule, str(regla))
self.main.rulelistWidget.setCurrentRow(index_rule)
del self.RuleList[index_rule]
self.RuleList.insert(index_rule, regla)
else:
self.error_dialog.setInformativeText(
"Regla no valida, debe contener al menos una entrada y una salida"
)
self.error_dialog.exec_()
[documentos]def crear_controlador(self):
"""
Función para crear el controlador a partir de toda la información recolectada, esta creación se realiza con el fin de realizar la prueba del controlador y observar la superficie de respuesta del controlador en caso de poseer una o dos entradas
"""
if self.main.rulelistWidget.count():
self.fuzzController = self.fuzzInitController(
self.InputList, self.OutputList, self.RuleEtiquetas
)
self.RuleList = copy.deepcopy(self.fuzzController.rulelist)
self.main.fuzzyTabWidget.addTab(self.PruebaTab, "Prueba")
ni = len(self.InputList)
no = len(self.OutputList)
# Se ocultan los widgets necesarios en función del numero de entradas y salidas
for it_f, ot_f, f2d, f3d in zip(
self.intestframes,
self.outtestframes,
self.respuesta2dframes,
self.respuesta3dframes,
):
it_f.hide()
ot_f.hide()
f2d.hide()
f3d.hide()
# Se muestran los widgets necesarios en función del numero de entradas
for i, salida in enumerate(self.InputList):
self.intestframes[i].show()
# Se muestran los widgets necesarios en función del numero de salidas
for o, salida in enumerate(self.OutputList):
self.outtestframes[o].show()
# Ejecucion del código correspondiente a la prueba del controlador
prueba_input(self)
# Chequeo del numero de entradas
if ni == 1:
self.main.fuzzyTabWidget.addTab(self.RespuestaTab, "Respuesta")
self.main.respuestastackedWidget.setCurrentIndex(0)
for o, salida in enumerate(self.OutputList):
self.respuesta2dframes[o].show()
rimin, rimax = self.InputList[0]["rango"]
self.fuzzController.graficar_respuesta_2d(self, [rimin, rimax], no)
if ni == 2:
self.main.fuzzyTabWidget.addTab(self.RespuestaTab, "Respuesta")
self.main.respuestastackedWidget.setCurrentIndex(1)
for o, salida in enumerate(self.OutputList):
self.respuesta3dframes[o].show()
rimin1, rimax1 = self.InputList[0]["rango"]
rimin2, rimax2 = self.InputList[1]["rango"]
self.fuzzController.graficar_respuesta_3d(
self, [rimin1, rimax1], [rimin2, rimax2], no
)