September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -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>

View file

@ -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

View file

@ -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)

View file

@ -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)}")
}

View file

@ -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})

View file

@ -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()));