NP完全性理论与近似算法
转自:http://www.cnblogs.com/chinazhangjie/archive/2010/12/06/1898070.html
一、图灵机
根据有限状态控制器的当前状态及每个读写头读到的带符号,图灵机的一个计算步可实现下面3个操作之一或全部。
(1)改变有限状态控制器中的状态。
(2)清除当前读写头下的方格中原有带符号并写上新的带符号。
(3)独立地将任何一个或所有读写头,向左移动一个方格(L)或向右移动一个方格(R)或停在当前单元不动(S)。
k带图灵机可形式化地描述为一个7元组(Q,T,I,δ,b,q0,qf),其中:
(1) Q是有限个状态的集合。
(2)T是有限个带符号的集合。
(3)I是输入符号的集合。
(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)也无定义。
确定型图灵机
有限状态集Q,状态q0:初始状态;qy:接受状态;状态qn:不接受状态。
字符集合{0, 1, b} ;其中b是空格符。
转换功能:
输入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)。
在非确定性图灵机计算模型下,许多问题可以在多项式时间内求解。
非确定性图灵机
在图灵机计算模型中,移动函数δ是单值的,即对于QxTk中的每一个值,当它属于δ的定义域时,Qx(Tx{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’V,|V’|=k,且对于所有的u,v∈V’,有(u,v)∈E。
若用邻接矩阵表示图G,用二进制串表示整数k,则团问题的一个实例可以用长度为n2+logk+1的二进位串表示。因此,团问题可表示为语言:
CLIQUE={w#v|w,v∈{0,1}*,以w为邻接矩阵的图G有一个k顶点的团,其中v是k的二进制表示。}
接受该语言CLIQUE的非确定性算法:用非确定性选择指令选出包含k个顶点的候选顶点子集V,然后确定性地检查该子集是否是团问题的一个解。算法分为3个阶段
算法的第一阶段将输入串w#v分解,并计算出n = ,以及用v表示的整数k。若输入不具有形式w#v或|w|不是一个平方数就拒绝该输入。显而易见,第一阶段可在时间内完成。
在算法的第二阶段中,非确定性地选择V的一个k元子集V’V。
算法的第三阶段是确定性地检查V’的团性质。若V’是一个团则接受输入,否则拒绝输入。这显然可以在时间内完成。因此,整个算法的时间复杂性为 。
非确定性算法在多项式时间内接受语言CLIQUE,故CLIQUE∈NP.
NP完全问题
PNP。
直观上看,P类问题是确定性计算模型下的易解问题类,而NP类问题是非确定性计算模型下的易验证问题类。
大多数的计算机科学家认为NP类中包含了不属于P类的语言,即P≠NP。
NP完全问题有一种令人惊奇的性质,即如果一个NP完全问题能在多项式时间内得到解决,那么NP中的每一个问题都可以在多项式时间内求解,即P = NP。
目前还没有一个NP完全问题有多项式时间算法。
三、NP完全问题的近似算法
迄今为止,所有的NP完全问题都还没有多项式时间算法。
对于这类问题,通常可采取以下几种解题策略。
(1)只对问题的特殊实例求解
(2)用动态规划法或分支限界法求解
(3)用概率算法求解
(4)只求近似解
(5)用启发式方法求解
近似算法的性能
若一个最优化问题的最优值为c*,求解该问题的一个近似算法求得的近似最优解相应的目标函数值为c,则将该近似算法的性能比定义为(注意:求最大值与最小值的性能比定义之间的不同)。
怎么理解那个Ratio Bound呢?第一点明白OPT是最优解,我们的近似解不可能优于它,所以对于最大化问题,A一定比OPT小而对于最小化问题A一定比OPT大,所以上面的连个max取了不同的值。注意这里的Ratio Bound指的是那个B(n),即是max{A/OPT, OPT/A}的上界。
在通常情况下,该性能比是问题输入规模n的一个函数ρ(n),即。
该近似算法的相对误差定义为:。若对问题的输入规模n,有一函数ε(n)使得则称ε(n)为该近似算法的相对误差界。近似算法的性能比ρ(n)与相对误差界ε(n)之间显然有如下关系:。
旅行售货员问题近似算法
问题描述:给定一个完全无向图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倍。
实现:
代码 /* 主题:近似算法——旅行售货员问题
* 作者: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 = , int nVertexIndexB = , int nWeight = )
: 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<bool> bFlag (m_nNodeCount, false) ;
bFlag[] = true ; int nMaxIndexA ;
int nMaxIndexB ;
int j = ;
while (j < m_nNodeCount - ) {
int nMaxWeight = numeric_limits<int>::max () ;
// 找到当前最短路径
int i = ;
while (i < m_nNodeCount) {
if (!bFlag[i]) {
++ i ;
continue ;
}
for (int j = ; 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 = ;
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()-].m_nVertexIndexB << "->"
<< mstree[].m_nVertexIndexA << " : "
<< graph[mstree[].m_nVertexIndexA][mstree[mstree.size()-].m_nVertexIndexB]
<< endl ;
iweight += graph[mstree[].m_nVertexIndexA][mstree[mstree.size()-].m_nVertexIndexB] ;
cout << "Total weight: " << iweight << endl ;
}
private:
MST_Prim m_mstPrim ;
};
int main()
{
const int cnNodeCount = ;
vector<vector<int> > graph (cnNodeCount) ;
for (size_t i = ; i < graph.size() ; ++ i) {
graph[i].resize (cnNodeCount, numeric_limits<int>::max()) ;
}
graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; AA_TSP aa (graph) ;
aa.Get_AA_Path () ;
return ;
}
2 一般的旅行售货员问题
在费用函数不一定满足三角不等式的一般情况下,不存在具有常数性能比的解TSP问题的多项式时间近似算法,除非P=NP。换句话说,若P≠NP,则对任意常数ρ>1,不存在性能比为ρ的解旅行售货员问题的多项式时间近似算法。
NP完全性理论与近似算法的更多相关文章
- 什么是P问题、NP问题和NPC问题
为了迎接我的期末考试,认真的看了一下关于NP完全性理论这一章,奈何课本上说的我怎么都看不懂,所以找了个博客认真研究了一下,同样贴出来分享给大家,大牛就是大牛,把问题说的很明白,看完后受益匪浅.其中有一 ...
- p,np,npc,np难问题,确定图灵机与非确定图灵机
本文转自豆瓣_燃烧的影子 图灵机与可计算性 图灵(1912~1954)出生于英国伦敦,19岁进入剑桥皇家学院研究量子力学和数理逻辑.1935年,图灵写出了"论高斯误差函数"的论文, ...
- 关于P,NP,NPC和NP-hard的通俗解释
这些概念以前老是犯糊涂,今天整清楚.摘要:P: Polynomial SolvableNP: Non-determinstic Polynomial Solvable 0)词语解释:Polynomia ...
- Google Interview University - 坚持完成这套学习手册,你就可以去 Google 面试了
作者:Glowin链接:https://zhuanlan.zhihu.com/p/22881223来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 原文地址:Google ...
- 算法设计手冊(第2版)读书笔记, Springer - The Algorithm Design Manual, 2ed Steven S.Skiena 2008
The Algorithm Design Manual, 2ed 跳转至: 导航. 搜索 Springer - The Algorithm Design Manual, 2ed Steven S.Sk ...
- 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)
第一部分 基础知识 第1章 算法在计算中的作用 第2章 算法基础 第3章 函数的增长 第4章 分治策略 第5章 概率分析和随机算法 第二部分 排序和顺序统计量 第6章 堆排序 第7章 快速排序 第8章 ...
- 贪婪算法(Greedy Algorithm)
Greedy Algorithm <数据结构与算法--C语言描述> 图论涉及的三个贪婪算法 Dijkstra 算法 Prim 算法 Kruskal 算法 Greedy 经典问题:coin ...
- 【转载】 历届Turing奖得主名单
Turing奖最早设立于1966年,是美国计算机协会在计算机技术方面所授予的最高奖项,被喻为计算机界的诺贝尔奖.它是以英国数学天才Alan Turing先生的名字命名的,Alan Turing先生对早 ...
- 历届图灵奖 (Turing award)得奖名单
历届图灵奖 (Turing award)得奖名单 一.总结 一句话总结:各个方面都有. 二.历届图灵奖 (Turing award)得奖名单 Turing奖最早设立于1966年,是美国计算机协会在计算 ...
随机推荐
- 如何通过创建切片器窗格节省PowerBI报告空间
许多用户在使用Power BI的过程中,都会有这么一个困扰:在Power BI 开发中,切片器一旦过多就会占用非常多的空间.发生这种情况时,您显示数据的页面也会更加小.但另一方面,如果您没有切片器,报 ...
- 位图(bitmap)—— C语言实现
高级数据结构及应用 -- 使用 bitmap 进行字符串去重 位图应当具备的置一,清零,以及判断三大功能: #define BITS_PER_WORD 32 #define MASK 0x1f #de ...
- Python学习笔记第十七周
目录: 一.jQuery 内容: 一.jQuery: ps:版本 1.xx (推荐最新版本,兼容性好) 2.xx 3.xx 转换: jQuery对象[0] => DOM对象 $(DOM对象 ...
- (转)View Transform(视图变换)详解
原文作者讲得太好了,唯有这篇让我对视图矩阵了解的清晰了很多. --------------------------------------------------------------------- ...
- 安装 aconda 后Linux的终端界面前部出现(base)字样
aconda 是做什么用的这里就不说了,一般玩Python的都知道这东西,最早接触这东西是因为它把NVIDIA中cuda计算和Python互连的一个库拿下了,是买下来了还是专业,还是唯一合作的也就记不 ...
- HTML5 canvas 内部元素事件响应
HTML5 canvas 内部元素事件响应 isPointInPath 只能拿当前上下文的路径 重画每个部分 都isPointInPath判断
- Git图形化界面客户端大汇总
文,还在不断更新,网上搜到的同名文章都是未经同意就从这里复制过去的) 一.TortoiseGit - The coolest Interface to Git Version Control Tort ...
- 2017-2018-2 20165313实验三 《敏捷开发与XP实践》
实验报告封面 实验内容及步骤 实验一 1.试验要求: 参考http://www.cnblogs.com/rocedu/p/6371315.html#SECCODESTANDARD安装alibaba 插 ...
- 《DSP using MATLAB》Problem5.33
代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...
- 《DSP using MATLAB》Problem 5.28
昨晚手机在看X信的时候突然黑屏,开机重启都没反应,今天维修师傅说使用时间太长了,还是买个新的吧,心疼银子啊! 这里只放前两个小题的图. 代码: 1. %% ++++++++++++++++++++++ ...