【问题标题】:Find the minimum number of elements in the set using z3py使用 z3py 查找集合中的最小元素数
【发布时间】:2020-08-16 02:42:24
【问题描述】:

运动: 找出集合 Z 中加起来为 4285 的最小元素数。 在哪里Z = { w(i): w(n) - n^2 - n + 1, i = 1,2,...,30 }

我创建了一个解决方案:

def f(t):
    return t ** 2 - t + 1


opt = z3.Optimize()

x = IntVector('x', 30)
x_val = [And(x[i] >= 0, x[i] <= 1) for i in range(30)]
opt.add(x_val)

m = [x[i] * f(i + 1) for i in range(30)]
m_sum = z3.Sum(m)

opt.add(m_sum == 4285)
opt.minimize(z3.Sum(x))

if z3.sat == opt.check():
    model = opt.model()
    print(model)

但它运行得太慢了。仅适用于小数字。我该如何改进它?

【问题讨论】:

    标签: python z3 solver smt z3py


    【解决方案1】:

    不是答案,而是对alias提出的7位solution的确认。

    我尝试了以下 MiniZinc 型号:

    int: n = 30;
    set of int: N = 1..n;
    
    function int: f(int: t) =
      t*t - t + 1;
    
    array[N] of var bool: x;
    
    constraint ( 4285 == sum([x[i] * f(i) | i in N]) );
    
    var int: bitCount = sum([ x[i] | i in N]);
    
    solve minimize bitCount;
    
    output ["#\(bitCount): "] ++
           ["\(if x[i] then 1 else 0 endif)" | i in N];
    

    结果:

    #7: 000000000000000010001001011011
    

    【讨论】:

      【解决方案2】:

      在 z3 中用整数表示布尔值几乎总是一个坏主意。因此,不要使用整数向量来表示项目介于 0-1 之间,而只需使用布尔向量和 If 构造。像这样的:

      from z3 import *
      
      def f(t):
          return t ** 2 - t + 1
      
      opt = z3.Optimize()
      
      x = BoolVector('x', 30)
      
      m = [If(x[i], f(i + 1), 0) for i in range(30)]
      m_sum = z3.Sum(m)
      
      opt.add(m_sum == 4285)
      
      opt.minimize(z3.Sum([If(x[i], 1, 0) for i in range(30)]))
      
      if z3.sat == opt.check():
          model = opt.model()
          print(model)
      

      当我运行它时,它运行得非常快并找到了解决方案:

      [x__0 = False,
       x__1 = False,
       x__2 = False,
       x__3 = False,
       x__4 = False,
       x__5 = False,
       x__6 = False,
       x__7 = False,
       x__8 = False,
       x__9 = False,
       x__10 = False,
       x__11 = False,
       x__12 = False,
       x__13 = True,
       x__14 = False,
       x__15 = False,
       x__16 = False,
       x__17 = True,
       x__18 = False,
       x__19 = False,
       x__20 = False,
       x__21 = False,
       x__22 = False,
       x__23 = False,
       x__24 = False,
       x__25 = True,
       x__26 = True,
       x__27 = True,
       x__28 = True,
       x__29 = True]
      

      我没有检查这是否是正确的解决方案,但至少它应该让你开始!

      【讨论】:

        猜你喜欢
        • 2015-04-18
        • 2013-01-10
        • 2019-04-15
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 2021-10-22
        • 1970-01-01
        相关资源
        最近更新 更多