Z3和DIMACS输出
Z3目前支持输入的DIMACS格式。在解决问题之前,是否有任何方法输出问题的DIMACS格式?我的意思是将问题转换为系统CNFs并以DIMACS格式输出。Z3和DIMACS输出,z3,Z3,Z3目前支持输入的DIMACS格式。在解决问题之前,是否有任何方法输出问题的DIMACS格式?我的意思是将问题转换为系统CNFs并以DIMACS格式输出。 如果没有,任何朝这个方向发展的想法都会非常有用。DIMACS格式非常原始,它只支持布尔变量。Z3并没有将每个问题都简化为SAT。有些问题是使用命题SAT解算器解决的,但这不是规则。这通常仅在输入仅包含布尔和/或位向量变量时发生。此外,即使输入问题只包含布尔和位向量变量,也不能保证Z3将使用纯SAT解算器来解决它 也就是说,您可以使用来控制Z3
如果没有,任何朝这个方向发展的想法都会非常有用。DIMACS格式非常原始,它只支持布尔变量。Z3并没有将每个问题都简化为SAT。有些问题是使用命题SAT解算器解决的,但这不是规则。这通常仅在输入仅包含布尔和/或位向量变量时发生。此外,即使输入问题只包含布尔和位向量变量,也不能保证Z3将使用纯SAT解算器来解决它 也就是说,您可以使用来控制Z3。例如,对于位向量问题,以下策略将其转换为CNF格式的命题公式。将其转换为DIMAC应该很简单。这是一个例子。您可以在以下网站在线试用:
x,y,z=BitVecs('x y z',16)
g=目标()
g、 加(x==y,z>If(x<0,x,-x))
打印g
#t是一种将位向量问题简化为命题CNF的策略
t=Then('simplify'、'bit blast'、'tseitin cnf')
子目标=t(g)
断言len(子目标)=1
#遍历第一个子目标的每个子句
对于子目标[0]中的c:
打印c
多亏了莱昂纳多的回答,我想出了这个代码,可以满足你的需求:
private static void Output(Context ctx,Solver slv)
{
var goal = ctx.MkGoal();
goal.Add(slv.Assertions);
var applyResult = ctx.Then(ctx.MkTactic("simplify"),
ctx.MkTactic("bit-blast"),
ctx.MkTactic("tseitin-cnf")).Apply(goal);
Debug.Assert(applyResult.Subgoals.Length==1);
var map = new Dictionary<BoolExpr,int>();
foreach (var f in applyResult.Subgoals[0].Formulas)
{
Debug.Assert(f.IsOr);
foreach (var e in f.Args)
if (e.IsNot)
{
Debug.Assert(e.Args.Length==1);
Debug.Assert(e.Args[0].IsConst);
map[(BoolExpr)e.Args[0]] = 0;
}
else
{
Debug.Assert(e.IsConst);
map[(BoolExpr)e] = 0;
}
}
var id = 1;
foreach (var key in map.Keys.ToArray())
map[key] = id++;
using (var fos = File.CreateText("problem.cnf"))
{
fos.WriteLine("c DIMACS file format");
fos.WriteLine($"p cnf {map.Count} {applyResult.Subgoals[0].Formulas.Length}");
foreach(var f in applyResult.Subgoals[0].Formulas)
{
foreach (var e in f.Args)
if (e.IsNot)
fos.Write($"{map[(BoolExpr)e.Args[0]]} ");
else
fos.Write($"-{map[(BoolExpr)e]} ");
fos.WriteLine("0");
}
}
}
私有静态无效输出(上下文ctx、解算器slv)
{
var goal=ctx.MkGoal();
添加(slv.Assertions);
var applyResult=ctx.Then(ctx.mk)(“简化”),
ctx.mktractic(“钻头爆炸”),
ctx.mktractic(“tseitin cnf”)。应用(目标);
Assert(applyResult.Subgoals.Length==1);
var map=newdictionary();
foreach(applyResult.Subgoals[0].公式中的var f)
{
断言(f.IsOr);
foreach(f.Args中的变量e)
如果(e.IsNot)
{
Assert(e.Args.Length==1);
Assert(e.Args[0].IsConst);
map[(BoolExpr)e.Args[0]]=0;
}
其他的
{
Assert(e.IsConst);
map[(BoolExpr)e]=0;
}
}
var-id=1;
foreach(map.Keys.ToArray()中的var key)
map[key]=id++;
使用(var fos=File.CreateText(“problem.cnf”))
{
fos.WriteLine(“c DIMACS文件格式”);
fos.WriteLine($“p cnf{map.Count}{applyResult.Subgoals[0].Formulas.Length}”);
foreach(applyResult.Subgoals[0].公式中的var f)
{
foreach(f.Args中的变量e)
如果(e.IsNot)
fos.Write($“{map[(BoolExpr)e.Args[0]}”);
其他的
fos.Write($“-{map[(BoolExpr)e]}”);
fos.WriteLine(“0”);
}
}
}
要使其工作,您应该通过调用slv.Assert(…)
将所有约束直接添加到解算器中
private static void Output(Context ctx,Solver slv)
{
var goal = ctx.MkGoal();
goal.Add(slv.Assertions);
var applyResult = ctx.Then(ctx.MkTactic("simplify"),
ctx.MkTactic("bit-blast"),
ctx.MkTactic("tseitin-cnf")).Apply(goal);
Debug.Assert(applyResult.Subgoals.Length==1);
var map = new Dictionary<BoolExpr,int>();
foreach (var f in applyResult.Subgoals[0].Formulas)
{
Debug.Assert(f.IsOr);
foreach (var e in f.Args)
if (e.IsNot)
{
Debug.Assert(e.Args.Length==1);
Debug.Assert(e.Args[0].IsConst);
map[(BoolExpr)e.Args[0]] = 0;
}
else
{
Debug.Assert(e.IsConst);
map[(BoolExpr)e] = 0;
}
}
var id = 1;
foreach (var key in map.Keys.ToArray())
map[key] = id++;
using (var fos = File.CreateText("problem.cnf"))
{
fos.WriteLine("c DIMACS file format");
fos.WriteLine($"p cnf {map.Count} {applyResult.Subgoals[0].Formulas.Length}");
foreach(var f in applyResult.Subgoals[0].Formulas)
{
foreach (var e in f.Args)
if (e.IsNot)
fos.Write($"{map[(BoolExpr)e.Args[0]]} ");
else
fos.Write($"-{map[(BoolExpr)e]} ");
fos.WriteLine("0");
}
}
}