1. 程式人生 > >動物識別專家系統課程設計

動物識別專家系統課程設計

包含 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

動物識別專家系統課程設計