This is my first time using Picat. I have attempted to write a basic knapsack problem. However, when run, the solution seems to pick no items even though I (think I) have asked it to maximise the total value of the items picked.
Here's the output:
$ Picat/picat --version
Picat version 3.5
$ more items-59.txt
58
45,27,1,2,27,4,22,4,36,19,39,54,26,17,8,23,35,38,35,12,52,21,43,15,46,43,21,22,49,1,12,8,47,23,28,35,4,17,14,1,45,41,13,49,24,6,7,20,4,33,32,16,46,17,14,40,40,52,33
9,19,15,14,7,20,18,19,2,3,15,15,4,14,3,20,1,15,13,10,21,14,18,20,17,23,18,14,6,23,14,3,4,9,20,21,10,19,9,13,8,4,11,23,3,13,2,10,15,20,23,5,10,14,4,20,10,3,18
$ more knapsack.pi
import sat.
import util.
main(Args) =>
solve_knap(Args).
solve_knap(Args) =>
Params = open(Args[1]),
MaxWeight = to_int(read_line(Params)),
ValsStr = split(read_line(Params),","),
N = len(ValsStr),
Vals = [to_int(X) : X in ValsStr],
WeightsStr = split(read_line(Params),","),
Weights = [to_int(X) : X in WeightsStr],
Take = new_array(N),
Take :: 0..1 ,
TotalWeight #= sum([ W * T : W in Weights, T in Take]),
TotalWeight #<= MaxWeight ,
TotalVal #= sum([ V * T : V in Vals, T in Take]),
solve([$max(TotalVal),$report(printf("Found %d\n",TotalVal))],Take),
println(TotalWeight),
println(MaxWeight),
println(Take).
$ Picat/picat knapsack.pi items-59.txt
Found 0
0
58
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
The is the same whether I import cp or import sat. I'm sure I'm making a newbie mistake, any help would be appreciated.
The main issue with this model is the two list comprehensions (see below for the full model):
They are actually doing cross products (all W's times all T's) which is not the proper way. Instead they should be using
zipto just multiply each ith pair.Unfortunately, for
zipto work theTakemust be a list, not an array:An alternative of using
zipis to use this approach (which works with Take as an array):Also, for this problem a MIP solver (GLPK or Cbc) are faster than SAT and CP solvers, and the SMT solvers are (surprisingly) fast. Here's the timing of the solvers I have on my machine (I don't have Gurobi available):
Here's the full model:
Here's the solution (from the MIP/GLPK run):