Найдите минимальное количество элементов в наборе, используя z3py - PullRequest
1 голос
/ 01 мая 2020

Упражнение: найдите минимальное количество элементов в наборе 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)

, но оно работает слишком медленно , Работает только для небольших номеров. Как я могу улучшить это?

Ответы [ 2 ]

3 голосов
/ 01 мая 2020

Почти всегда плохая идея представлять логические числа целыми числами в 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]

Я не проверял, является ли это правильным решением, но в по крайней мере, вы должны начать!

1 голос
/ 01 мая 2020

Не ответ, а подтверждение 7-битного решения , предложенного псевдоним .

Я попробовал следующую модель MiniZin c:

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
...