Kann über Integers gelöst werden, wobei die Multiplikatoren zwischen 0 und 1 eingeschränkt sind. Ich werde das anhand eines spezifischen Beispiels zeigen (ersten 10 Primzahlen, Summe ergibt 100), aber es ist einfach, ein allgemeines Verfahren dafür zu entwickeln.
primeset = Prime[Range[10]];
mults = Array[x, Length[primeset]];
constraints01 = Map[0 <= # <= 1 &, mults];
target = 100;
Timing[res = mults /.
Solve[Flatten[{mults.primeset == target, constraints01}],
mults, Integers];
Map[Pick[primeset, #, 1] &, res]
]
Ergebnis [178]= {0,004, {{7, 11, 13, 17, 23, 29}, {5, 11, 13, 19, 23, 29}, {5, 7, 17, 19, 23, 29}, {2, 5, 11, 13, 17, 23, 29}, {2, 3, 11, 13, 19, 23, 29}, {2, 3, 7, 17, 19, 23, 29}, {2, 3, 5, 7, 11, 13, 17, 19, 23}}}
---Bearbeiten--- Um dies in Version 7 durchzuführen, würde man Reduce anstelle von Solve verwenden. Ich werde dies in einer Funktion bündeln.
knapsack[target_, items_] := Module[
{newset, x, mults, res},
newset = Select[items, # <= target &];
mults = Array[x, Length[newset]];
res = mults /.
{ToRules[Reduce[
Flatten[{mults.newset == target, Map[0 <= # <= 1 &, mults]}],
mults, Integers]]};
Map[Pick[newset, #, 1] &, res]]
Hier ist das Beispiel von Leonid Shifrin:
Timing[Length[knapsack[200, Prime[Range[150]]]]]
Ergebnis [128]= {1,80373, 4660}
Nicht so schnell wie der Baumcode, aber dennoch (denke ich) akzeptables Verhalten. Zumindest nicht offensichtlich unvernünftig.
---Ende Bearbeiten---
Daniel Lichtblau Wolfram Research