動物識別專家系統課程設計
阿新 • • 發佈:2017-12-23
包含 logic get() pytho 都在 txt tgui ati 是否
title: 動物識別專家系統課程設計
date: 2017-12-23 18:44:13
tags:
categories: python
設計一個可以識別7種動物的專家系統,可以根據前提推導出結論,如果只有部分前提,詢問提示。
RD.txt是規則庫,一行一條,每條空格分隔,前面是前提,最後一個是結論。
用PyQt5設計界面
RD.txt
有毛發 哺乳動物 有奶 哺乳動物 有羽毛 鳥 會飛 下蛋 鳥 吃肉 食肉動物 有犬齒 有爪 眼盯前方 食肉動物 哺乳動物 有蹄 有蹄類動物 哺乳動物 嚼反芻動物 有蹄類動物 哺乳動物 食肉動物 黃褐色 暗斑點 金錢豹 哺乳動物 食肉動物 黃褐色 黑色條紋 虎 有蹄類動物 長脖子 長腿 暗斑點 長頸鹿 有蹄類動物 黑色條紋 斑馬 鳥 長脖子 長腿 黑白二色 不飛 鴕鳥 鳥 會遊泳 不飛 黑白二色 企鵝 鳥 善飛 信天翁
主要文件,包含界面
main.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.setGeometry(100, 200, 623, 300)
self.groupBox = QtWidgets.QGroupBox(Form)
self .groupBox.setGeometry(QtCore.QRect(10, -20, 600, 311))
self.groupBox.setTitle("")
self.groupBox.setObjectName("groupBox")
self.label = QtWidgets.QLabel(self.groupBox)
self.label.setGeometry(QtCore.QRect(30, 40, 61, 18))
self.label.setAlignment(QtCore.Qt.AlignCenter)
self .label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.groupBox)
self.label_2.setGeometry(QtCore.QRect(470, 40, 101, 18))
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.pushButton = QtWidgets.QPushButton(self.groupBox)
self.pushButton.setGeometry(QtCore.QRect(230, 35, 88, 27))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
self.pushButton_2.setGeometry(QtCore.QRect(475, 190, 88, 27))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_2.clicked.connect(self.btn2_click)
self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
self.pushButton_3.setGeometry(QtCore.QRect(475, 240, 88, 27))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_3.clicked.connect(QtCore.QCoreApplication.instance().quit)
self.pushButton_4 = QtWidgets.QPushButton(self.groupBox)
self.pushButton_4.setGeometry(475, 140, 88, 27)
self.pushButton_4.setObjectName("pushButton_4")
self.pushButton_4.clicked.connect(self.topological)
self.textEdit = QtWidgets.QTextEdit(self.groupBox)
self.textEdit.setGeometry(QtCore.QRect(20, 80, 80, 211))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.groupBox)
self.textEdit_2.setGeometry(QtCore.QRect(110, 80, 331, 211))
self.textEdit_2.setObjectName("textEdit_2")
self.textEdit_2.setReadOnly(True)
self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
self.lineEdit.move(460, 90)
self.lineEdit.setReadOnly(True)
self.pushButton.clicked.connect(self.go)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def btn2_click(self):
if self.pushButton_2.text() != "確定輸入":
self.pushButton_2.setText("確定輸入")
else:
self.pushButton_2.setText("修改知識庫")
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "動物識別專家系統"))
self.label.setText(_translate("Form", "輸入事實"))
self.label_2.setText(_translate("Form", "顯示推理結果"))
self.pushButton.setText(_translate("Form", "進行推理"))
self.pushButton_2.setText(_translate("Form", "修改知識庫"))
self.pushButton_3.setText(_translate("Form", "退出程序"))
self.pushButton_4.setText(_translate("From", "整理知識庫"))
# 將知識庫做拓撲排序
def topological(self):
Q = []
P = []
ans = "" # 排序後的結果
for line in open('RD.txt'):
line = line.strip('\n')
if line == '':
continue
line = line.split(' ')
Q.append(line[line.__len__() - 1])
del (line[line.__len__() - 1])
P.append(line)
# 計算入度
inn = []
for i in P:
sum = 0
for x in i:
if Q.count(x) > 0: # 能找到,那麽
sum += Q.count(x)
inn.append(sum)
while (1):
x = 0
if inn.count(-1) == inn.__len__():
break
for i in inn:
if i == 0:
str = ' '.join(P[x])
# print("%s %s" %(str, Q[x]))
ans = ans + str + " " + Q[x] + "\n" # 寫入結果
# print("%s -- %s" %(P[x],Q[x]))
inn[x] = -1
# 更新入度
y = 0
for j in P:
if j.count(Q[x]) == 1:
inn[y] -= 1
y += 1
x += 1
print(ans)
# 將結果寫入文件
fw = open('RD.txt', 'w', buffering=1)
fw.write(ans)
fw.flush()
fw.close()
# 進行推理
def go(self, flag=True):
# 將產生式規則放入規則庫中
# if P then Q
# 讀取產生式文件
self.Q = []
self.P = []
fo = open('RD.txt', 'r', encoding='utf-8')
for line in fo:
line = line.strip('\n')
if line == '':
continue
line = line.split(' ')
self.Q.append(line[line.__len__() - 1])
del (line[line.__len__() - 1])
self.P.append(line)
fo.close()
print("go按鈕按下")
self.lines = self.textEdit.toPlainText()
self.lines = self.lines.split('\n') # 分割成組
self.DB = set(self.lines)
print(self.DB)
self.str = ""
print(self.str)
flag = True
temp = ""
for x in self.P: # 對於每條產生式規則
if ListInSet(x, self.DB): # 如果所有前提條件都在規則庫中
self.DB.add(self.Q[self.P.index(x)])
temp = self.Q[self.P.index(x)]
flag = False # 至少能推出一個結論
# print("%s --> %s" %(x, self.Q[self.P.index(x)]))
self.str += "%s --> %s\n" % (x, self.Q[self.P.index(x)])
if flag: # 一個結論都推不出
print("一個結論都推不出")
for x in self.P: # 對於每條產生式
if ListOneInSet(x, self.DB): # 事實是否滿足部分前提
flag1 = False # 默認提問時否認前提
for i in x: # 對於前提中所有元素
if i not in self.DB: # 對於不滿足的那部分
btn = s.quest("是否" + i)
if btn == QtWidgets.QMessageBox.Ok:
self.textEdit.setText(self.textEdit.toPlainText() + "\n" + i) # 確定則增加到textEdit
self.DB.add(i) # 確定則增加到規則庫中
flag1 = True # 肯定前提
# self.go(self)
if flag1: # 如果肯定前提,則重新推導
self.go()
return
self.textEdit_2.setPlainText(self.str)
print("----------------------")
print(self.str)
if flag:
btn = s.alert("啥也推不出來!!!")
# if btn == QtWidgets.QMessageBox.Ok: # 點擊確定
# self.textEdit.setText(self.textEdit.toPlainText() + "\n確定")
else:
self.lineEdit.setText(temp)
# 判斷list中至少有一個在集合set中
def ListOneInSet(li, se):
for i in li:
if i in se:
return True
return False
# 判斷list中所有元素是否都在集合set中
def ListInSet(li, se):
for i in li:
if i not in se:
return False
return True
class SecondWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(SecondWindow, self).__init__(parent)
self.setWindowTitle("修改知識庫")
self.setGeometry(725, 200, 300, 300)
self.textEdit = QtWidgets.QTextEdit(self)
self.textEdit.setGeometry(8, 2, 284, 286)
# 警告沒有推導結果
def alert(self, info):
QtWidgets.QMessageBox.move(self, 200, 200)
QtWidgets.QMessageBox.information(self, "Information", self.tr(info))
# 詢問補充事實
def quest(self, info):
# 如果推理為空,需要詢問用戶是否要添加已知條件
QtWidgets.QMessageBox.move(self, 200, 200)
button = QtWidgets.QMessageBox.question(self, "Question",
self.tr(info),
QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel,
QtWidgets.QMessageBox.Cancel)
return button
def handle_click(self):
if not self.isVisible():
# 讀取文件放到多行文本框中
str = ""
fo = open('RD.txt', 'r', encoding='utf-8')
for line in fo:
line = line.strip('\n')
if line == '':
continue
str = str + line + "\n"
fo.close()
self.textEdit.setText(str)
self.show()
else:
# 輸出文本框內容
self.str = self.textEdit.toPlainText()
print(self.str)
# 將文本框內容寫入文件
self.fw = open('RD.txt', 'w')
self.fw.write(self.str)
self.fw.close() # 關閉文件
self.close() # 關閉窗口
def handle_close(self):
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(widget)
widget.show()
s = SecondWindow()
ui.pushButton_2.clicked.connect(s.handle_click)
sys.exit(app.exec_())
linux下開發,在Windows下運行可能需要將open函數的encoding設定為gbk
動物識別專家系統課程設計