栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

人工智能导论 贪婪最佳优先搜索与A*原理及python代码实现

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

人工智能导论 贪婪最佳优先搜索与A*原理及python代码实现

搜索算法的形式化描述:状态、动作、状态转移、路径、测试目标
状态:从原问题转化出的问题描述;
动作:从当前时刻所处状态转移到下一时刻所处状态所进行操作,一般而言这些操作都是离散的;
状态转移:对某一时刻对应状态进行某一种操作后,所能够到达状态;
路径:一个状态序列,该状态序列被一系列操作所连接;
测试目标:评估当前状态是否为所求解的目标状态;


问题:寻找从Arad到Bucharest的一条最短路径

辅助信息:任意一个城市与Bucharest的直线距离

代码实现

import sys
from collections import deque


class Romania:

    """The abstract class for a formal problem. You should subclass
    this and implement the methods actions and result, and possibly
    __init__, goal_test, and path_cost. Then you will create instances
    of your subclass and solve them with the various search functions."""

    neighbor_map = {'Arad': ['Zerind', 'Sibiu', 'Timisoara'], 'Bucharest': ['Urziceni', 'Pitesti', 'Giurgiu', 'Fagaras'],
                    'Craiova': ['Drobeta', 'Rimnicu', 'Pitesti'], 'Drobeta': ['Mehadia'], 'Eforie': ['Hirsova'],
                    'Fagaras': ['Sibiu'], 'Hirsova': ['Urziceni'],
                    'Iasi': ['Vaslui', 'Neamt'],'Lugoj': ['Timisoara', 'Mehadia'],
                    'Oradea': ['Zerind', 'Sibiu'], 'Pitesti': ['Rimnicu'],
                    'Rimnicu': ['Sibiu'], 'Urziceni': ['Vaslui']
                    }

    straight_line = {'Arad': 366, 'Bucharest': 0,'Craiova': 160,'Drobeta': 242, 'Eforie': 161,'Fagaras': 178, 'Giurgiu': 77, 'Hirsova': 151,'Iasi': 226, 'Lugoj': 244,
        'Mehadia': 241,'Neamt': 234,'Oradea': 380, 'Pitesti': 98,'Rimnicu': 193,'Sibiu': 253,'Timisoara': 329,'Urziceni': 80,
        'Vaslui': 199,'Zerind': 374,
    }

    neighbormapWithweight = {'Arad': {'Zerind': 75, 'Sibiu': 140, 'Timisoara': 118},
                             'Bucharest': {'Urziceni': 85, 'Pitesti': 101, 'Giurgiu': 90, 'Fagaras': 211},
                             'Craiova': {'Drobeta': 120, 'Rimnicu': 146, 'Pitesti': 138},
                             'Drobeta': {'Mehadia': 75,'Craiova':120},
                             'Eforie': {'Hirsova': 86},
                             'Fagaras': {'Sibiu': 99,'Bucharest':211},
                             'Hirsova': {'Urziceni': 98,'Eforie':86},
                             'Iasi': {'Vaslui': 92, 'Neamt': 87},
                             'Lugoj': {'Timisoara': 111, 'Mehadia': 70},
                             'Oradea': {'Zerind': 71, 'Sibiu': 151},
                             'Pitesti': {'Rimnicu': 97,'Craiova':138,'Bucharest':101},
                             'Rimnicu': {'Sibiu': 80,'Craiova':146,'Pitesti':97},
                             'Urziceni': {'Vaslui': 142,'Bucharest':85,'Hirsova':98},
                             'Zerind':{'Arad':75,'Oradea':71},
                             'Timisoara':{'Arad':118,'Logoj':111},
                             'Mehadia':{'Lugoj':70,'Drobeta':75},
                             'Sibiu':{'Oradea':151,'Arad':140,'Rimnicu':80,'Fagaras':99},
                             'Giurgiu':{'Bucharest':90},
                             'Neamt':{'Iasi':87},
                             'Vaslui':{'Iasi':92,'Urziceni':142}
                             }

    def __init__(self, initial, goal=None):
        """The constructor specifies the initial state, and possibly a goal
        state, if there is a unique goal. Your subclass's constructor can add
        other arguments."""
        self.initial = initial
        self.goal = goal

    # actions返回该城市能到达的所有城市,返回一个列表
    def actions(self, state):
        citys=[]
        # 根据字典的值查找键
        for item in self.neighbor_map:
            for city in self.neighbor_map.get(item):
                if city == state:
                    citys.append(item)
        if self.neighbor_map.get(state):
            return self.neighbor_map.get(state) + citys
        else:
            return citys

    # result返回该城市到终点的距离,即启发函数的值
    def result(self, action):
        return self.straight_line.get(action)

    def goal_test(self, state):
        return state == self.goal

    # path——cost返回从state1到达state2的路程
    def path_cost(self, state1, state2):
        return self.neighbormapWithweight.get(state1).get(state2)

    def value(self, state):
        """For optimization problems, each state has a value. Hill Climbing
        and related algorithms try to maximize this value."""
        raise NotImplementedError


# ______________________________________________________________________________


class Node:
    """A node in a search tree. Contains a pointer to the parent (the node
    that this is a successor of) and to the actual state for this node. Note
    that if a state is arrived at by two paths, then there are two nodes with
    the same state. Also includes the action that got us to this state, and
    the total path_cost (also known as g) to reach the node. Other functions
    may add an f and h value; see best_first_graph_search and astar_search for
    an explanation of how the f and h values are handled. You will not need to
    subclass this class."""

    def __init__(self, state, parent=None, action=None, path_cost=0):
        """Create a search tree Node, derived from a parent by an action."""
        self.state = state
        self.parent = parent
        self.action = action
        self.path_cost = path_cost
        self.depth = 0
        if parent:
            self.depth = parent.depth + 1

    def __repr__(self):
        return "".format(self.state)

    def __lt__(self, node):
        return self.state < node.state

    def expand(self, problem):
        """List the nodes reachable in one step from this node."""
        if problem.actions(self.state):
            return [self.child_node(action)
                for action in problem.actions(self.state)]

    def child_node(self, action):
        """[Figure 3.10]"""
        next_state = action
        next_node = Node(next_state, self, action,path_cost=self.path_cost+problem.path_cost(self.state,action))
        return next_node

    def solution(self):
        """Return the sequence of actions to go from the root to this node."""
        return [node.state for node in self.path()[0:]]

    def path(self):
        """Return a list of nodes forming the path from the root to this node."""
        node, path_back = self, []
        while node:
            path_back.append(node)
            node = node.parent
        return list(reversed(path_back))

    # We want for a queue of nodes in breadth_first_graph_search or
    # astar_search to have no duplicated states, so we treat nodes
    # with the same state as equal. [Problem: this may not be what you
    # want in other contexts.]

    def __eq__(self, other):
        return isinstance(other, Node) and self.state == other.state

    def __hash__(self):
        # We use the hash value of the state
        # stored in the node instead of the node
        # object itself to quickly search a node
        # with the same state in a Hash Table
        return hash(self.state)


problem=Romania('Arad','Bucharest')
start=Node('Arad')
frontier = []
explored = set()
frontier.append(start)
while 1:
    node = frontier.pop()
    if problem.goal_test(node.state):
        print('贪婪搜索最佳路线为:')
        print(node.solution())
        print('贪婪搜索最佳路线长度为:')
        print(node.path_cost)
        break
    else:
        explored.add(node.state)
        for node1 in node.expand(problem):
            if node1.state not in explored:
                frontier.append(node1)
        frontier.sort(key=lambda x: problem.result(x.state),reverse=True)

A*搜索将最后一句更换为
frontier.sort(key=lambda x: problem.result(x.state)+x.path_cost,reverse=True)

实现结果

A*最佳路线为:
['Arad', 'Sibiu', 'Rimnicu', 'Pitesti', 'Bucharest']
A*搜索最佳路线长度为:
418
贪婪搜索最佳路线为:
['Arad', 'Sibiu', 'Fagaras', 'Bucharest']
贪婪搜索最佳路线长度为:
450

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/269827.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号