168 lines
5.5 KiB
Python
168 lines
5.5 KiB
Python
import random
|
|
import time
|
|
import matplotlib.pyplot as plt
|
|
import sys
|
|
|
|
def greedy(n, weight, value, capacity ):
|
|
pairs = list(zip(value, weight))
|
|
pairs.sort(reverse=True, key=lambda x: x[0] / x[1])
|
|
|
|
current_value = 0
|
|
currentCapacity = capacity
|
|
|
|
for i in range(n):
|
|
if pairs[i][1] <= currentCapacity:
|
|
current_value += pairs[i][0]
|
|
currentCapacity -= pairs[i][1]
|
|
|
|
return current_value
|
|
|
|
def dynamic(n, weight, value, capacity, print_table=False):
|
|
table = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)]
|
|
|
|
for i in range(1, n + 1):
|
|
for w in range(capacity + 1):
|
|
if weight[i - 1] <= w:
|
|
table[i][w] = max(table[i - 1][w], table[i - 1][w - weight[i - 1]] + value[i - 1])
|
|
else:
|
|
table[i][w] = table[i - 1][w]
|
|
|
|
|
|
if print_table:
|
|
print("\n".join(["\t".join(map(str, row)) for row in table]))
|
|
return table[n][capacity]
|
|
|
|
def benchmark_containers(container_list, capacity):
|
|
greedy_times = []
|
|
dynamic_times = []
|
|
greedy_values = []
|
|
dynamic_values = []
|
|
rel_errors = []
|
|
|
|
# For each container number or capacity
|
|
for containers in container_list:
|
|
weights = [random.randint(1, 10) for _ in range(containers)]
|
|
values = [random.randint(1, 20) for _ in range(containers)]
|
|
|
|
# Dynamic
|
|
start = time.time()
|
|
dyn = dynamic(containers, weights, values, capacity)
|
|
dyn_time = (time.time() - start) * 1000
|
|
|
|
# Greedy
|
|
start = time.time()
|
|
gr = greedy(containers, weights, values, capacity)
|
|
gr_time = (time.time() - start) * 1000
|
|
|
|
greedy_times.append(gr_time)
|
|
dynamic_times.append(dyn_time)
|
|
greedy_values.append(gr)
|
|
dynamic_values.append(dyn)
|
|
|
|
print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%")
|
|
rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0)
|
|
|
|
return greedy_times, dynamic_times, rel_errors
|
|
|
|
def benchmark_capacity(capacity_list, containers):
|
|
greedy_times = []
|
|
dynamic_times = []
|
|
greedy_values = []
|
|
dynamic_values = []
|
|
rel_errors = []
|
|
|
|
# For each container number or capacity
|
|
for capacity in capacity_list:
|
|
weights = [random.randint(1, 10) for _ in range(containers)]
|
|
values = [random.randint(2, 20) for _ in range(containers)]
|
|
|
|
# Dynamic
|
|
start = time.time()
|
|
dyn = dynamic(containers, weights, values, capacity)
|
|
dyn_time = (time.time() - start) * 1000
|
|
|
|
# Greedy
|
|
start = time.time()
|
|
gr = greedy(containers, weights, values, capacity)
|
|
gr_time = (time.time() - start) * 1000
|
|
|
|
greedy_times.append(gr_time)
|
|
dynamic_times.append(dyn_time)
|
|
greedy_values.append(gr)
|
|
dynamic_values.append(dyn)
|
|
print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%")
|
|
|
|
rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0)
|
|
|
|
return greedy_times, dynamic_times, rel_errors
|
|
|
|
if __name__ == "__main__":
|
|
# Check if there was given a second argument, if yes run a test instead of the benchmark
|
|
if len(sys.argv) > 1:
|
|
file = sys.argv[1]
|
|
"""
|
|
Format we are expecting:
|
|
5 - liczba elementów
|
|
3 2 4 3 1 - rozmiary
|
|
5 3 4 4 2 - wartości
|
|
8 - rozmiar plecaka
|
|
"""
|
|
with open(file, 'r') as f:
|
|
lines = f.readlines()
|
|
n = int(lines[0].strip())
|
|
weights = list(map(int, lines[1].strip().split()))
|
|
values = list(map(int, lines[2].strip().split()))
|
|
capacity = int(lines[3].strip())
|
|
|
|
dynamic(n, weights, values, capacity, print_table=True)
|
|
print(greedy(n, weights, values, capacity))
|
|
exit(0)
|
|
|
|
# First test case - constant capacity, variable number of containers
|
|
containers_list = list(range(1, 51, 2))
|
|
|
|
# Constant capacity of 20
|
|
greedy_times, dynamic_times, rel_errors = benchmark_containers(containers_list, 20)
|
|
|
|
plt.figure(figsize=(12,5))
|
|
plt.subplot(1,2,1)
|
|
plt.plot(containers_list, greedy_times, label='Zachłanny', )
|
|
plt.plot(containers_list, dynamic_times, label='Dynamiczny', )
|
|
plt.xlabel('Liczba kontenerów')
|
|
plt.ylabel('Czas [ms]')
|
|
# plt.yscale('log', base=2)
|
|
plt.title('Czas działania dla zmiennej liczby kontenerów (B=20)')
|
|
plt.legend()
|
|
|
|
axis = plt.subplot(1,2,2)
|
|
plt.bar(containers_list, rel_errors)
|
|
plt.xlabel('Liczba kontenerów')
|
|
plt.ylabel('Błąd względny [%]')
|
|
axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', ''))
|
|
plt.title('Błąd względny')
|
|
plt.savefig('benchmark_vary_n.png')
|
|
|
|
|
|
# Second test case - variable capacity, constant number of containers
|
|
capacity_list = list(range(5, 101, 5))
|
|
|
|
# Constant number of containers of 50
|
|
greedy_times, dynamic_times, rel_errors = benchmark_capacity(capacity_list, 50)
|
|
|
|
plt.figure(figsize=(12,5))
|
|
plt.subplot(1,2,1)
|
|
plt.plot(capacity_list, greedy_times, label='Zachłanny' )
|
|
plt.plot(capacity_list, dynamic_times, label='Dynamiczny')
|
|
plt.xlabel('Pojemność')
|
|
plt.ylabel('Czas [ms]')
|
|
plt.title('Czas działania dla zmiennej pojemności (n=50)')
|
|
plt.legend()
|
|
|
|
axis = plt.subplot(1,2,2)
|
|
plt.bar(capacity_list, rel_errors )
|
|
plt.xlabel('Pojemność')
|
|
plt.ylabel('Błąd względny [%]')
|
|
axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', ''))
|
|
plt.title('Błąd względny')
|
|
plt.savefig('benchmark_vary_capacity.png')
|