def dfs_bfs(): solver = Solver(3) result = [[], []] # Keeps the execution time + path length bfs_target = rubiks_cube() for i in range(4): print '# i = ', i t = [] l = [] for j in range(100): print'### j = ', j start = time.clock() v = solver.dfs(math.pow(2, i)) u = solver.bfs(v, bfs_target) p = solver.calculate_shortest_path(u) # Path from v to cube's initial state total_time = time.clock() - start if total_time < 180: print "### time %d length %d" % (total_time, len(p)) t.append(total_time) l.append(len(p)) result_full.append(len(p)) result[0].append(np.median(t)) result[1].append(np.median(l)) return result
def dfs_bfs(): solver = Solver(3) result = [[], []] # Keeps the execution time + path length bfs_target = rubiks_cube() for i in range(7): print '# i = ', i t = [] l = [] for j in range(100): print '### j = ', j start = time.clock() v = solver.dfs(i) u = solver.bfs(v, bfs_target) p = solver.calculate_shortest_path( u) # Path from v to cube's initial state total_time = time.clock() - start if total_time < 180: print "### time %d length %d" % (total_time, len(p)) t.append(total_time) l.append(len(p)) result_full.append(len(p)) result[0].append(np.median(t)) result[1].append(np.median(l)) return result
class Example(QWidget): def __init__(self): super().__init__() self.start = '2164 8753' self.cnt = 8 # 当前九宫格已经填入的数字的个数 self.solver = Solver(self.start, max_depth=20) self.updater = UpdateObj(self) self.myThread = QThread() self.updater.moveToThread(self.myThread) self.initUI() self.bindSlots() ''' 布置所有组件 ''' def initUI(self): with open('./res/style.qss', encoding='utf8', mode='r') as f: self.qss = f.read() self.setStyleSheet(self.qss) # 应用qss样式表 self.setWindowTitle('八数码实验') self.setWindowIcon(QIcon('./res/8puzzle.png')) # 设置应用图标 self.title = QLabel('八数码问题的实验程序', self) self.title.setObjectName('title') self.title.move(78, 52) self.setGeometry(300, 300, 800, 600) self.setFixedSize(800, 600) QLabel('最大搜索深度', self).setGeometry(260, 455, 95, 20) self.max_depth = QLineEdit(self) self.max_depth.setGeometry(QRect(350, 452, 50, 22)) self.max_depth.setText(str(self.solver.max_depth)) # 左侧按钮集 self.lbtns = [ QPushButton('深度优先搜索', self), QPushButton('宽度优先搜索', self), QPushButton('启发式搜索1', self), QPushButton('启发式搜索2', self), QPushButton('启发式搜索3', self), QPushButton('全部运行(F5)', self) ] # 右侧按钮集 self.rbtns = [ QPushButton('随机生成', self), QPushButton('手动输入', self), QPushButton('清空', self), QPushButton('退出', self), QPushButton('解法演示', self), QPushButton('别点', self) ] # 初始状态禁用 self.rbtns[4].setEnabled(False) self.lbtns[5].setShortcut(QKeySequence("F5")) # 分别将两侧按钮集添加到两个垂直布局中 self.ver_layout1 = QVBoxLayout() self.ver_layout2 = QVBoxLayout() for btn in self.lbtns: self.ver_layout1.addWidget(btn) for btn in self.rbtns: self.ver_layout2.addWidget(btn) # 调整按钮栏的位置 self.ver_layout1.setGeometry(QRect(87, 135, 140, 320)) self.ver_layout2.setGeometry(QRect(572, 135, 140, 320)) # 八数码的牌子设置为初始状态 self.nums = [MyLabel(self) for _ in range(9)] for i, ch in enumerate(self.start): self.nums[i].setText(ch) self.nums[i].setEnabled(False) # 八数码棋盘 self.puzzles = QFrame(self) self.puzzles.setObjectName('puzzles') self.puzzles.setGeometry(QRect(310, 135, 210, 210)) # 设置八数码的九宫格显示 grid = QGridLayout(self.puzzles) positions = [(i, j) for i in range(3) for j in range(3)] for label, position in zip(self.nums, positions): grid.addWidget(label, *position) # 构建结果表格 self.result = QTableWidget(2, 6, self) self.result.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) # 设置自适应列宽 self.result.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) self.result.setHorizontalHeaderLabels( ['方法', '深度优先', '宽度优先', 'h1(n)', 'h2(n)', 'h3(n)']) for i in range(2): for j in range(6): self.result.setItem(i, j, QTableWidgetItem()) # 添加item self.result.item(i, j).setTextAlignment( Qt.AlignCenter | Qt.AlignVCenter) # 设置文本居中 self.result.item(0, 0).setText('扩展节点数') self.result.item(1, 0).setText('生成节点数') self.result.setGeometry(QRect(87, 478, 630, 100)) # 调整表格位置 # 设置logo self.logo = QLabel(self) self.logo.setGeometry(QRect(600, 10, 90, 100)) jpg = QPixmap('./res/scnulogo.png').scaled(self.logo.width(), self.logo.height()) self.logo.setPixmap(jpg) # 增添提示 self.descrip = QLabel(self) self.descrip.setGeometry(QRect(260, 360, 300, 100)) self.descrip.setText( '''最大搜索深度过大可能会导致搜索时间过长\n(特别是BFS),导致程序无响应,需要强制关闭\nh1(n) =W(n) “不在位”的将牌数\nh2(n) = P(n)将牌“不在位”的距离和\nh3(n) = h(n)=P(n)+3S(n)''' ) self.show() ''' 给必要的控件绑定槽函数 ''' def bindSlots(self): self.lbtns[0].clicked.connect(self.run_dfs) self.lbtns[1].clicked.connect(self.run_bfs) self.lbtns[2].clicked.connect(self.run_h1) self.lbtns[3].clicked.connect(self.run_h2) self.lbtns[4].clicked.connect(self.run_h3) self.lbtns[5].clicked.connect(self.run_all) self.rbtns[0].clicked.connect(self.random_state) self.rbtns[1].clicked.connect(self.manual_input) self.rbtns[2].clicked.connect(self.clear) self.rbtns[3].clicked.connect(self.close) self.rbtns[4].clicked.connect(self.updater.show_ans) self.rbtns[5].clicked.connect(self.useless) self.max_depth.textChanged[str].connect(self.change_max_depth) self.myThread.start() for w in self.nums: w.clicked.connect(w.input_num) ''' 用来皮一下的函数 ''' def useless(self): for _ in range(20): QMessageBox.about(self, '叫你别点', '欢迎大家学习人工智能导论') ''' 根据val更改最大搜索深度 ''' def change_max_depth(self, val): if re.search('^\\d+$', val): self.solver.max_depth = int(val) ''' 运行深度优先搜索算法,调用了Solver类的dfs方法,更新结果表格 ''' def run_dfs(self): res, gen, expand = self.solver.dfs() self.rbtns[4].setEnabled(True if res else False) # 是否允许进行解法演示 print(res, gen, expand) self.result.item(0, 1).setText(str(expand)) self.result.item(1, 1).setText(str(gen)) ''' 运行宽度优先搜索算法,调用了Solver类的bfs算法,更新结果表格 ''' def run_bfs(self): res, gen, expand = self.solver.bfs() self.rbtns[4].setEnabled(True if res else False) # 是否允许进行解法演示 print(res, gen, expand) self.result.item(0, 2).setText(str(expand)) self.result.item(1, 2).setText(str(gen)) ''' 运行h1启发式搜索算法,调用了Solver类的hs1方法,更新结果表格 ''' def run_h1(self): res, gen, expand = self.solver.hs1() self.rbtns[4].setEnabled(True if res else False) # 是否允许进行解法演示 print(res, gen, expand) self.result.item(0, 3).setText(str(expand)) self.result.item(1, 3).setText(str(gen)) ''' 运行h2启发式搜索算法,调用了Solver类的hs2方法,更新结果表格 ''' def run_h2(self): res, gen, expand = self.solver.hs2() self.rbtns[4].setEnabled(True if res else False) # 是否允许进行解法演示 print(res, gen, expand) self.result.item(0, 4).setText(str(expand)) self.result.item(1, 4).setText(str(gen)) ''' 运行h3启发式搜索算法,调用了Solver类的hs1方法,更新结果表格 ''' def run_h3(self): res, gen, expand = self.solver.hs3() self.rbtns[4].setEnabled(True if res else False) # 是否允许进行解法演示 print(res, gen, expand) self.result.item(0, 5).setText(str(expand)) self.result.item(1, 5).setText(str(gen)) ''' 运行所有搜索算法,更新结果表格 ''' def run_all(self): self.run_dfs() self.run_bfs() self.run_h1() self.run_h2() self.run_h3() ''' 清空结果表 ''' def clear(self): for i in range(2): for j in range(1, 6): self.result.item(i, j).setText('') ''' 手动输入初始状态 ''' def manual_input(self): self.clear() # 清空表格 # 清空九宫格的数字,并设置为可点击,即允许输入 for w in self.nums: w.setText('') w.setEnabled(True) # 未输入完成前不允许执行搜索和解法演示 for b in self.lbtns: b.setEnabled(False) self.rbtns[4].setEnabled(False) # 计数器清零 self.cnt = 0 ''' 生成随机状态 ''' def random_state(self): self.start = ''.join([str(i) for i in random.sample(range(0, 9), 9) ]).replace('0', ' ') self.solver.start = self.start # 更新ui for i, w in enumerate(self.nums): w.setText(self.start[i]) self.rbtns[4].setEnabled(False)