NP完全性理论与近似算法

640?wx_fmt=gif


一、图灵机


根据有限状态控制器的当前状态及每个读写头读到的带符号,图灵机的一个计算步可实现下面3个操作之一或全部。


  1. 改变有限状态控制器中的状态。

  2. 清除当前读写头下的方格中原有带符号并写上新的带符号。

  3. 独立地将任何一个或所有读写头,向左移动一个方格(L)或向右移动一个方格(R)或停在当前单元不动(S)。


k带图灵机可形式化地描述为一个7元组(Q,T,I,δ,b,q0,qf),其中: 


  1. Q是有限个状态的集合。

  2. T是有限个带符号的集合。

  3. I是输入符号的集合640?wx_fmt=jpeg

  4. b是唯一的空白符,b∈T-I。

  5. q0是初始状态。      

  6. qf是终止(或接受)状态。

  7. δ是移动函数。


它是从Q×Tk的某一子集映射到Q×(T×{L,R,S})k的函数。


图灵机M的时间复杂性T(n)是它处理所有长度为n的输入所需的最大计算步数。如果对某个长度为n的输入,图灵机不停机,T(n)对这个n值无定义。


图灵机的空间复杂性S(n)是它处理所有长度为n的输入时,在k条带上所使用过的方格数的总和。如果某个读写头无限地向右移动而不停机,S(n)也无定义。


确定型图灵机


640?wx_fmt=jpeg


有限状态集Q,状态q0:初始状态;qy:接受状态;状态qn:不接受状态。


字符集合{0, 1, b} ;其中b是空格符。


转换功能:


640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


输入x = 101000b


执行顺序:


q0输入1 (q0,r)右移磁头到0

q0输入0 (q0,r)右移磁头到1

q0输入0 (q0,r)右移磁头到0

...

q0输入b (q1,l)左移磁头到0

q1输入0 (q2,b)

q2输入b (q2,l)左移磁头到0

q2输入0 (q3,b)

q3输入b (qy,l)退出


二、P类与NP类问题


一般地说,将可由多项式时间算法求解的问题看作是易处理的问题,而将需要超多项式时间才能求解的问题看作是难处理的问题。


有许多问题,从表面上看似乎并不比排序或图的搜索等问题更困难,然而至今人们还没有找到解决这些问题的多项式时间算法,也没有人能够证明这些问题需要超多项式时间下界。


在图灵机计算模型下,这类问题的计算复杂性至今未知。


为了研究这类问题的计算复杂性,人们提出了另一个能力更强的计算模型,即非确定性图灵机计算模型,简记为NDTM(Nondeterministic Turing Machine)。


在非确定性图灵机计算模型下,许多问题可以在多项式时间内求解。


非确定性图灵机


在图灵机计算模型中,移动函数δ是单值的,即对于Q´Tk中的每一个值,当它属于δ的定义域时,Q´(T´{L,R,S})k中只有唯一的值与之对应,称这种图灵机为确定性图灵机,简记为DTM(Deterministic Turing Machine)。


非确定性图灵机(NDTM):一个k带的非确定性图灵机M是一个7元组:(Q,T,I,δ,b,q0,qf)。与确定性图灵机不同的是非确定性图灵机允许移动函数δ具有不确定性,即对于Q×Tk中的每一个值(q;x1,x2,…,xk),当它属于δ的定义域时,Q×(T×{L,R,S})k中有唯一的一个子集δ(q;x1,x2,…,xk)与之对应。可以在δ(q;x1,x2,…,xk)中随意选定一个值作为它的函数值。


P类与NP类语言定义


P={L|L是一个能在多项式时间内被一台DTM所接受的语言}


NP={L|L是一个能在多项式时间内被一台NDTM所接受的语言}


由于一台确定性图灵机可看作是非确定性图灵机的特例,所以可在多项式时间内被确定性图灵机接受的语言也可在多项式时间内被非确定性图灵机接受。故P Í NP。 


NP类语言举例——无向图的团问题


该问题的输入是一个有n个顶点的无向图G=(V,E)和一个整数k。要求判定图G是否包含一个k顶点的完全子图(团),即判定是否存在V’640?wx_fmt=jpegV,|V’|=k,且对于所有的u,v∈V’,有(u,v)∈E。


若用邻接矩阵表示图G,用二进制串表示整数k,则团问题的一个实例可以用长度为640?wx_fmt=jpeg的二进位串表示。因此,团问题可表示为语言:


CLIQUE={w#v|w,v∈{0,1}*,以w为邻接矩阵的图G有一个k顶点的团,其中v是k的二进制表示。}


接受该语言CLIQUE的非确定性算法:用非确定性选择指令选出包含k个顶点的候选顶点子集V,然后确定性地检查该子集是否是团问题的一个解。算法分为3个阶段


算法的第一阶段将输入串w#v分解,并计算出n =640?wx_fmt=jpeg ,以及用v表示的整数k。若输入不具有形式w#v或|w|不是一个平方数就拒绝该输入。显而易见,第一阶段可在640?wx_fmt=jpeg时间内完成。


在算法的第二阶段中,非确定性地选择V的一个k元子集V’640?wx_fmt=jpegV。


算法的第三阶段是确定性地检查V’的团性质。若V’是一个团则接受输入,否则拒绝输入。这显然可以在640?wx_fmt=jpeg时间内完成。因此,整个算法的时间复杂性为640?wx_fmt=jpeg 。


非确定性算法在多项式时间内接受语言CLIQUE,故CLIQUE∈NP.


NP完全问题


P640?wx_fmt=jpegNP。


直观上看,P类问题是确定性计算模型下的易解问题类,而NP类问题是非确定性计算模型下的易验证问题类。


大多数的计算机科学家认为NP类中包含了不属于P类的语言,即P≠NP。


NP完全问题有一种令人惊奇的性质,即如果一个NP完全问题能在多项式时间内得到解决,那么NP中的每一个问题都可以在多项式时间内求解,即P = NP。


目前还没有一个NP完全问题有多项式时间算法。


三、NP完全问题的近似算法


迄今为止,所有的NP完全问题都还没有多项式时间算法。


对于这类问题,通常可采取以下几种解题策略。


  1. 只对问题的特殊实例求解

  2. 用动态规划法或分支限界法求解

  3. 用概率算法求解

  4. 只求近似解

  5. 用启发式方法求解


近似算法的性能


若一个最优化问题的最优值为c*,求解该问题的一个近似算法求得的近似最优解相应的目标函数值为c,则将该近似算法的性能比定义为640?wx_fmt=jpeg


在通常情况下,该性能比是问题输入规模n的一个函数ρ(n),即640?wx_fmt=jpeg


该近似算法的相对误差定义为:640?wx_fmt=jpeg。若对问题的输入规模n,有一函数ε(n)使得640?wx_fmt=jpeg则称ε(n)为该近似算法的相对误差界。近似算法的性能比ρ(n)与相对误差界ε(n)之间显然有如下关系:640?wx_fmt=jpeg


旅行售货员问题近似算法


问题描述:给定一个完全无向图G=(V,E),其每一边(u,v)∈E有一非负整数费用c(u,v)。要找出G的最小费用哈密顿回路。


旅行售货员问题的一些特殊性质:

 

比如,费用函数c往往具有三角不等式性质,即对任意的3个顶点u,v,w∈V,有:c(u,w)≤c(u,v)+c(v,w)。当图G中的顶点就是平面上的点,任意2顶点间的费用就是这2点间的欧氏距离时,费用函数c就具有三角不等式性质。


  • 1 满足三角不等式的旅行售货员问题


对于给定的无向图G,可以利用找图G的最小生成树的算法设计找近似最优的旅行售货员回路的算法。


void approxTSP (Graph g)

{

  1. 选择g的任一顶点r;

  2. 用Prim算法找出带权图g的一棵以r为根的最小生成树T;

  3. 前序遍历树T得到的顶点表L;

  4. 将r加到表L的末尾,按表L中顶点次序组成回路H,作为计 算结果返回;

}

   

当费用函数满足三角不等式时,算法找出的旅行售货员回路的费用不会超过最优旅行售货员回路费用的2倍

 

640?wx_fmt=jpeg

实现


/* 主题:近似算法——旅行售货员问题

作者:chinazhangjie

邮箱:chinajiezhang@gmail.com

开发语言: C++

开发环境: Virsual Studio 2005

时间2010.12.06

*/

 

#include <iostream>

#include <vector>

#include <limits>

using namespace std ;

 

struct TreeNode

{

public:

    TreeNode (int nVertexIndexA = 0, int nVertexIndexB = 0, int nWeight = 0)

        : m_nVertexIndexA (nVertexIndexA),

        m_nVertexIndexB (nVertexIndexB),

        m_nWeight (nWeight)

    { }

public:

    int m_nVertexIndexA ;

    int m_nVertexIndexB ;

    int m_nWeight ;

} ;

 

class MST_Prim

{

public:

    MST_Prim ()

    {}

    MST_Prim (const vector<vector<int> >& vnGraph)

    {

        m_nvGraph = vnGraph ;

        m_nNodeCount = (int)m_nvGraph.size () ;

    }

    void SetData (const vector<vector<int> >& vnGraph)

    {

        m_nvGraph = vnGraph ;

        m_nNodeCount = (int)m_nvGraph.size () ;

    }

    //

    const vector<TreeNode>& GetMSTree () const

    {

        return m_tnMSTree ;

    }

    //

    const vector<vector<int> >& GetGraph () const

    {

        return    m_nvGraph ;

    }

    void DoPrim ()

    {

        // 是否被访问标志

        vector<boolbFlag (m_nNodeCount, false) ;

        bFlag[0] = true ;

 

        int nMaxIndexA ;

        int nMaxIndexB ;

        int j = 0 ;

        while (j < m_nNodeCount - 1) {

            int nMaxWeight = numeric_limits<int>::max () ;

            // 找到当前最短路径

            int i = 0 ;

            while (i < m_nNodeCount) {

                if (!bFlag[i]) {

                    ++ i ;

                    continue ;

                }

                for (int j = 0; j < m_nNodeCount; ++ j) {

                    if (!bFlag[j] && nMaxWeight > m_nvGraph[i][j]) {

                        nMaxWeight = m_nvGraph[i][j] ;

                        nMaxIndexA = i ;

                        nMaxIndexB = j ;

                    }

                }

                ++ i ;

            }

            bFlag[nMaxIndexB] = true ;

            m_tnMSTree.push_back (TreeNode(nMaxIndexA, nMaxIndexB, nMaxWeight)) ;

            ++ j ;

        }

        // 输出结果

        /*for (vector<TreeNode>::const_iterator ite = m_tnMSTree.begin() ;

                ite != m_tnMSTree.end() ;

                ++ ite ) {

            cout << (*ite).m_nVertexIndexA << "->"

                << (*ite).m_nVertexIndexB << " : "

                << (*ite).m_nWeight << endl ;

        }*/

    }

 

private:

    vector<vector<int> > m_nvGraph ;    // 无向连通图

    vector<TreeNode>    m_tnMSTree ;    // 最小生成树

    int    m_nNodeCount ;

} ;

 

 

class AA_TSP

{

public:

    AA_TSP (const vector<vector<int> >& vnGraph)

    {

        m_mstPrim.SetData(vnGraph) ;

    }

    void Get_AA_Path ()

    {

        m_mstPrim.DoPrim () ;

        vector<TreeNode>        mstree = m_mstPrim.GetMSTree () ;

        vector<vector<int> >    graph = m_mstPrim.GetGraph() ;

        int iweight = 0 ;

        for (vector<TreeNode>::const_iterator ite = mstree.begin() ;

                ite != mstree.end() ;

                ++ ite ) {

            cout << (*ite).m_nVertexIndexA << "->"

                << (*ite).m_nVertexIndexB << " : "

                << (*ite).m_nWeight << endl ;

            iweight += (*ite).m_nWeight ;

        }    

        cout << mstree[mstree.size()-1].m_nVertexIndexB << "->"

            << mstree[0].m_nVertexIndexA << " : "

            << graph[mstree[0].m_nVertexIndexA][mstree[mstree.size()-1].m_nVertexIndexB]

            << endl ;

        iweight += graph[mstree[0].m_nVertexIndexA][mstree[mstree.size()-1].m_nVertexIndexB] ;

        cout << "Total weight: " << iweight  << endl ;

    }

private:

    MST_Prim    m_mstPrim ;

};

int main()

{

    const int cnNodeCount = 5 ;

    vector<vector<int> > graph (cnNodeCount) ;

    for (size_t i = 0; i < graph.size() ; ++ i) {

        graph[i].resize (cnNodeCount, numeric_limits<int>::max()) ;

    }

    graph[0][1] = 5 ;

    graph[0][2] = 1 ;

    graph[0][3] = 2 ;

    graph[0][4] = 3 ;

 

    graph[1][0] = 5 ;

    graph[1][2] = 4 ;

    graph[1][3] = 2 ;

    graph[1][4] = 2 ;

 

    graph[2][1] = 4 ;

    graph[2][0] = 1 ;

    graph[2][3] = 5 ;

    graph[2][4] = 3 ;

 

    graph[3][1] = 2 ;

    graph[3][2] = 5 ;

    graph[3][0] = 2 ;

    graph[3][4] = 2 ;

 

    graph[4][1] = 2 ;

    graph[4][2] = 3 ;

    graph[4][3] = 2 ;

    graph[4][0] = 3 ;

 

    AA_TSP aa (graph) ;

    aa.Get_AA_Path () ;

     return 0 ;

}


  • 2 一般的旅行售货员问题

在费用函数不一定满足三角不等式的一般情况下,不存在具有常数性能比的解TSP问题的多项式时间近似算法,除非P=NP。换句话说,若P≠NP,则对任意常数ρ>1,不存在性能比为ρ的解旅行售货员问题的多项式时间近似算法。


来源:独酌逸醉

www.cnblogs.com/chinazhangjie/archive/2010/12/06/1898070.html


640?wx_fmt=png


640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里25k 百度25k,招WPF!

.NET5打通7大开发方向&#xff0c;CLR超高性能&#xff0c;.NET6支持Blazor嵌入WPF&#xff0c;还有MAUI跨平台UI解决方案&#xff0c;都是.NET的利好&#xff0c;也是WPF的利好。牛年跳槽季&#xff0c;.NET在客户端方向一骑绝尘&#xff0c;阿里影视、百度地图&#xff0c;以…

掌握神经网络模型的快捷方式

TensorFlow是Google基于DistBelief进行研发的第二代人工智能学习系统&#xff0c;其命名来源于本身的运行原理。Tensor&#xff08;张量&#xff09;意味着N维数组&#xff0c;Flow&#xff08;流&#xff09;意味着基于数据流图的计算&#xff0c;TensorFlow实际上就是张量从流…

.Net项目模板(Project Template)

你有没有这样的感觉&#xff0c;开启一个新项目时&#xff0c;总是做一堆体力活——项目的结构层次&#xff0c;常用日志库&#xff0c;OpenAPI库&#xff0c;ORM库&#xff0c;的引入&#xff0c;权限认证方式选择添加&#xff0c;配置文件重新归置存放等等。公共框架的部分总…

谈通过测试与失败测试

在软件测试技术中&#xff0c;现有的测试方法、测试技术中均未提及到通过测试与失败测试。 而在实际项目测试过程中&#xff0c;很多项目组却再应用该方法。虽然该方法被采用&#xff0c;但是很多人对通过测试与失败测试理解并不透侧&#xff0c;在实际使用过程中并未按统一的标…

100个微信小程序的源码公开分享

现在微信小程序越来越火&#xff0c;小编一直有意识地收集微信小程序源码&#xff0c;至今已经拥有100个小程序的源码&#xff0c;有gank、LOL战绩查询、百度小说、豆瓣电影、手势解锁等。现在&#xff0c;小编准备将这些资料免费分享给大家&#xff01;gankLOL战绩查询百度小说…

家里在一二线城市有很多套房是什么体验?答案太颠覆!

作者&#xff1a;匿名来源&#xff1a;知乎&#xff08;图片&#xff1a;网络&#xff09;“家里在一二线城市有很多套房是怎么的一种体验&#xff1f;”这是知乎上一个浏览超600万的话题。其中一个答案非常颠覆&#xff0c;获得高赞。作者的观点是否正确见仁见智&#xff0c;但…

希尔排序听起来有点难,其实很简单

前言直接插入排序当待排序数据的顺序和期望排序结果相反时&#xff0c;排序效率是最差的&#xff1b;上次聊到的折半插入排序只是减少有序列表的比较次数&#xff0c;而对于整体数据遍历次数还是没有得到优化&#xff1b;接下来要说的希尔排序就是针对整体数据进行优化&#xf…

等我敲完这行代码,就和你离婚!

工作是高端大气上档次&#xff0c;工资是低调奢华接地气&#xff01;我们叫做“程序猿”&#xff0c;也叫“攻城狮”&#xff01;但是往往城还没攻下来&#xff0c;我们的头发就先掉下来&#xff01;我们最喜欢听的一句话就是☟段子一“等我敲完这行代码&#xff0c;就和你离婚…

深夜,学妹遇到了数据分析师生涯的第一个疑问

大家好&#xff0c;我是大鹏&#xff0c;目前是一名数据分析师。自从上次学妹深夜给我发微信&#xff0c;询问数据分析师招聘要求和需要掌握的技能&#xff0c;已经过去2个月了。直到昨天&#xff0c;我再次收到了学妹的召唤&#xff1a;当天深夜 学妹深夜求助&#xff0c;定是…

你知道WPF与WinForms的区别吗?

介绍WPF的缩写指微软的Windows Presentation Foundation&#xff0c;而WinForms是Windows Forms Applications的简单组合。这两个都是微软的Windows应用程序图形用户界面&#xff0c;开发人员可以使用它们来开发Windows桌面应用程序。本文重点介绍两种开发Windows桌面应用程序的…

一起谈.NET技术,发布NGuestBook(一个基于.NET平台的分层架构留言本小系统)

发布NGuestBook的动机说明 大约在半年前&#xff0c;我在博客上发表了一个系列文章&#xff1a;《基于.NET平台的分层架构实战》。当时在讲解过程中用到了一个叫NGuestBook的案例&#xff0c;在那以后&#xff0c;有很多朋友留言或发E-mail希望能得到NGuestBook的完整源代…

当Java、C++、Python等编程语言都变成妹子。。。

试想一下&#xff0c;当Java、C、Python、Ruby、PHP、C#、JS等编程语言变成了动漫人物会是怎样的一幅场景呢&#xff1f;下面就一起看看在日本作家渡辺将人的笔下&#xff0c;各种编程语言都是哪类“美女”的吧&#xff01;Java犹如宫泽贤治的《不畏风雨》中出现的、性格木讷的…

对MySQL 进行深入学习是非常必要的

MySQL 在互联网行业非常流行&#xff0c;腾讯&#xff0c;阿里等互联网巨头都在深入使用MySQL&#xff0c; 我在腾讯时也使用MySQL&#xff0c;我在微信群里经常听到大家对MySQL 的意见也很大。在传统企业环境下使用最多的数据库产品是Oracle,SQL Server等企业级数据库&#xf…

4月 .NET 线上 Meetup,快来报名

点击蓝字关注我们.NET 6 preview 2 在3月11日已经发布&#xff0c;.NET 6 将是 .NET Core 3.1 之后的第一个 LTS 版本&#xff0c;也是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义不可谓不大&#xff0c;那么 .NET 5/6 又会带来哪些新特性呢&#…

机器学习资料第3版,助你继续成长!

之前分享的两份机器学习资料得到很多人的支持&#xff0c;因此小编决定再分享一份机器学习的资料。前两份资料传送门&#xff1a;【资源】机器学习资料包来袭机器学习资料升级版来了&#xff01;&#xff01;&#xff01;现在&#xff0c;再来看看有什么新资料吧。How to Build…

人工智能、机器学习、深度学习,到底他们哥仨是什么关系?

有三个词&#xff0c;这两年出现的频率越来越高&#xff1a;人工智能&#xff08;AI&#xff09;&#xff0c;机器学习&#xff08;ML&#xff09;&#xff0c;深度学习&#xff08;DL&#xff09;&#xff0c;到底他们哥仨是什么关系&#xff1f;今天小编化繁为简&#xff0c;…

如何在 ASP.NET Core 中使用 HttpClientFactory ?

ASP.Net Core 是一个开源的&#xff0c;跨平台的&#xff0c;轻量级模块化框架&#xff0c;可用它来构建高性能的Web程序&#xff0c;这篇文章我们将会讨论如何在 ASP.Net Core 中使用 HttpClientFactory。为什么要使用 HttpClientFactory 可以用 HttpClientFactory 来集中化管…

如何选择合适的损失函数,请看......

机器学习中的所有算法都依赖于最小化或最大化某一个函数&#xff0c;我们称之为“目标函数”。最小化的这组函数被称为“损失函数”。损失函数是衡量预测模型预测期望结果表现的指标。寻找函数最小值的最常用方法是“梯度下降”。把损失函数想象成起伏的山脉&#xff0c;梯度下…

OxyPlot.SkiaSharp中文显示乱码的问题

oxyplot 图表控件功能强大&#xff0c;使用很广泛。最近考虑到性能使用OxyPlot.SkiaSharp替代OxyPlot.WPF&#xff0c;曲线图表初步测试&#xff0c;性能提升近10倍左右。基于SkiaSharp图形引擎的一些控件常遇见中文乱码的问题&#xff0c;所以改用OxyPlot.SkiaSharp时也有心里…

想入门平均月薪2.58w人工智能领域?看看BAT的工程师在学什么

在这个贩卖焦虑的时代&#xff0c;职场人士和新晋父母成为了重点呵护对象&#xff0c;前有“摩拜同龄人”超越你&#xff0c;后有“月薪 3 万支撑不起的暑假班”等着你&#xff0c;而人工智能&#xff0c;又威胁要彻底抢走你的饭碗。京东无人分拣中心曝光&#xff0c;华尔街顶级…