September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -71,5 +71,6 @@ Show how many of each item does he take to maximize the value of items he is car
|
|||
|
||||
;Related tasks:
|
||||
* [[Knapsack problem/Bounded]]
|
||||
* [[Knapsack problem/Continuous]]
|
||||
* [[Knapsack problem/0-1]]
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
* Knapsack problem/Unbounded 04/02/2017
|
||||
KNAPSACK CSECT
|
||||
USING KNAPSACK,R13 base register
|
||||
B 72(R15) skip savearea
|
||||
DC 17F'0' savearea
|
||||
STM R14,R12,12(R13) prolog
|
||||
ST R13,4(R15) " <-
|
||||
ST R15,8(R13) " ->
|
||||
LR R13,R15 " addressability
|
||||
MVC S,=F'0' s(1,kva)=0;
|
||||
LA R11,0 ns=0
|
||||
LA R1,KW kw
|
||||
SLA R1,2 *4
|
||||
L R2,PANACEA-4(R1) panacea(kw)
|
||||
L R4,SACKW sackw
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 sackw/panacea(kw)
|
||||
ST R5,XP xp=sackw/panacea(kw)
|
||||
LA R1,KV kv
|
||||
SLA R1,2 *4
|
||||
L R2,PANACEA-4(R1) panacea(kv)
|
||||
L R4,SACKV sackv
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 r5=sackv/panacea(kv)
|
||||
C R5,XP if r5<xp
|
||||
BNL EMINXP
|
||||
ST R5,XP xp=min(sackw/panacea(kw),sackv/panacea(kv))
|
||||
EMINXP LA R1,KW kw
|
||||
SLA R1,2 *4
|
||||
L R2,ICHOR-4(R1) ichor(kw)
|
||||
L R4,SACKW sackw
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 sackw/ichor(kw)
|
||||
ST R5,XI xi=sackw/ichor(kw)
|
||||
LA R1,KV kv
|
||||
SLA R1,2 *4
|
||||
L R2,ICHOR-4(R1) ichor(kv)
|
||||
L R4,SACKV sackv
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 r5=sackv/ichor(kv)
|
||||
C R5,XI if r5<xi
|
||||
BNL EMINXI
|
||||
ST R5,XI xi=min(sackw/ichor(kw),sackv/ichor(kv))
|
||||
EMINXI LA R1,KW kw
|
||||
SLA R1,2 *4
|
||||
L R2,GOLD-4(R1) gold(kw)
|
||||
L R4,SACKW sackw
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 sackw/gold(kw)
|
||||
ST R5,XG xg=sackw/gold(kw)
|
||||
LA R1,KV kv
|
||||
SLA R1,2 *4
|
||||
L R2,GOLD-4(R1) gold(kv)
|
||||
L R4,SACKV sackv
|
||||
SRDA R4,32 ~
|
||||
DR R4,R2 r5=sackv/gold(kv)
|
||||
C R5,XG if r5<xg
|
||||
BNL EMINXG
|
||||
ST R5,XG xg=min(sackw/gold(kw),sackv/gold(kv))
|
||||
EMINXG SR R10,R10 ip=0
|
||||
LOOPIP C R10,XP do ip=0 to xp
|
||||
BH ELOOPIP
|
||||
SR R9,R9 ii=0
|
||||
LOOPII C R9,XI do ii=0 to xi
|
||||
BH ELOOPII
|
||||
SR R8,R8 ig=0
|
||||
LOOPIG C R8,XG do ig=0 to xg
|
||||
BH ELOOPIG
|
||||
LA R7,KVA m=kva
|
||||
LOOPM C R7,=A(KV) do m=kva to kv
|
||||
BH ELOOPM
|
||||
LR R1,R7 m
|
||||
SLA R1,2 *4
|
||||
LR R5,R8 ig
|
||||
M R4,GOLD-4(R1) *gold(m)
|
||||
LR R2,R5 r2=ig*gold(m)
|
||||
LR R5,R9 ii
|
||||
M R4,ICHOR-4(R1) *ichor(m)
|
||||
AR R2,R5 r2=ig*gold(m)+ii*ichor(m)
|
||||
LR R5,R10 ip
|
||||
M R4,PANACEA-4(R1) *panacea(m)
|
||||
AR R2,R5 r2=r2+ip*panacea(m)
|
||||
ST R2,CUR-4(R1) cur(m)=r2
|
||||
LA R7,1(R7) m=m+1
|
||||
B LOOPM
|
||||
ELOOPM LA R1,KVA kva
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kva)
|
||||
C R2,S-4(R1) if cur(kva)>=s(1,kva)
|
||||
BL ENDIF
|
||||
LA R1,KW kw
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kw)
|
||||
C R2,SACKW if cur(kw)<=sackw
|
||||
BH ENDIF
|
||||
LA R1,KV kv
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kv)
|
||||
C R2,SACKV if cur(kv)<=sackv
|
||||
BH ENDIF
|
||||
LR R6,R11 j=ns
|
||||
LOOPJ C R6,=F'1' do j=ns to 1 by -1
|
||||
BL ELOOPJ
|
||||
LR R1,R6 j
|
||||
MH R1,=H'24' *24
|
||||
LA R2,S(R1) s(j+1,1)
|
||||
LA R3,S-24(R1) s(j,1)
|
||||
MVC 0(24,R2),0(R3) s(j+1,*)=s(j,*)
|
||||
BCTR R6,0 j=j-1
|
||||
B LOOPJ
|
||||
ELOOPJ LA R1,KVA kva
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kva)
|
||||
ST R2,S-4(R1) s(1,kva)=cur(kva)
|
||||
LA R1,KW kw
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kw)
|
||||
ST R2,S-4(R1) s(1,kw)=cur(kw)
|
||||
LA R1,KV kv
|
||||
SLA R1,2 *4
|
||||
L R2,CUR-4(R1) cur(kv)
|
||||
ST R2,S-4(R1) s(1,kv)=cur(kv)
|
||||
LA R1,KP kp
|
||||
SLA R1,2 *4
|
||||
ST R10,S-4(R1) s(1,kp)=ip
|
||||
LA R1,KI ki
|
||||
SLA R1,2 *4
|
||||
ST R9,S-4(R1) s(1,ki)=ii
|
||||
LA R1,KG kg
|
||||
SLA R1,2 *4
|
||||
ST R8,S-4(R1) s(1,kg)=ig
|
||||
L R2,S r2=s(1,1)
|
||||
C R2,S+24 if s(1,1)>s(2,1)
|
||||
BNH ELSE
|
||||
LA R11,1 ns=1
|
||||
B ENDIF
|
||||
ELSE LA R11,1(R11) ns+1
|
||||
ENDIF LA R8,1(R8) ig=ig+1
|
||||
B LOOPIG
|
||||
ELOOPIG LA R9,1(R9) ii=ii+1
|
||||
B LOOPII
|
||||
ELOOPII LA R10,1(R10) ip=ip+1
|
||||
B LOOPIP
|
||||
ELOOPIP XPRNT TITLE,72
|
||||
LA R6,1 j=1
|
||||
LA R3,S-4 r3=@item
|
||||
LOOPJP CR R6,R11 do j=1 to ns
|
||||
BH ELOOPJP
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,kva)
|
||||
XDECO R1,PG edit
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,kw)
|
||||
XDECO R1,PG+12 edit
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,kv)
|
||||
XDECO R1,PG+24 edit
|
||||
MVC PG+20(2),PG+21 shift
|
||||
MVI PG+22,C'.' decimal point
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,kp)
|
||||
XDECO R1,PG+36 edit
|
||||
MVC PG+31(2),=C'0.' decimal point
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,ki)
|
||||
XDECO R1,PG+48 edit
|
||||
LA R3,4(R3) ++
|
||||
L R1,0(R3) s(j,kg)
|
||||
XDECO R1,PG+60 edit
|
||||
XPRNT PG,L'PG print buffer
|
||||
LA R6,1(R6) j=j+1
|
||||
B LOOPJP
|
||||
ELOOPJP L R13,4(0,R13) epilog
|
||||
LM R14,R12,12(R13) " restore
|
||||
XR R15,R15 " rc=0
|
||||
BR R14 exit
|
||||
KVA EQU 1
|
||||
KW EQU 2
|
||||
KV EQU 3
|
||||
KP EQU 4
|
||||
KI EQU 5
|
||||
KG EQU 6
|
||||
SACKW DC F'250'
|
||||
SACKV DC F'250'
|
||||
PANACEA DC F'3000',F'3',F'25'
|
||||
ICHOR DC F'1800',F'2',F'15'
|
||||
GOLD DC F'2500',F'20',F'2'
|
||||
XP DS F
|
||||
XI DS F
|
||||
XG DS F
|
||||
CUR DS 3F
|
||||
S DS 60F
|
||||
TITLE DC CL36' Value Weight Volume'
|
||||
DC CL36' Panacea Ichor Gold'
|
||||
PG DS CL72
|
||||
YREGS
|
||||
END KNAPSACK
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
defmodule Item do
|
||||
defstruct volume: 0.0, weight: 0.0, value: 0
|
||||
def new(volume, weight, value) do
|
||||
%__MODULE__{volume: volume, weight: weight, value: value}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Knapsack do
|
||||
def solve_unbounded(items, maximum) do
|
||||
{max_volume, max_weight} = {maximum.volume, maximum.weight}
|
||||
max_items = Enum.map(items, fn {name,item} ->
|
||||
{name, trunc(min(max_volume / item.volume, max_weight / item.weight))}
|
||||
end)
|
||||
Enum.map(max_items, fn {name,max} -> for i <- 0..max, do: {name,i} end)
|
||||
|> product
|
||||
|> total(items)
|
||||
|> Enum.filter(fn {_kw, {volume,weight,_}} -> volume <= max_volume and
|
||||
weight <= max_weight end)
|
||||
|> Enum.group_by(fn {_kw, {_,_,value}} -> value end)
|
||||
|> Enum.max
|
||||
|> print
|
||||
end
|
||||
|
||||
defp product([x]), do: x
|
||||
defp product([a,b]), do: for x <- a, y <- b, do: [x,y]
|
||||
defp product([h|t]), do: for x <- h, y <- product(t), do: [x | y]
|
||||
|
||||
defp total(lists, items) do
|
||||
Enum.map(lists, fn kwlist ->
|
||||
total = Enum.reduce(kwlist, {0,0,0}, fn {name,n},{volume,weight,value} ->
|
||||
{volume + n * items[name].volume,
|
||||
weight + n * items[name].weight,
|
||||
value + n * items[name].value}
|
||||
end)
|
||||
{kwlist, total}
|
||||
end)
|
||||
end
|
||||
|
||||
defp print({max_value, data}) do
|
||||
IO.puts "Maximum value achievable is #{max_value}\tvolume weight value"
|
||||
Enum.each(data, fn {kw,{volume,weight,value}} ->
|
||||
:io.format "~s =>\t~6.3f, ~5.1f, ~6w~n", [(inspect kw), volume, weight, value]
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
items = %{panacea: Item.new(0.025, 0.3, 3000),
|
||||
ichor: Item.new(0.015, 0.2, 1800),
|
||||
gold: Item.new(0.002, 2.0, 2500) }
|
||||
maximum = Item.new(0.25, 25, 0)
|
||||
Knapsack.solve_unbounded(items, maximum)
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// version 1.1.2
|
||||
|
||||
data class Item(val name: String, val value: Double, val weight: Double, val volume: Double)
|
||||
|
||||
val items = listOf(
|
||||
Item("panacea", 3000.0, 0.3, 0.025),
|
||||
Item("ichor", 1800.0, 0.2, 0.015),
|
||||
Item("gold", 2500.0, 2.0, 0.002)
|
||||
)
|
||||
|
||||
val n = items.size
|
||||
val count = IntArray(n)
|
||||
val best = IntArray(n)
|
||||
var bestValue = 0.0
|
||||
|
||||
const val MAX_WEIGHT = 25.0
|
||||
const val MAX_VOLUME = 0.25
|
||||
|
||||
fun knapsack(i: Int, value: Double, weight: Double, volume: Double) {
|
||||
if (i == n) {
|
||||
if (value > bestValue) {
|
||||
bestValue = value
|
||||
for (j in 0 until n) best[j] = count[j]
|
||||
}
|
||||
return
|
||||
}
|
||||
val m1 = Math.floor(weight / items[i].weight).toInt()
|
||||
val m2 = Math.floor(volume / items[i].volume).toInt()
|
||||
val m = minOf(m1, m2)
|
||||
count[i] = m
|
||||
while (count[i] >= 0) {
|
||||
knapsack(
|
||||
i + 1,
|
||||
value + count[i] * items[i].value,
|
||||
weight - count[i] * items[i].weight,
|
||||
volume - count[i] * items[i].volume
|
||||
)
|
||||
count[i]--
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
knapsack(0, 0.0, MAX_WEIGHT, MAX_VOLUME)
|
||||
println("Item Chosen Number Value Weight Volume")
|
||||
println("----------- ------ ----- ------ ------")
|
||||
var itemCount = 0
|
||||
var sumNumber = 0
|
||||
var sumWeight = 0.0
|
||||
var sumVolume = 0.0
|
||||
for (i in 0 until n) {
|
||||
if (best[i] == 0) continue
|
||||
itemCount++
|
||||
val name = items[i].name
|
||||
val number = best[i]
|
||||
val value = items[i].value * number
|
||||
val weight = items[i].weight * number
|
||||
val volume = items[i].volume * number
|
||||
sumNumber += number
|
||||
sumWeight += weight
|
||||
sumVolume += volume
|
||||
print("${name.padEnd(11)} ${"%2d".format(number)} ${"%5.0f".format(value)} ${"%4.1f".format(weight)}")
|
||||
println(" ${"%4.2f".format(volume)}")
|
||||
}
|
||||
println("----------- ------ ----- ------ ------")
|
||||
print("${itemCount} items ${"%2d".format(sumNumber)} ${"%5.0f".format(bestValue)} ${"%4.1f".format(sumWeight)}")
|
||||
println(" ${"%4.2f".format(sumVolume)}")
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
--
|
||||
-- demo\rosetta\knapsack.exw
|
||||
-- =========================
|
||||
--
|
||||
integer attempts = 0
|
||||
function knapsack(sequence res, goodies, atom profit, weight, volume, at=1, sequence chosen={})
|
||||
atom {pitem,witem,vitem} = goodies[at][2]
|
||||
integer n = min(floor(weight/witem),floor(volume/vitem))
|
||||
chosen &= n
|
||||
profit += n*pitem -- increase profit
|
||||
weight -= n*witem -- decrease weight left
|
||||
volume -= n*vitem -- decrease space left
|
||||
if at=length(goodies) then
|
||||
attempts += 1
|
||||
if length(res)=0
|
||||
or res<{profit,weight,volume} then
|
||||
res = {profit,weight,volume,chosen}
|
||||
end if
|
||||
else
|
||||
while n>=0 do
|
||||
res = knapsack(res,goodies,profit,weight,volume,at+1,chosen)
|
||||
n -= 1
|
||||
chosen[$] = n
|
||||
profit -= pitem
|
||||
weight += witem
|
||||
volume += vitem
|
||||
end while
|
||||
end if
|
||||
return res
|
||||
end function
|
||||
|
||||
constant goodies = {
|
||||
-- item profit weight volume
|
||||
{"panacea", {3000, 0.3, 0.025}},
|
||||
{"ichor", {1800, 0.2, 0.015}},
|
||||
{"shiney shiney",{2500, 2.0, 0.002}}}
|
||||
|
||||
sequence res -- {profit,(weight left),(space left),{counts}}
|
||||
res = knapsack({},goodies,0,25,0.25)
|
||||
integer {p,i,g} = res[4]
|
||||
sequence {d,pwv} = columnize(goodies),
|
||||
{?,w,v} = columnize(pwv)
|
||||
atom weight = sum(sq_mul(res[4],w)),
|
||||
volume = sum(sq_mul(res[4],v))
|
||||
printf(1,"Profit %d: %d %s, %d %s, %d %s\n",
|
||||
{res[1],p,d[1],i,d[2],g,d[3]})
|
||||
printf(1," [weight:%g, volume:%g, %d attempts]\n",
|
||||
{weight,volume,attempts})
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
panacea:=T(3000, 0.3, 0.025); // (value,weight,volume)
|
||||
ichor :=T(1800, 0.2, 0.015);
|
||||
gold :=T(2500, 2.0, 0.002);
|
||||
sack :=T( 0, 25.0, 0.250); const VAL=0, W=1, VOL=2;
|
||||
|
||||
maxes:=T(panacea,ichor,gold)
|
||||
.apply('wrap(t){ (sack[W]/t[W]).min(sack[VOL]/t[VOL]).toInt().walker() });
|
||||
best:=Utils.Helpers.cprod3(maxes.xplode())
|
||||
.apply('wrap(t){
|
||||
T(T(panacea[VAL]*t[0] + ichor[VAL]*t[1] + gold[VAL]*t[2],
|
||||
panacea[W] *t[0] + ichor[W] *t[1] + gold[W] *t[2],
|
||||
panacea[VOL]*t[0] + ichor[VOL]*t[1] + gold[VOL]*t[2]), t)
|
||||
})
|
||||
.filter('wrap(t){ t[0][W]<=sack[W] and t[0][VOL]<=sack[VOL] })
|
||||
.reduce(fcn(a,b){ a[0][VAL] > b[0][VAL] and a or b });
|
||||
|
||||
println("Maximum value achievable is %,d".fmt(best[0][VAL]));
|
||||
println(("This is achieved by carrying (one solution):"
|
||||
" %d panacea, %d ichor and %d gold").fmt(best[1].xplode()));
|
||||
println("The weight to carry is %4.1f and the volume used is %5.3f"
|
||||
.fmt(best[0][1,*].xplode()));
|
||||
Loading…
Add table
Add a link
Reference in a new issue