Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 优化8字谜_Python_Python 3.x_Optimization - Fatal编程技术网

Python 优化8字谜

Python 优化8字谜,python,python-3.x,optimization,Python,Python 3.x,Optimization,我是一名初级程序员,我试图用广度优先搜索来解决8字谜问题,但解决这个问题花了太长时间,我想优化我的代码。 配置:[[5,4,3],[0,7,2],[6,1,8]将在22.623718615秒内解决, 配置[[8,0,6],[5,4,7],[2,3,1]占用了235.721346421秒。 我想减少求解时间。 这是我的代码: from copy import deepcopy from collections import deque from time import perf_counter

我是一名初级程序员,我试图用广度优先搜索来解决8字谜问题,但解决这个问题花了太长时间,我想优化我的代码。 配置:
[[5,4,3],[0,7,2],[6,1,8]
将在
22.623718615
秒内解决, 配置
[[8,0,6],[5,4,7],[2,3,1]
占用了
235.721346421
秒。 我想减少求解时间。 这是我的代码:

from copy import deepcopy
from collections import deque
from time import perf_counter

most_hard = [[8, 0, 6], [5, 4, 7], [2, 3, 1]]  # 30 moves


class CheckPuzzle:
    def __init__(self, puzzle: list):
        self.puzzle = puzzle
        self.len = len(puzzle)
        if self.len == 3:
            self.goal = [[1, 2, 3],
                         [4, 5, 6],
                         [7, 8, 0]]
        elif self.len == 4:
            self.goal = [[1, 2, 3, 4],
                         [5, 6, 7, 8],
                         [9, 10, 11, 12],
                         [13, 14, 15, 0]]
        if not self.is_valid():
            raise TypeError("Puzzle is not valid")
        elif not self.is_solvable():
            raise Exception("Unsolvable puzzle")

    #  создай ф-ию check

    def sum_of_numbers(self) -> int:
        return sum(self.convert_to_1d(self.goal))

    def sum_of_squares(self) -> int:
        return sum([i ** 2 for i in self.convert_to_1d(self.goal)])

    def is_valid(self) -> bool:
        sum_of_numbers = 0
        sum_of_squares = 0
        for row in range(self.len):
            for column in range(self.len):
                sum_of_numbers += self.puzzle[row][column]
                sum_of_squares += (self.puzzle[row][column]) ** 2
        return sum_of_numbers == self.sum_of_numbers() and sum_of_squares == self.sum_of_squares()

    def convert_to_1d(self, board) -> list:
        one_dimension_matrix = []
        for row in range(self.len):
            for column in range(self.len):
                one_dimension_matrix.append(board[row][column])
        return one_dimension_matrix

    def inversion(self, board) -> int:
        inversion = 0
        one_dimension_matrix = self.convert_to_1d(board)
        for index in range(len(one_dimension_matrix)):
            temp = one_dimension_matrix[index]
            if temp == 0 or temp == 1:
                continue
            for elem in one_dimension_matrix[index:]:
                if elem == 0:
                    continue
                if temp > elem:
                    inversion += 1
        return inversion

    def is_solvable(self) -> bool:
        inv_of_matrix = self.inversion(self.puzzle)
        inv_of_goal_matrix = self.inversion(self.goal)
        return (inv_of_matrix % 2 == 0 and inv_of_goal_matrix % 2 == 0) or \
               (inv_of_matrix % 2 == 1 and inv_of_goal_matrix % 2 == 1)


class Puzzle:
    def __init__(self, board: list):
        self.board = board
        self.len = len(board)
        if self.len == 3:
            self.goal = [[1, 2, 3],
                         [4, 5, 6],
                         [7, 8, 0]]
        elif self.len == 4:
            self.goal = [[1, 2, 3, 4],
                         [5, 6, 7, 8],
                         [9, 10, 11, 12],
                         [13, 14, 15, 0]]

    def print_matrix(self) -> str:
        output = ''
        for row in self.board:
            for elem in row:
                output += str(elem) + " "
            output += '\n'
        return output

    def get_index(self, matrix, value) -> tuple:
        for i in range(self.len):
            for j in range(self.len):
                if matrix[i][j] == value:
                    return i, j

    def manhattan(self):
        distance = 0
        for i in range(self.len):
            for j in range(self.len):
                if self.board[i][j] != 0:
                    x, y = divmod(self.board[i][j] - 1, self.len)
                    distance += abs(x - i) + abs(y - j)
        return distance

    def list_of_possible_moves(self) -> list:
        x, y = self.get_index(self.board, 0)
        possible_moves = []
        if x > 0:
            possible_moves.append((x - 1, y))
        if x < self.len - 1:
            possible_moves.append((x + 1, y))
        if y > 0:
            possible_moves.append((x, y - 1))
        if y < self.len - 1:
            possible_moves.append((x, y + 1))
        return possible_moves

    def move(self, to: tuple) -> list:
        moving_board = deepcopy(self.board)
        x, y = self.get_index(self.board, 0)
        i, j = to
        moving_board[x][y], moving_board[i][j] = moving_board[i][j], moving_board[x][y]
        return moving_board

    def solved(self) -> bool:
        return self.board == self.goal

    def __str__(self) -> str:
        return ''.join(map(str, self))

    def __iter__(self):
        for row in self.board:
            yield from row


class Node:
    def __init__(self, puzzle, parent=None):
        self.puzzle = puzzle
        self.parent = parent
        if self.parent:
            self.g = parent.g + 1
        else:
            self.g = 0

    def state(self) -> str:
        return str(self)

    def path(self):
        node, p = self, []
        while node:
            p.append(node)
            node = node.parent
        yield from reversed(p)

    def solved(self) -> bool:
        return self.puzzle.solved()

    def pretty_print(self) -> str:
        return self.puzzle.print_matrix()

    def h(self) -> int:
        return self.puzzle.manhattan()

    def f(self) -> int:
        return self.h() + self.g

    def all_moves(self) -> list:
        return self.puzzle.list_of_possible_moves()

    def __str__(self) -> str:
        return str(self.puzzle)

    def make_a_move(self, to: tuple) -> list:
        return self.puzzle.move(to)


class GameTree:
    def __init__(self, root):
        self.root = root

    def solve(self):
        queue = deque([Node(self.root)])
        seen = set()
        seen.add(queue[0].state())
        while queue:
            queue = deque(sorted(list(queue), key=lambda node: node.f()))
            node = queue.popleft()
            if node.solved():
                return node.path()

            for move in node.all_moves():
                moved = node.make_a_move(move)
                child = Node(Puzzle(moved), node)

                if child.state() not in seen:
                    queue.append(child)
                    seen.add(child.state())


def main():
    a = [[5, 4, 3], [0, 7, 2], [6, 1, 8]]
    c = Puzzle(a)
    d = GameTree(c)
    tic = perf_counter()
    p = d.solve()
    toc = perf_counter()
    step = 0
for i in p:
    print(i.pretty_print())
    step += 1
print(step)
print(toc-tic)


if __name__ == "__main__":
    main()
从复制导入deepcopy
从集合导入deque
从时间导入性能计数器
大部分难度=[8,0,6],[5,4,7],[2,3,1]#30步
类支票拼图:
定义初始化(自我,谜题:列表):
self.puzzle=puzzle
self.len=len(拼图)
如果self.len==3:
self.goal=[[1,2,3],
[4, 5, 6],
[7, 8, 0]]
elif self.len==4:
self.goal=[[1,2,3,4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
如果不是self.u有效():
raise TypeError(“拼图无效”)
elif not self.is_solvable():
引发异常(“无法解决的难题”)
#检查
定义数字之和(自)->int:
返回和(自我转换为自我目标)
定义平方和(自)->int:
返回和([i**2表示自我中的i.convert\u为自我1d(self.goal)])
def有效(自)->bool:
_个数之和=0
平方和=0
对于范围内的行(self.len):
对于范围内的列(self.len):
数字之和+=自我拼图[行][列]
平方和+=(自拼图[行][列]**2
返回self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self
def convert_to_1d(自身、电路板)->列表:
一维矩阵=[]
对于范围内的行(self.len):
对于范围内的列(self.len):
一维矩阵。追加(板[行][列])
返回一维矩阵
def反转(自、板)->int:
反转=0
一维矩阵=自。将一维转换为一维(板)
对于范围内的索引(len(一维矩阵)):
temp=一维矩阵[索引]
如果温度=0或温度=1:
持续
对于一维矩阵中的元素[索引:]:
如果elem==0:
持续
如果温度>元素:
反转+=1
返回反转
def可解(自)->bool:
_矩阵的inv_=self.inversion(self.puzzle)
目标矩阵的inv\u=self.inversion(self.goal)
返回(矩阵%2的库存=0,目标矩阵%2的库存=0)或\
(矩阵%2的库存=1,目标矩阵%2的库存=1)
班级难题:
定义初始化(自我,电路板:列表):
self.board=board
self.len=len(板)
如果self.len==3:
self.goal=[[1,2,3],
[4, 5, 6],
[7, 8, 0]]
elif self.len==4:
self.goal=[[1,2,3,4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
def打印矩阵(自身)->str:
输出=“”
对于self.board中的行:
对于行中的元素:
输出+=str(元素)+“
输出+='\n'
返回输出
def get_索引(自身、矩阵、值)->元组:
对于范围内的i(self.len):
对于范围内的j(自透镜):
如果矩阵[i][j]==值:
返回i,j
def曼哈顿(自我):
距离=0
对于范围内的i(self.len):
对于范围内的j(自透镜):
if self.board[i][j]!=0:
x、 y=divmod(自板[i][j]-1,自透镜)
距离+=abs(x-i)+abs(y-j)
返回距离
def list_of_可能的_移动(自)->列表:
x、 y=self.get_索引(self.board,0)
可能的_移动=[]
如果x>0:
可能的_移动。追加((x-1,y))
如果x0:
可能的_移动。追加((x,y-1))
如果y列表:
移动电路板=深度复制(self.board)
x、 y=self.get_索引(self.board,0)
i、 j=至
移动电路板[x][y],移动电路板[i][j]=移动电路板[i][j],移动电路板[x][y]
回程板
def已解决(自)->bool:
返回self.board==self.goal
定义(自我)->str:
返回“”。加入(映射(str,self))
定义(自我):
对于self.board中的行:
行产量
类节点:
def uuu init uuu(self,puzzle,parent=None):
self.puzzle=puzzle
self.parent=parent
如果self.parent:
self.g=parent.g+1
其他:
self.g=0
def状态(自身)->str:
返回str(self)
def路径(自身):
节点,p=self,[]
while节点:
p、 附加(节点)
node=node.parent
反向收益率(p)
def已解决(自)->bool:
return self.puzzle.solved()
def pretty_打印(自)->str:
return self.puzzle.print_matrix()
def h(自)->int:
return self.puzzle.manhattan()
def f(自)->int:
返回self.h()+self.g
定义所有移动(自)->列表:
return self.puzzle.list\u可能的移动()
定义(自我)->str:
返回str(self.puzzle)
def make_a_move(self,to:tuple)->列表:
返回自我。拼图。移动(到)
类游戏树:
定义初始化(自,根):
self.root=根
def解算(自):
queue=deque([Node(self.root)])
seen=set()
西元