Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
C++ 如何通过SAT和优化解决顶点覆盖问题?_C++_Algorithm_Optimization_Sat_Optimathsat - Fatal编程技术网

C++ 如何通过SAT和优化解决顶点覆盖问题?

C++ 如何通过SAT和优化解决顶点覆盖问题?,c++,algorithm,optimization,sat,optimathsat,C++,Algorithm,Optimization,Sat,Optimathsat,所以现在我正在使用SAT解决最小顶点覆盖问题,这是我对图G={V,E}的编码,它有k个顶点覆盖,下面是这些子句: Let n = sizeof(V); 首先,顶点覆盖中至少有一个顶点: For i in {1..k} Add clause (x<1,i> ∨ x<2,i> ∨ ··· ∨ x<n,i>); For j in {1..n} For l and m in {1..k} with l < m Add clau

所以现在我正在使用SAT解决最小顶点覆盖问题,这是我对图G={V,E}的编码,它有k个顶点覆盖,下面是这些子句:

Let n = sizeof(V);
首先,顶点覆盖中至少有一个顶点:

For i in {1..k}
    Add clause (x<1,i> ∨ x<2,i> ∨ ··· ∨ x<n,i>);
For j in {1..n}
    For l and m in {1..k} with l < m
        Add clause (¬x<j,l> ∨ ¬x<j,m>) 
For j in {1..k}
    For l and m in {1..n} with l < m
        Add clause (¬x<l,j> ∨ ¬x<m,j>) 
{1..k}中i的

添加第(x)条∨ x∨ ··· ∨ x) );
然后,一个顶点不能在顶点覆盖中出现两次:

For i in {1..k}
    Add clause (x<1,i> ∨ x<2,i> ∨ ··· ∨ x<n,i>);
For j in {1..n}
    For l and m in {1..k} with l < m
        Add clause (¬x<j,l> ∨ ¬x<j,m>) 
For j in {1..k}
    For l and m in {1..n} with l < m
        Add clause (¬x<l,j> ∨ ¬x<m,j>) 
{1..n}中j的

对于l
之后,顶点覆盖中的特定位置只能出现一个顶点:

For i in {1..k}
    Add clause (x<1,i> ∨ x<2,i> ∨ ··· ∨ x<n,i>);
For j in {1..n}
    For l and m in {1..k} with l < m
        Add clause (¬x<j,l> ∨ ¬x<j,m>) 
For j in {1..k}
    For l and m in {1..n} with l < m
        Add clause (¬x<l,j> ∨ ¬x<m,j>) 
{1..k}中j的

对于l
最后,顶点覆盖中至少有一个顶点应来自边:

For i and j in each edge e from E
    Add clause (x<i,1> ∨ x<i,2> ∨ ... ∨ x<i,k> ∨ x<j,1> ∨ ... ∨ x<j,k>)
从e开始的每条边e中的i和j的

添加第(x)条∨ x∨ ... ∨ x∨ x∨ ... ∨ 十)
现在我可以通过使用这种编码获得最小顶点覆盖,但是效率非常差。我只能得到<20个顶点的任何图形的结果,否则只需要几分钟和几个小时就可以得到结果。我现在正在考虑将它从SAT进一步降低,也许降低到3SAT。但看起来我不能简单地将all子句从nCNF改为3CNF来获得相同的结果。谁能帮我弄清楚下一步该怎么办?我需要一个全新的编码吗

非常感谢你


顺便说一句,我使用miniat作为解算器。

首先,让我假设我在理解您的编码时遇到一些困难,所以我将从头开始。这就是我处理这个问题的方法

注意:我的示例基于语法,可以使用类似于MaxSMT的解算器来解决,例如和。但是,由于它不使用任何SMT功能,因此您实际上可以使用在MaxSAT竞赛中使用的功能编写相同的内容。在选择解算器来处理问题时,这将为您提供更多选择。我可能错了,但我推测在这个特定问题上,MaxSAT解算器可能比MaxSMT解算器表现更好


设G={V,E}是一个图

首先,为图中的每个顶点声明一个布尔变量:

(declare-fun vertex_1 () Bool)
...
(declare-fun vertex_K () Bool)
(任何没有边的顶点都应该忽略,因为这只会浪费时间。)

其次,为图中连接顶点
i
和顶点
j
的每条边声明一个布尔变量(假设为无向)

第三,断言必须覆盖每个边
edge\u i\u j

(assert edge_i_j)
...
第四,如果一条边被覆盖,则顶点
i
或顶点
j
必须为
true

(assert (=> edge_i_j (or vertex_i vertex_j)))
...
第五,对于每个
vertex\u i
软子句断言
vertex\u i
应该是
false
。如果情况并非如此,则对
cover
的值处以
1
的罚款:

(assert-soft (not vertex_i) :weight 1 :id cover)
最后,解决问题:

(set-option :config opt.maxsmt_engine=maxres) ; only for optimathsat
(minimize cover)                              ; only for optimathsat
(check-sat)
(get-objectives)
(get-model)
此时,可以使用任何有效的MaxSAT/MaxSMT引擎(例如)获得一个覆盖所有边的模型,同时使用最少数量的顶点(如果有的话)。

我在问题中没有看到任何优化组件,因为它与伪代码一起出现,所以我猜模型的某些部分丢失了。您能否编辑您的问题并包含缺少的部分?如果有任何优化正在进行,优化过程是属于miniat的还是您自己编写的?在后一种情况下,你介意详细说明它是如何工作的吗?