C++ 如何通过SAT和优化解决顶点覆盖问题?
所以现在我正在使用SAT解决最小顶点覆盖问题,这是我对图G={V,E}的编码,它有k个顶点覆盖,下面是这些子句: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
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的还是您自己编写的?在后一种情况下,你介意详细说明它是如何工作的吗?