2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,9 +1,8 @@
See also: [[Knapsack problem/Bounded]], [[Knapsack problem/0-1]]
A traveler gets diverted and has to make an unscheduled stop in what turns out to be Shangri La.   Opting to leave, he is allowed to take as much as he likes of the following items, so long as it will fit in his knapsack, and he can carry it.
A traveller gets diverted and has to make an unscheduled stop in what turns out to be Shangri La. Opting to leave, he is allowed to take as much as he likes of the following items, so long as it will fit in his knapsack, and he can carry it.
He knows that he can carry no more than 25 'weights' in total; and that the capacity of his knapsack is 0.25 'cubic lengths'.
He knows that he can carry no more than   25   'weights' in total;   and that the capacity of his knapsack is   0.25   'cubic lengths'.
Looking just above the bar codes on the items he finds their weights and volumes. He digs out his recent copy of a financial paper and gets the value of each item.
Looking just above the bar codes on the items he finds their weights and volumes.   He digs out his recent copy of a financial paper and gets the value of each item.
<table
style="text-align: left; width: 80%;" border="4"
cellpadding="2" cellspacing="2"><tr><td
@ -44,14 +43,20 @@ Looking just above the bar codes on the items he finds their weights and volumes
style="background-color: rgb(255, 204, 255);" align="left"
nowrap="nowrap" valign="middle">&lt;=25</td><td
style="background-color: rgb(255, 204, 255);" align="left"
nowrap="nowrap" valign="middle">&lt;=0.25&nbsp;</td></tr></table>
nowrap="nowrap" valign="middle">&lt;=0.25&nbsp;</td></tr>
</table>
<br>
He can only take whole units of any item, but there is much more of any item than he could ever carry
'''How many of each item does he take to maximise the value of items he is carrying away with him?'''
Note:
# There are four solutions that maximise the value taken. Only one ''need'' be given.
;Task:
Show how many of each item does he take to maximize the value of items he is carrying away with him.
;Note:
* &nbsp; There are four solutions that maximize the value taken. &nbsp; Only one ''need'' be given.
<!-- All solutions
@ -63,3 +68,8 @@ Note:
# (9, 0, 11) also minimizes weight and volume within the limits of calculation
-->
;Related tasks:
* &nbsp; [[Knapsack problem/Bounded]]
* &nbsp; [[Knapsack problem/0-1]]
<br><br>

View file

@ -1,52 +1,58 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct {
double val, wgt, vol;
const char * name;
} items[] = { // value in hundreds, volume in thousandths
{30, .3, 25, "panacea"},
{18, .2, 15, "ichor"},
{25, 2., 2, "gold"},
{0,0,0,0}
typedef struct {
char *name;
double value;
double weight;
double volume;
} item_t;
item_t items[] = {
{"panacea", 3000.0, 0.3, 0.025},
{"ichor", 1800.0, 0.2, 0.015},
{"gold", 2500.0, 2.0, 0.002},
};
/* silly setup for silly task */
int best_cnt[16] = {0}, cnt[16] = {0};
double best_v = 0;
int n = sizeof (items) / sizeof (item_t);
int *count;
int *best;
double best_value;
void grab_em(int idx, double cap_v, double cap_w, double v)
{
double val;
int t = cap_w / items[idx].wgt;
cnt[idx] = cap_v / items[idx].vol;
if (cnt[idx] > t) cnt[idx] = t;
while (cnt[idx] >= 0) {
val = v + cnt[idx] * items[idx].val;
if (!items[idx + 1].name) {
if (val > best_v) {
best_v = val;
memcpy(best_cnt, cnt, sizeof(int) * (1 + idx));
}
return;
}
grab_em(idx + 1, cap_v - cnt[idx] * items[idx].vol,
cap_w - cnt[idx] * items[idx].wgt, val);
cnt[idx]--;
}
void knapsack (int i, double value, double weight, double volume) {
int j, m1, m2, m;
if (i == n) {
if (value > best_value) {
best_value = value;
for (j = 0; j < n; j++) {
best[j] = count[j];
}
}
return;
}
m1 = weight / items[i].weight;
m2 = volume / items[i].volume;
m = m1 < m2 ? m1 : m2;
for (count[i] = m; count[i] >= 0; count[i]--) {
knapsack(
i + 1,
value + count[i] * items[i].value,
weight - count[i] * items[i].weight,
volume - count[i] * items[i].volume
);
}
}
int main(void)
{
int i;
grab_em(0, 250, 25, 0);
printf("value: %g hundreds\n", best_v);
for (i = 0; items[i].name; i++)
printf("%d %s\n", best_cnt[i], items[i].name);
return 0;
int main () {
count = malloc(n * sizeof (int));
best = malloc(n * sizeof (int));
best_value = 0;
knapsack(0, 0.0, 25.0, 0.25);
int i;
for (i = 0; i < n; i++) {
printf("%d %s\n", best[i], items[i].name);
}
printf("best value: %.0f\n", best_value);
free(count); free(best);
return 0;
}

View file

@ -3,8 +3,9 @@ class KnapsackItem {
has $.weight;
has $.value;
has $.name;
method new($volume,$weight,$value, $name) {
self.bless(*, :$volume, :$weight, :$value, :$name)
method new($volume,$weight,$value,$name) {
self.bless(:$volume, :$weight, :$value, :$name)
}
};

View file

@ -0,0 +1,62 @@
# Define the items to pack
$Item = @(
[pscustomobject]@{ Name = 'panacea'; Unit = 'vials' ; value = 3000; Weight = 0.3; Volume = 0.025 }
[pscustomobject]@{ Name = 'ichor' ; Unit = 'ampules'; value = 1800; Weight = 0.2; Volume = 0.015 }
[pscustomobject]@{ Name = 'gold' ; Unit = 'bars' ; value = 2500; Weight = 2.0; Volume = 0.002 }
)
# Define our maximums
$MaxWeight = 25
$MaxVolume = 0.25
# Set our default value to beat
$OptimalValue = 0
# Iterate through the possible quantities of item 0, without going over the weight or volume limit
ForEach ( $Qty0 in 0..( [math]::Min( [math]::Truncate( $MaxWeight / $Item[0].Weight ), [math]::Truncate( $MaxVolume / $Item[0].Volume ) ) ) )
{
# Calculate the remaining space
$RemainingWeight = $MaxWeight - $Qty0 * $Item[0].Weight
$RemainingVolume = $MaxVolume - $Qty0 * $Item[0].Volume
# Iterate through the possible quantities of item 1, without going over the weight or volume limit
ForEach ( $Qty1 in 0..( [math]::Min( [math]::Truncate( $RemainingWeight / $Item[1].Weight ), [math]::Truncate( $RemainingVolume / $Item[1].Volume ) ) ) )
{
# Calculate the remaining space
$RemainingWeight2 = $RemainingWeight - $Qty1 * $Item[1].Weight
$RemainingVolume2 = $RemainingVolume - $Qty1 * $Item[1].Volume
# Calculate the maximum quantity of item 2 for the remaining space, without going over the weight or volume limit
$Qty2 = [math]::Min( [math]::Truncate( $RemainingWeight2 / $Item[2].Weight ), [math]::Truncate( $RemainingVolume2 / $Item[2].Volume ) )
# Calculate the total value of the items packed
$TrialValue = $Qty0 * $Item[0].Value +
$Qty1 * $Item[1].Value +
$Qty2 * $Item[2].Value
# Describe the trial solution
$Solution = "$Qty0 $($Item[0].Unit) of $($Item[0].Name), "
$Solution += "$Qty1 $($Item[1].Unit) of $($Item[1].Name), and "
$Solution += "$Qty2 $($Item[2].Unit) of $($Item[2].Name) worth a total of $TrialValue."
# If the trial value is higher than previous most valuable trial...
If ( $TrialValue -gt $OptimalValue )
{
# Set the new number to beat
$OptimalValue = $TrialValue
# Overwrite the previous optimal solution(s) with the trial solution
$Solutions = @( $Solution )
}
# Else if the trial value matches the previous most valuable trial...
ElseIf ( $TrialValue -eq $OptimalValue )
{
# Add the trial solution to the list of optimal solutions
$Solutions += @( $Solution )
}
}
}
# Show the results
$Solutions

View file

@ -0,0 +1,36 @@
/*REXX program solves the knapsack/unbounded problem: highest value, weight, and volume.*/
/* value weight volume */
maxPanacea=0 /* ═══════ ══════ ══════ */
maxIchor =0; panacea.$ = 3000 ; panacea.w = 0.3 ; panacea.v = 0.025
maxGold =0; ichor.$ = 1800 ; ichor.w = 0.2 ; ichor.v = 0.015
max$ =0; gold.$ = 2500 ; gold.w = 2 ; gold.v = 0.002
now. =0; sack.$ = 0 ; sack.w = 25 ; sack.v = 0.25
maxPanacea= min(sack.w / panacea.w, sack.v / panacea.v)
maxIchor = min(sack.w / ichor.w, sack.v / ichor.v)
maxGold = min(sack.w / gold.w, sack.v / gold.v)
do p=0 to maxPanacea
do i=0 to maxIchor
do g=0 to maxGold
now.$= g * gold.$ + i * ichor.$ + p * panacea.$
now.w= g * gold.w + i * ichor.w + p * panacea.w
now.v= g * gold.v + i * ichor.v + p * panacea.v
if now.w > sack.w | now.v > sack.v then iterate
if now.$ > max$ then do; maxP=p; maxI=i; maxG=g
max$=now.$; maxW=now.w; maxV=now.v
end
end /*g (gold) */
end /*i (ichor) */
end /*p (panacea)*/
Ctot = maxP + maxI + maxG; L = length(Ctot) + 1
say ' panacea in sack:' right(maxP, L)
say ' ichors in sack:' right(maxI, L)
say ' gold items in sack:' right(maxG, L)
say '' copies("", L)
say 'carrying a total of:' right(cTot, L)
say left('', 40) "total value: " max$ / 1
say left('', 40) "total weight: " maxW / 1
say left('', 40) "total volume: " maxV / 1
/*stick a fork in it, we're all done. */

View file

@ -0,0 +1,40 @@
/*REXX program solves the knapsack/unbounded problem: highest value, weight, and volume.*/
maxPanacea=0 /* value weight volume */
maxIchor =0 /* ═══════ ═══════ ══════ */
maxGold =0; panacea.$ = 3000 ; panacea.w = 0.3 ; panacea.v = 0.025
max$ =0; ichor.$ = 1800 ; ichor.w = 0.2 ; ichor.v = 0.015
now. =0; gold.$ = 2500 ; gold.w = 2 ; gold.v = 0.002
# =0; sack.$ = 0 ; sack.w = 25 ; sack.v = 0.25
L =0
maxPanacea= min(sack.w / panacea.w, sack.v / panacea.v)
maxIchor = min(sack.w / ichor.w, sack.v / ichor.v)
maxGold = min(sack.w / gold.w, sack.v / gold.v)
do p=0 to maxPanacea
do i=0 to maxIchor
do g=0 to maxGold
now.$ = g * gold.$ + i * ichor.$ + p * panacea.$
now.w = g * gold.w + i * ichor.w + p * panacea.w
now.v = g * gold.v + i * ichor.v + p * panacea.v
if now.w > sack.w | now.v > sack.v then iterate i
if now.$ > max$ then do; #=0; max$=now.$; end
if now.$ = max$ then do; #=#+1; maxP.#=p; maxI.#=i; maxG.#=g
max$.#=now.$; maxW.#=now.w; maxV.#=now.v
L=max(L, length(p + i + g) )
end
end /*g (gold) */
end /*i (ichor) */
end /*p (panacea)*/
L=L + 1
do j=1 for #; say; say copies('', 70) "solution" j
say ' panacea in sack:' right(maxP.j, L)
say ' ichors in sack:' right(maxI.j, L)
say ' gold items in sack:' right(maxG.j, L)
say '' copies("", L)
say 'carrying a total of:' right(maxP.j + maxI.j + maxG.j, L)
say left('', 40) "total value: " max$.j / 1
say left('', 40) "total weight: " maxW.j / 1
say left('', 40) "total volume: " maxV.j / 1
end /*j*/
/*stick a fork in it, we're all done. */

View file

@ -1,45 +0,0 @@
/*REXX program solves a knapsack/unbounded problem. */
maxPanacea = 0
maxIchor = 0
maxGold = 0
max$ = 0
current. = 0
/* value weight volume */
/* ═══════ ═══════ ══════ */
panacea.$ = 3000 ; panacea.w = 0.3 ; panacea.v = 0.025
ichor.$ = 1800 ; ichor.w = 0.2 ; ichor.v = 0.015
gold.$ = 2500 ; gold.w = 2 ; gold.v = 0.002
sack.$ = 0 ; sack.w = 25 ; sack.v = 0.25
maxPanacea = min(sack.w / panacea.w, sack.v / panacea.v)
maxIchor = min(sack.w / ichor.w, sack.v / ichor.v)
maxGold = min(sack.w / gold.w, sack.v / gold.v)
do p=0 to maxpanacea
do i=0 to maxichor
do g=0 to maxgold
current.$ = g*gold.$ + i*ichor.$ + p*panacea.$
current.w = g*gold.w + i*ichor.w + p*panacea.w
current.v = g*gold.v + i*ichor.v + p*panacea.v
if current.w>sack.w | current.v>sack.v then iterate
if current.$>max$ then do
max$ = current.$
totalW = current.w
totalV = current.v
maxP = p; maxI = i; maxG = g
end
end /*g (gold) */
end /*i (ichor) */
end /*p (panacea)*/
cTot = maxP + maxI + maxG
L = length(cTot) + 1
say ' panacea in sack:' right(maxP,L)
say ' ichors in sack:' right(maxI,L)
say ' gold items in sack:' right(maxG,L)
say '' copies('',L)
say 'carrying a total of:' right(cTot,L)
say left('',40) 'total value: ' max$/1
say left('',40) 'total weight: ' totalW/1
say left('',40) 'total volume: ' totalV/1
/*stick a fork in it, we're done.*/

View file

@ -0,0 +1,40 @@
/* create SAS data set */
data mydata;
input Item $1-19 Value weight Volume;
datalines;
panacea (vials of) 3000 0.3 0.025
ichor (ampules of) 1800 0.2 0.015
gold (bars) 2500 2.0 0.002
;
/* call OPTMODEL procedure in SAS/OR */
proc optmodel;
/* declare sets and parameters, and read input data */
set <str> ITEMS;
num value {ITEMS};
num weight {ITEMS};
num volume {ITEMS};
read data mydata into ITEMS=[item] value weight volume;
/* declare variables, objective, and constraints */
var NumSelected {ITEMS} >= 0 integer;
max TotalValue = sum {i in ITEMS} value[i] * NumSelected[i];
con WeightCon:
sum {i in ITEMS} weight[i] * NumSelected[i] <= 25;
con VolumeCon:
sum {i in ITEMS} volume[i] * NumSelected[i] <= 0.25;
/* call mixed integer linear programming (MILP) solver */
solve;
/* print optimal solution */
print TotalValue;
print NumSelected;
/* to get all optimal solutions, call CLP solver instead */
solve with CLP / findallsolns;
/* print all optimal solutions */
print TotalValue;
for {s in 1.._NSOL_} print {i in ITEMS} NumSelected[i].sol[s];
quit;

View file

@ -0,0 +1,42 @@
import scala.annotation.tailrec
case class Item(name: String, value: Int, weight: Double, volume: Double)
val items = List(
Item("panacea", 3000, 0.3, 0.025),
Item("ichor", 1800, 0.2, 0.015),
Item("gold", 2500, 2.0, 0.002))
val (maxWeight, maxVolume) = (25, 0.25)
def show(is: List[Item]) =
(items.map(_.name) zip items.map(i => is.count(_ == i))).map {
case (i, c) => s"$i: $c"
}.mkString(", ")
case class Knapsack(items: List[Item]) {
def value = items.foldLeft(0)(_ + _.value)
def weight = items.foldLeft(0.0)(_ + _.weight)
def volume = items.foldLeft(0.0)(_ + _.volume)
def isFull = !((weight <= maxWeight) && (volume <= maxVolume))
override def toString =
s"[${show(items)} | value: $value, weight: $weight, volume: $volume]"
}
def fill(knapsack: Knapsack): List[Knapsack] =
items.map(i => Knapsack(i :: knapsack.items))
//cause brute force
def distinct(list: List[Knapsack]) =
list.map(k => Knapsack(k.items.sortBy(_.name))).distinct
@tailrec
def f(notPacked: List[Knapsack], packed: List[Knapsack]): List[Knapsack] =
notPacked match {
case Nil => packed.sortBy(_.value).takeRight(4)
case _ =>
val notFull = distinct(notPacked.flatMap(fill)).filterNot(_.isFull)
f(notFull, notPacked ::: packed)
}
f(items.map(i => Knapsack(List(i))), Nil).foreach(println)