Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
b0e78b3f6d | |||
ca3fdf03ca | |||
d75f598425 | |||
0fa51fd003 | |||
b09a9200b1 |
122
lab10/lab10.py
Normal file
122
lab10/lab10.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import sys
|
||||||
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QLineEdit, QPushButton, QColorDialog, QTableWidget, QTableWidgetItem, QHeaderView
|
||||||
|
from PyQt5.QtGui import QColor
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
class FuzzyScaleApp(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle("Оценка прибыли")
|
||||||
|
self.setGeometry(100, 100, 800, 600)
|
||||||
|
|
||||||
|
self.plot_widget = pg.PlotWidget()
|
||||||
|
self.table_widget = QTableWidget()
|
||||||
|
self.table_widget.setColumnCount(6)
|
||||||
|
self.table_widget.setHorizontalHeaderLabels(["Название", "Тип", "a", "b", "c", "d"])
|
||||||
|
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
|
||||||
|
self.add_btn = QPushButton("Добавить")
|
||||||
|
self.remove_btn = QPushButton("Удалить")
|
||||||
|
self.update_btn = QPushButton("Обновить график")
|
||||||
|
|
||||||
|
main_widget = QWidget()
|
||||||
|
main_layout = QVBoxLayout()
|
||||||
|
main_layout.addWidget(self.plot_widget)
|
||||||
|
main_layout.addWidget(self.table_widget)
|
||||||
|
button_layout = QVBoxLayout()
|
||||||
|
button_layout.addWidget(self.add_btn)
|
||||||
|
button_layout.addWidget(self.remove_btn)
|
||||||
|
button_layout.addWidget(self.update_btn)
|
||||||
|
main_layout.addLayout(button_layout)
|
||||||
|
main_widget.setLayout(main_layout)
|
||||||
|
self.setCentralWidget(main_widget)
|
||||||
|
|
||||||
|
self.membership_functions = [
|
||||||
|
["Низкая", "Треугольная", 10, 20, 30, None],
|
||||||
|
["Средняя", "Трапециевидная", 15, 25, 35, 45],
|
||||||
|
["Высокая", "Треугольная", 40, 50, 60, None],
|
||||||
|
]
|
||||||
|
self.update_table()
|
||||||
|
self.update_plot()
|
||||||
|
|
||||||
|
self.add_btn.clicked.connect(self.add_function)
|
||||||
|
self.remove_btn.clicked.connect(self.remove_function)
|
||||||
|
self.table_widget.cellChanged.connect(self.update_data)
|
||||||
|
self.update_btn.clicked.connect(self.update_plot)
|
||||||
|
|
||||||
|
def update_data(self):
|
||||||
|
print(self.membership_functions)
|
||||||
|
for row in range(self.table_widget.rowCount()):
|
||||||
|
for column in range(6):
|
||||||
|
index = self.table_widget.model().index(row, column)
|
||||||
|
data = self.table_widget.model().data(index)
|
||||||
|
if column == 5:
|
||||||
|
if self.membership_functions[row][1] == 'Треугольная' and data != '':
|
||||||
|
self.membership_functions[row][1] = 'Трапециевидная'
|
||||||
|
elif self.membership_functions[row][column] == 'Трапециевидная' and data == '':
|
||||||
|
self.membership_functions[row][1] = 'Треугольная'
|
||||||
|
if data == '':
|
||||||
|
self.membership_functions[row][column] = None
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
self.membership_functions[row][column] = int(data)
|
||||||
|
except ValueError:
|
||||||
|
self.membership_functions[row][column] = data
|
||||||
|
print(self.membership_functions)
|
||||||
|
|
||||||
|
def add_function(self):
|
||||||
|
print("чмо")
|
||||||
|
row_count = self.table_widget.rowCount()
|
||||||
|
self.table_widget.insertRow(row_count)
|
||||||
|
self.table_widget.setItem(row_count, 0, QTableWidgetItem("Новая функция"))
|
||||||
|
self.table_widget.setItem(row_count, 1, QTableWidgetItem("Треугольная"))
|
||||||
|
self.membership_functions.append(["Новая функция", "Треугольная", 0, 25, 50, None])
|
||||||
|
self.update_table()
|
||||||
|
self.update_plot()
|
||||||
|
|
||||||
|
def remove_function(self):
|
||||||
|
selected_rows = self.table_widget.selectionModel().selectedRows()
|
||||||
|
rows_to_remove = [index.row() for index in selected_rows]
|
||||||
|
rows_to_remove.sort(reverse=True)
|
||||||
|
for row in rows_to_remove:
|
||||||
|
self.table_widget.removeRow(row)
|
||||||
|
del self.membership_functions[row]
|
||||||
|
self.update_plot()
|
||||||
|
|
||||||
|
def update_table(self):
|
||||||
|
self.table_widget.setRowCount(len(self.membership_functions))
|
||||||
|
row = 0
|
||||||
|
for (name, mf_type, a, b, c, d) in self.membership_functions:
|
||||||
|
self.table_widget.setItem(row, 0, QTableWidgetItem(name))
|
||||||
|
self.table_widget.setItem(row, 1, QTableWidgetItem(mf_type))
|
||||||
|
self.table_widget.setItem(row, 2, QTableWidgetItem(str(a)))
|
||||||
|
self.table_widget.setItem(row, 3, QTableWidgetItem(str(b)))
|
||||||
|
self.table_widget.setItem(row, 4, QTableWidgetItem(str(c)))
|
||||||
|
self.table_widget.setItem(row, 5, QTableWidgetItem(str(d) if d is not None else ""))
|
||||||
|
row += 1
|
||||||
|
|
||||||
|
def update_plot(self):
|
||||||
|
self.plot_widget.clear()
|
||||||
|
print('лох')
|
||||||
|
x = [-10, 110]
|
||||||
|
y = [0, 0]
|
||||||
|
self.plot_widget.plot(x, y)
|
||||||
|
for (name, mf_type, a, b, c, d) in self.membership_functions:
|
||||||
|
print(name, mf_type, a, b, c, d)
|
||||||
|
if mf_type == "Треугольная":
|
||||||
|
x = [a, b, c]
|
||||||
|
y = [0, 1, 0]
|
||||||
|
self.plot_widget.plot(x, y, name=name, pen=pg.mkPen(QColor(random.randint(0,255), random.randint(0,255), random.randint(0,255)), width=2))
|
||||||
|
else:
|
||||||
|
x = [a, b, c, d]
|
||||||
|
y = [0, 1, 1, 0]
|
||||||
|
self.plot_widget.plot(x, y, name=name, pen=pg.mkPen(QColor(random.randint(0,255), random.randint(0,255), random.randint(0,255)), width=2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
fuzzy_scale_app = FuzzyScaleApp()
|
||||||
|
fuzzy_scale_app.show()
|
||||||
|
sys.exit(app.exec_())
|
104
lab11/lab11.py
Normal file
104
lab11/lab11.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import math
|
||||||
|
import random
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def get_distance(first: np.ndarray, second: np.ndarray) -> float:
|
||||||
|
return math.sqrt(sum([(first[i] - second[i]) ** 2 for i in range(first.shape[0])])) + 1e-5
|
||||||
|
|
||||||
|
|
||||||
|
def affiliation_calculation(data: np.ndarray, centers: np.ndarray, k: int, m: int) -> np.ndarray:
|
||||||
|
data_len = data.shape[0]
|
||||||
|
u = np.zeros((data_len, k))
|
||||||
|
for i in range(data_len):
|
||||||
|
for j in range(k):
|
||||||
|
total = 0
|
||||||
|
distance = get_distance(data[i], centers[j])
|
||||||
|
for c in range(k):
|
||||||
|
total += (distance / get_distance(data[i], centers[c])) ** (2 / (m - 1))
|
||||||
|
u[i, j] = 1 / total
|
||||||
|
return u
|
||||||
|
|
||||||
|
|
||||||
|
def variance_calculation(data: np.ndarray, centers: np.ndarray, u: np.ndarray) -> float:
|
||||||
|
value = 0
|
||||||
|
for j in range(k):
|
||||||
|
for i in range(data.shape[0]):
|
||||||
|
value += get_distance(data[i], centers[j]) ** 2 * u[i, j]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def center_update(data: np.ndarray, u: np.ndarray, k: int, m: int) -> np.ndarray:
|
||||||
|
centers = np.zeros((k, data.shape[1]))
|
||||||
|
for j in range(k):
|
||||||
|
total = 0
|
||||||
|
for i in range(data.shape[0]):
|
||||||
|
total += u[i, j] ** m * data[i]
|
||||||
|
centers[j] = total / np.sum(u[:, j] ** m)
|
||||||
|
return centers
|
||||||
|
|
||||||
|
|
||||||
|
def fuzzy_c_means(data: np.ndarray, k: int, m: int, max_iter: int = 100, tol: float = 1e-5) -> (
|
||||||
|
np.ndarray, np.ndarray, float):
|
||||||
|
centers = np.array([[random.randint(data.min(), data.max()) for i in range(data.shape[1])] for j in range(k)])
|
||||||
|
u = None
|
||||||
|
|
||||||
|
value = 0
|
||||||
|
|
||||||
|
for _ in range(max_iter):
|
||||||
|
u = affiliation_calculation(data, centers, k, m)
|
||||||
|
|
||||||
|
new_value = variance_calculation(data, centers, u)
|
||||||
|
if abs(new_value - value) <= tol:
|
||||||
|
return centers, u, value
|
||||||
|
|
||||||
|
value = new_value
|
||||||
|
|
||||||
|
centers = center_update(data, u, k, m)
|
||||||
|
|
||||||
|
return centers, u, value
|
||||||
|
|
||||||
|
|
||||||
|
def visualise_resout(centers: np.ndarray, u: np.ndarray):
|
||||||
|
center_colors = [[random.random(), random.random(), random.random()] for i in range(k)]
|
||||||
|
point_colors = []
|
||||||
|
for i in u:
|
||||||
|
tmp_color = [0, 0, 0]
|
||||||
|
for j in range(k):
|
||||||
|
tmp_color[0] += center_colors[j][0] * i[j]
|
||||||
|
tmp_color[1] += center_colors[j][1] * i[j]
|
||||||
|
tmp_color[2] += center_colors[j][1] * i[j]
|
||||||
|
point_colors.append(tmp_color)
|
||||||
|
|
||||||
|
plt.title("Нечёткая кластеризация")
|
||||||
|
plt.xlabel("Размер зарплаты")
|
||||||
|
|
||||||
|
if data.shape[1] == 1:
|
||||||
|
plt.scatter(data[:, 0], [0] * data.shape[0], c=point_colors)
|
||||||
|
plt.scatter(centers[:, 0], [0] * centers.shape[0], marker='*', edgecolor='black', s=100, c=center_colors)
|
||||||
|
plt.gca().axes.get_yaxis().set_visible(False)
|
||||||
|
else:
|
||||||
|
plt.scatter(data[:, 0], data[:, 1], c=point_colors)
|
||||||
|
plt.scatter(centers[:, 0], centers[:, 1], marker='*', edgecolor='black', s=100, c=center_colors)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
data: np.ndarray = np.array(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
random.randint(0, 500)
|
||||||
|
]
|
||||||
|
for i in range(random.randint(40, 100))
|
||||||
|
])
|
||||||
|
k = 3
|
||||||
|
m = 2
|
||||||
|
|
||||||
|
centers, u, value = fuzzy_c_means(data, k, m)
|
||||||
|
print(f"Значение функции отклонений: {value}")
|
||||||
|
print("Степени принадлежности первых 10 точек:")
|
||||||
|
print(*u[:10], sep="\n")
|
||||||
|
print("Центры всех кластеров:")
|
||||||
|
print(*centers, sep="\n")
|
||||||
|
visualise_resout(centers, u)
|
20
lab12/FuzzyRule.py
Normal file
20
lab12/FuzzyRule.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
class FuzzyRule:
|
||||||
|
def __init__(self):
|
||||||
|
self.condition: dict[str, str] = {}
|
||||||
|
self.resout: (str, str) = None
|
||||||
|
|
||||||
|
def add_condition(self, variable: str, value: str):
|
||||||
|
self.condition[variable] = value
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_resout(self, variable: str, value: str):
|
||||||
|
self.resout = (variable, value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def calculate_res(self, variables: dict[str, dict[str, float]]) -> (str, str, float):
|
||||||
|
res = 1
|
||||||
|
|
||||||
|
for i in self.condition:
|
||||||
|
res = min(res, variables[i][self.condition[i]])
|
||||||
|
|
||||||
|
return self.resout[0], self.resout[1], res
|
21
lab12/FuzzySet.py
Normal file
21
lab12/FuzzySet.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
class FuzzySet:
|
||||||
|
def __init__(self, name: str, a: float, b: float, c: float, d: float):
|
||||||
|
self.name = name
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
self.c = c
|
||||||
|
self.d = d
|
||||||
|
|
||||||
|
def affiliation(self, x: float) -> float:
|
||||||
|
if x <= self.a or x >= self.d:
|
||||||
|
return 0
|
||||||
|
if self.b <= x <= self.c:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if x <= self.b:
|
||||||
|
return (x - self.a) / (self.b - self.a)
|
||||||
|
else:
|
||||||
|
return (self.d - x) / (self.d - self.c)
|
||||||
|
|
||||||
|
def defuzzification(self) -> float:
|
||||||
|
return (self.c + self.b) / 2
|
24
lab12/LinguisticVariable.py
Normal file
24
lab12/LinguisticVariable.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from FuzzySet import FuzzySet
|
||||||
|
|
||||||
|
|
||||||
|
class LinguisticVariable:
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.name = name
|
||||||
|
self.fuzzy_sets: dict[str, FuzzySet] = {}
|
||||||
|
|
||||||
|
def add_fuzzy_set(self, name: str, a: float, b: float, c: float, d: float):
|
||||||
|
if not (a <= b <= c <= d):
|
||||||
|
return
|
||||||
|
|
||||||
|
if name in self.fuzzy_sets:
|
||||||
|
fuzzy = self.fuzzy_sets[name]
|
||||||
|
fuzzy.a = a
|
||||||
|
fuzzy.b = b
|
||||||
|
fuzzy.c = c
|
||||||
|
fuzzy.d = d
|
||||||
|
else:
|
||||||
|
self.fuzzy_sets[name] = FuzzySet(name, a, b, c, d)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_all_supplies(self, x: float) -> dict[str, float]:
|
||||||
|
return {i: self.fuzzy_sets[i].affiliation(x) for i in self.fuzzy_sets}
|
105
lab12/main.py
Normal file
105
lab12/main.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
from FuzzyRule import FuzzyRule
|
||||||
|
from LinguisticVariable import LinguisticVariable
|
||||||
|
|
||||||
|
|
||||||
|
def get_linguistic_data(vars: list[LinguisticVariable], x: dict[str, float]) -> dict[str, dict[str, float]]:
|
||||||
|
return {i.name: i.get_all_supplies(x[i.name]) for i in vars}
|
||||||
|
|
||||||
|
|
||||||
|
def get_rule_table_res(rules: list[FuzzyRule], vars: list[LinguisticVariable], x: dict[str, float]) \
|
||||||
|
-> (str, str, float):
|
||||||
|
res = [i.calculate_res(get_linguistic_data(vars, x)) for i in rules]
|
||||||
|
|
||||||
|
return sorted(res, key=lambda y: -y[2])[0]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
variables: list[LinguisticVariable] = [
|
||||||
|
LinguisticVariable("Часы эксплуатации")
|
||||||
|
.add_fuzzy_set("мало", 0, 0, 100, 200)
|
||||||
|
.add_fuzzy_set("средне", 100, 300, 500, 700)
|
||||||
|
.add_fuzzy_set("много", 500, 800, 1000, 1000),
|
||||||
|
|
||||||
|
LinguisticVariable("Срок последней проверки")
|
||||||
|
.add_fuzzy_set("недавно", 0, 0, 3, 6)
|
||||||
|
.add_fuzzy_set("давно", 3, 6, 12, 18)
|
||||||
|
.add_fuzzy_set("очень давно", 12, 18, 24, 24),
|
||||||
|
|
||||||
|
LinguisticVariable("Риск поломки")
|
||||||
|
.add_fuzzy_set("низкий", 0, 0, 20, 40)
|
||||||
|
.add_fuzzy_set("средний", 20, 40, 60, 80)
|
||||||
|
.add_fuzzy_set("высокий", 60, 80, 100, 100)
|
||||||
|
]
|
||||||
|
|
||||||
|
rules: list[FuzzyRule] = [
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'мало')
|
||||||
|
.add_condition("Срок последней проверки", 'недавно')
|
||||||
|
.add_resout("Риск поломки", 'низкий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'мало')
|
||||||
|
.add_condition("Срок последней проверки", 'давно')
|
||||||
|
.add_resout("Риск поломки", 'низкий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'мало')
|
||||||
|
.add_condition("Срок последней проверки", 'очень давно')
|
||||||
|
.add_resout("Риск поломки", 'средний'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'средне')
|
||||||
|
.add_condition("Срок последней проверки", 'недавно')
|
||||||
|
.add_resout("Риск поломки", 'низкий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'средне')
|
||||||
|
.add_condition("Срок последней проверки", 'давно')
|
||||||
|
.add_resout("Риск поломки", 'средний'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'средне')
|
||||||
|
.add_condition("Срок последней проверки", 'очень давно')
|
||||||
|
.add_resout("Риск поломки", 'высокий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'много')
|
||||||
|
.add_condition("Срок последней проверки", 'недавно')
|
||||||
|
.add_resout("Риск поломки", 'средний'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'много')
|
||||||
|
.add_condition("Срок последней проверки", 'давно')
|
||||||
|
.add_resout("Риск поломки", 'высокий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'много')
|
||||||
|
.add_condition("Срок последней проверки", 'очень давно')
|
||||||
|
.add_resout("Риск поломки", 'высокий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'мало')
|
||||||
|
.add_condition("Срок последней проверки", 'недавно')
|
||||||
|
.add_resout("Риск поломки", 'низкий'),
|
||||||
|
|
||||||
|
FuzzyRule()
|
||||||
|
.add_condition("Часы эксплуатации", 'много')
|
||||||
|
.add_condition("Срок последней проверки", 'недавно')
|
||||||
|
.add_resout("Риск поломки", 'средний')
|
||||||
|
]
|
||||||
|
|
||||||
|
input_data: dict[str, float] = {
|
||||||
|
"Часы эксплуатации": 550,
|
||||||
|
"Срок последней проверки": 15
|
||||||
|
}
|
||||||
|
|
||||||
|
varz = []
|
||||||
|
for i in variables:
|
||||||
|
if i.name in input_data:
|
||||||
|
varz.append(i)
|
||||||
|
|
||||||
|
name, value, confidence = get_rule_table_res(rules, varz, input_data)
|
||||||
|
print(name, value)
|
||||||
|
for i in variables:
|
||||||
|
if i.name == name:
|
||||||
|
print(i.fuzzy_sets[value].defuzzification())
|
42
lab9/lab9.py
Normal file
42
lab9/lab9.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
print("Введите минимальное значение (первое основание треугольника) :")
|
||||||
|
min_value = float(input())
|
||||||
|
|
||||||
|
print("Введите максимальное значение (второе основание треугольника) :")
|
||||||
|
max_value = float(input())
|
||||||
|
|
||||||
|
if max_value < min_value:
|
||||||
|
max_value, min_value = min_value, max_value
|
||||||
|
|
||||||
|
print("Введите центральное значение (вершина треугольника) :")
|
||||||
|
center_value = float(input())
|
||||||
|
|
||||||
|
print("Введите значение объекта для проверки степени принадлежности:")
|
||||||
|
x = float(input())
|
||||||
|
|
||||||
|
if min_value <= x <= center_value:
|
||||||
|
membership = (x - min_value) / (center_value - min_value)
|
||||||
|
elif center_value < x <= max_value:
|
||||||
|
membership = (max_value - x) / (max_value - center_value)
|
||||||
|
elif x < min_value or x > max_value:
|
||||||
|
membership = 0
|
||||||
|
else:
|
||||||
|
membership = -1
|
||||||
|
|
||||||
|
|
||||||
|
if membership == -1:
|
||||||
|
print("Не удалось рассчитать степень принадлежности объекта")
|
||||||
|
|
||||||
|
|
||||||
|
print(f"Минимум: {min_value}")
|
||||||
|
print(f"Максимум: {max_value}")
|
||||||
|
print(f"Центр: {center_value}")
|
||||||
|
print(f"Степень принадлежности {x}: {membership:.2f}")
|
||||||
|
|
||||||
|
X = [min_value, center_value, max_value]
|
||||||
|
Y = [0, 1, 0]
|
||||||
|
|
||||||
|
plt.plot(X, Y)
|
||||||
|
plt.plot(x, membership, 'ro')
|
||||||
|
plt.show()
|
Loading…
Reference in New Issue
Block a user