diff --git a/funkcje.py b/funkcje.py new file mode 100644 index 0000000..7e129a0 --- /dev/null +++ b/funkcje.py @@ -0,0 +1,11 @@ +def ograniczenie(lista, left_cap): + wynik = 0 + for item in lista: + new_cap = left_cap - item.waga + if new_cap <= 0: + temp = item.waga + new_cap + wynik += item.wartosc*(temp/item.waga) + break + else: + wynik += item.wartosc + return wynik diff --git a/item.py b/item.py index 169c96f..f28476f 100644 --- a/item.py +++ b/item.py @@ -5,6 +5,7 @@ class Item: def __init__(self): self._waga = random.randint(1, 6) self._wartosc = random.randint(5, 10) + self._ratio = self._wartosc/self._waga @property def waga(self): @@ -13,3 +14,7 @@ class Item: @property def wartosc(self): return self._wartosc + + @property + def ratio(self): + return self._ratio diff --git a/main.py b/main.py index 5459c72..47f1958 100644 --- a/main.py +++ b/main.py @@ -1,44 +1,94 @@ -from plecak import * +from item import * +from funkcje import ograniczenie -l = 10 -dostepne = [Item() for _ in range(l)] +liczba_itemow = 20 +dost = [] +for i in range(liczba_itemow): + item = Item() + ratio = item.ratio + dost.append((ratio, item)) -for x in dostepne: +r = [el[0] for el in dost] +r.sort(reverse=True) +dostepne_items = [] +for i in r: + for j in dost: + if i == j[0]: + dostepne_items.append(j[1]) + break + + +for x in dostepne_items: print(x.waga, x.wartosc) -cap = 25 +cap = 4 * liczba_itemow / 2 # te liczby tutaj są raczej przypadkowe i można je zmieniać, algorytm dalej powinien działać +alfa = liczba_itemow * 5 -def knapsack(dostepne, cap): - def rekurencja(i, waga, val, items, alfa): - nonlocal max_val, plecak +def knapsack(dostepne, cap, mode): - if i >= len(dostepne) or waga == cap: + def rekurencja(i, waga, val, items): + nonlocal max_val, plecak, actions + + actions += 1 + if i >= len(dostepne): if val > max_val: max_val = val plecak = items return - if val >= alfa: - plecak = items + if mode in [1, 2] and waga >= cap: # alfa cięcie return - rekurencja(i+1, waga, val, items, alfa) + if mode in [2] and max_val >= val + ograniczenie(dostepne[i:], cap-waga): # beta cięcie + return if waga + dostepne[i].waga <= cap: temp = items[:] temp.append(dostepne[i]) - rekurencja(i+1, waga + dostepne[i].waga, val + dostepne[i].wartosc, temp, alfa) + rekurencja(i+1, waga + dostepne[i].waga, val + dostepne[i].wartosc, temp) + + rekurencja(i+1, waga, val, items[:]) max_val = float("-inf") plecak = [] - rekurencja(0, 0, 0, [], 60) - return max_val, plecak + actions = 0 + rekurencja(0, 0, 0, []) + return plecak, actions -best, final = knapsack(dostepne, cap) +final0, actions0 = knapsack(dostepne_items, cap, 0) +final1, actions1 = knapsack(dostepne_items, cap, 1) +final2, actions2 = knapsack(dostepne_items, cap, 2) +total_w0 = 0 +best_val0 = 0 +total_w1 = 0 +best_val1 = 0 +total_w2 = 0 +best_val2 = 0 +for item in final0: + total_w0 += item.waga + best_val0 += item.wartosc -print("----------\n" + f'wartość plecaka: {best}') -for item in final: - print(item.waga, item.wartosc) +for item in final1: + total_w1 += item.waga + best_val1 += item.wartosc + +for item in final2: + total_w2 += item.waga + best_val2 += item.wartosc + +print("----------\n" + f'wartości plecaka: {best_val0} - {best_val1} - {best_val2}') +print(f"waga plecaka: {total_w0}/{int(cap)} - {total_w1}/{int(cap)} - {total_w2}/{int(cap)}") + +binar = '' +for item in dostepne_items: + binar += "1" if item in final0 else "0" + +print(binar) + +print("---------------") +print(f"Wierzchołki na surowo: {actions0}") +print(f"Wierzchołki z alfa cięciem: {actions1}") +print(f"Wierzchołki z alfabeta cięciem: {actions2}")