# %load CLP_pokrivanje.sage
#!/usr/bin/env python
from __future__ import print_function
import json
import six
import sys
import time
if six.PY2:
FileNotFoundError = IOError
json.JSONDecodeError = ValueError
DATOTEKA = 'pokrivanje.json'
def pokrivanje(n, r=1):
meja = floor(sqrt((n * (n + 1) * (2*n + 1)) / (r * 6)))
p = MixedIntegerLinearProgram(maximization=True)
w = p.new_variable(binary=True)
y = p.new_variable(binary=True)
z = p.new_variable(binary=True)
p.set_objective(sum(z[l] for l in range(1, meja + 1))) ##ciljna funkcija
p.add_constraint(z[0] == 1) ## robni pogoj, kvadrat velikosti 0 lahko vedno pokrijemo
for i in range(1, n + 1):
p.add_constraint(sum(w[i,u,v] for u in range(1, meja + 1) for v in range(1, meja + 1)) == 1) ##pogoj, da imamo največ en kvadrat dolžine i
for j in range(1, meja + 1):
for k in range(1, meja + 1):
p.add_constraint(r*y[j,k] <= sum(w[i,u,v] ## pogoj, da je kvadratek (j,k) pokrit vsaj r-krat
for i in range(1, n + 1)
for u in range(max(1, j - i + 1), j + 1)
for v in range(max(1, k - i + 1), k + 1)))
for l in range(1, meja + 1):
p.add_constraint(2*l*z[l] <= (z[l-1] + y[l,l] + sum((y[m,l] +y[l,m]) for m in range(1, l)))) ## pogoj, da je kvadrat lxl pokrit
t = p.solve() ##vrne velikost največjega kvadrata, ki ga dobimo s pokrivanjem.
resw = p.get_values(w)
resy = p.get_values(y)
resz = p.get_values(z)
kvadratki = []
for (x,y) in resy.items():
if y == 1:
kvadratki.append(x)
KVADRATI = []
for (x,y) in resw.items():
if y == 1:
KVADRATI.append(x)
return (t, KVADRATI) ## vrne izhodišča kvadratov v optimalni rešitvi
def pozeni(n, r=1, podatki=None, datoteka=DATOTEKA):
if podatki is None:
podatki = {}
print("pokrivanje(%d, %d)" % (n, r), end=" ")
sys.stdout.flush()
start = time.time()
t, kvadrati = pokrivanje(n, r)
end = time.time()
cas = end-start
print("-> %d, cas = %.2f" % (t, cas))
podatki[n, r] = (t, kvadrati, cas)
with open(datoteka, "w") as f:
json.dump([{"n": int(nn), "r": int(rr), "velikost": int(t), "kvadrati": kv, "cas": c}
for (nn, rr), (t, kv, c) in sorted(podatki.items())], f, indent=4)
def preberi_podatke(datoteka=DATOTEKA):
try:
with open(datoteka) as f:
podatki = {(d["n"], d["r"]): (d["velikost"], d["kvadrati"], d["cas"]) for d in json.load(f)}
except (FileNotFoundError, json.JSONDecodeError):
print("Branje ni uspelo, začenjam znova")
podatki = {}
return podatki
# %load poganjanje.sage
#!/usr/bin/env python
datoteka = 'pokrivanje.json'
podatki = preberi_podatke(datoteka)
for n in range(1, 6):
for r in range(n, 0, -1):
pozeni(n, r, podatki=podatki, datoteka=datoteka)
pokrivanje(1, 1) -> 1, cas = 0.04 pokrivanje(2, 2) -> 1, cas = 0.00 pokrivanje(2, 1) -> 2, cas = 0.00 pokrivanje(3, 3) -> 1, cas = 0.00 pokrivanje(3, 2) -> 2, cas = 0.00 pokrivanje(3, 1) -> 3, cas = 0.00 pokrivanje(4, 4) -> 1, cas = 0.00 pokrivanje(4, 3) -> 2, cas = 0.00 pokrivanje(4, 2) -> 3, cas = 0.00 pokrivanje(4, 1) -> 4, cas = 0.01 pokrivanje(5, 5) -> 1, cas = 0.00 pokrivanje(5, 4) -> 2, cas = 0.00 pokrivanje(5, 3) -> 3, cas = 0.01 pokrivanje(5, 2) -> 4, cas = 0.01 pokrivanje(5, 1) -> 6, cas = 0.28
velikost, kvadrati, cas = podatki[8, 4] # primer: podatki za n = 8, r = 4
(velikost, cas)
(6, 0.04350399971008301)
kvadrati
[[5, 1, 2], [4, 3, 1], [7, 1, 1], [3, 4, 4], [6, 1, 1], [2, 1, 1], [8, 1, 1], [1, 2, 7]]
podatki2 = preberi_podatke('pokrivanje2.json')
velikost2, kvadrati2, cas2 = podatki2[16, 3] # primer: podatki za n = 16, r = 3
(velikost2, cas2)
(21, 2302.75945186615)
kvadrati2
[[5, 17, 1], [14, 1, 1], [4, 18, 6], [7, 15, 1], [1, 17, 6], [9, 13, 1], [11, 11, 11], [15, 7, 7], [10, 1, 12], [2, 20, 10], [16, 1, 1], [13, 9, 10], [3, 17, 8], [12, 1, 1], [6, 1, 16], [8, 1, 15]]