假设x,y,z是int变量而A是矩阵,我想表达一个约束:
z == A[x][y]
然而,这会导致错误: TypeError:object不能解释为索引
这样做的正确方法是什么?
=======================
一个具体的例子:
我想选择2项具有最佳组合得分的项目, 其中得分由每个项目的值和选择对上的奖励给出。 例如, 对于3个项目:a,b,c具有相关值[1,2,1],并且对上的奖励(a,b)= 2,(a,c)= 5,(b,c)= 3,最佳选择是(a,c),因为它得分最高:1 + 1 + 5 = 7.
我的问题是如何表示选择奖金的约束。 假设CHOICE [0]和CHOICE [1]是选择变量而B是奖励变量。 理想的约束应该是:
B = bonus[CHOICE[0]][CHOICE[1]]
但它导致TypeError:object无法解释为索引 我知道另一种方法是使用嵌套for来首先实例化CHOICE,然后代表B,但这对于大量数据来说效率非常低。 有没有专家建议我提供更好的解决方案呢?
如果有人想玩玩具示例,请输入以下代码:
from z3 import *
items = [0,1,2]
value = [1,2,1]
bonus = [[1,2,5],
[2,1,3],
[5,3,1]]
choices = [0,1]
# selection score
SCORE = [ Int('SCORE_%s' % i) for i in choices ]
# bonus
B = Int('B')
# final score
metric = Int('metric')
# selection variable
CHOICE = [ Int('CHOICE_%s' % i) for i in choices ]
# variable domain
domain_choice = [ And(0 <= CHOICE[i], CHOICE[i] < len(items)) for i in choices ]
# selection implication
constraint_sel = []
for c in choices:
for i in items:
constraint_sel += [Implies(CHOICE[c] == i, SCORE[c] == value[i])]
# choice not the same
constraint_neq = [CHOICE[0] != CHOICE[1]]
# bonus constraint. uncomment it to see the issue
# constraint_b = [B == bonus[val(CHOICE[0])][val(CHOICE[1])]]
# metric definition
constraint_sumscore = [metric == sum([SCORE[i] for i in choices ]) + B]
constraints = constraint_sumscore + constraint_sel + domain_choice + constraint_neq + constraint_b
opt = Optimize()
opt.add(constraints)
opt.maximize(metric)
s = []
if opt.check() == sat:
m = opt.model()
print [ m.evaluate(CHOICE[i]) for i in choices ]
print m.evaluate(metric)
else:
print "failed to solve"
答案 0 :(得分:2)
原来解决这个问题的最好方法是实际上根本不使用数组,而只是创建整数变量。使用这种方法,最初发布的317x317项目问题实际上在我相对较旧的计算机上大约40秒内得到解决:
[ 0.01s] Data loaded
[ 2.06s] Variables defined
[37.90s] Constraints added
[38.95s] Solved:
c0 = 19
c1 = 99
maxVal = 27
请注意实际的&#34;解决方案&#34;发现大约一秒钟!但是,添加所有必需的约束需要花费40秒的大部分时间。这是编码:
from z3 import *
import sys
import json
import sys
import time
start = time.time()
def tprint(s):
global start
now = time.time()
etime = now - start
print "[%ss] %s" % ('{0:5.2f}'.format(etime), s)
# load data
with open('data.json') as data_file:
dic = json.load(data_file)
tprint("Data loaded")
items = dic['items']
valueVals = dic['value']
bonusVals = dic['bonusVals']
vals = [[Int("val_%d_%d" % (i, j)) for j in items if j > i] for i in items]
tprint("Variables defined")
opt = Optimize()
for i in items:
for j in items:
if j > i:
opt.add(vals[i][j-i-1] == valueVals[i] + valueVals[j] + bonusVals[i][j])
c0, c1 = Ints('c0 c1')
maxVal = Int('maxVal')
opt.add(Or([Or([And(c0 == i, c1 == j, maxVal == vals[i][j-i-1]) for j in items if j > i]) for i in items]))
tprint("Constraints added")
opt.maximize(maxVal)
r = opt.check ()
if r == unsat or r == unknown:
raise Z3Exception("Failed")
tprint("Solved:")
m = opt.model()
print " c0 = %s" % m[c0]
print " c1 = %s" % m[c1]
print " maxVal = %s" % m[maxVal]
我认为这和Z3在这个问题上的速度一样快。当然,如果您想最大化多个指标,那么您可以构建代码,以便重用大多数约束,从而分摊构建模型的成本一次,然后逐步优化为了获得最佳性能。