Добавил:
lovickaaolesa
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:5 курс / lab3
.pyimport time
from typing import List, Tuple, Dict
class Item:
def __init__(self, name: str, weight: float, value: float):
self.name = name
self.weight = weight
self.value = value
def __str__(self):
return f"{self.name} (вес: {self.weight}, ценность: {self.value})"
def __repr__(self):
return self.__str__()
@property
def value_per_weight(self):
return self.value / self.weight if self.weight > 0 else 0
class Knapsack:
def __init__(self, max_weight: float = 10.0):
self.max_weight = max_weight
self.current_weight = 0.0
self.items = []
self.total_value = 0.0
def add_item(self, item: Item):
if self.current_weight + item.weight <= self.max_weight:
self.items.append(item)
self.current_weight += item.weight
self.total_value += item.value
return True
return False
def clear(self):
self.items = []
self.current_weight = 0.0
self.total_value = 0.0
def __str__(self):
return (f"Рюкзак (макс. вес: {self.max_weight}, текущий вес: {self.current_weight:.2f}, "
f"стоимость: {self.total_value:.2f})\nПредметы: {self.items}")
class KnapsackSolver:
def __init__(self, items: List[Item]):
self.items = items
self.n = len(items)
def recursive_solve(self, capacity: float) -> Tuple[List[Item], float]:
def rec(i: int, w: float):
if i == 0 or w == 0:
return 0, []
if self.items[i - 1].weight > w:
return rec(i - 1, w)
value_with, items_with = rec(i - 1, w - self.items[i - 1].weight)
value_with += self.items[i - 1].value
value_without, items_without = rec(i - 1, w)
if value_with > value_without:
return value_with, items_with + [self.items[i - 1]]
else:
return value_without, items_without
max_value, selected_items = rec(self.n, capacity)
return selected_items, max_value
def dp_solve(self, capacity: float) -> Tuple[List[Item], float]:
dp = [[0] * (int(capacity) + 1) for _ in range(self.n + 1)]
for i in range(1, self.n + 1):
for w in range(1, int(capacity) + 1):
if self.items[i - 1].weight <= w:
dp[i][w] = max(dp[i - 1][w],
dp[i - 1][w - int(self.items[i - 1].weight)] + self.items[i - 1].value)
else:
dp[i][w] = dp[i - 1][w]
max_value = dp[self.n][int(capacity)]
selected_items = []
w = int(capacity)
for i in range(self.n, 0, -1):
if dp[i][w] != dp[i - 1][w]:
selected_items.append(self.items[i - 1])
w -= int(self.items[i - 1].weight)
selected_items.reverse()
return selected_items, max_value
def greedy_solve_by_weight(self, capacity: float) -> Tuple[List[Item], float]:
sorted_items = sorted(self.items, key=lambda x: x.weight, reverse=True)
knapsack = Knapsack(capacity)
for item in sorted_items:
knapsack.add_item(item)
return knapsack.items, knapsack.total_value
def greedy_solve_by_value_per_weight(self, capacity: float) -> Tuple[List[Item], float]:
sorted_items = sorted(self.items, key=lambda x: x.value_per_weight, reverse=True)
knapsack = Knapsack(capacity)
for item in sorted_items:
knapsack.add_item(item)
return knapsack.items, knapsack.total_value
class KnapsackApp:
def __init__(self):
self.items = []
self.knapsack = Knapsack()
self.solver = None
self.results = {}
def load_from_file(self, filename: str):
try:
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
if line.strip():
parts = line.strip().split(',')
if len(parts) >= 3:
name = parts[0].strip()
weight = float(parts[1].strip())
value = float(parts[2].strip())
self.items.append(Item(name, weight, value))
print(f"Загружено {len(self.items)} предметов")
self.solver = KnapsackSolver(self.items)
except FileNotFoundError:
print(f"Файл {filename} не найден")
except Exception as e:
print(f"Ошибка при загрузке файла: {e}")
def add_item(self):
name = input("Введите название предмета: ")
try:
weight = float(input("Введите вес предмета: "))
value = float(input("Введите ценность предмета: "))
self.items.append(Item(name, weight, value))
self.solver = KnapsackSolver(self.items)
print("Предмет добавлен")
except ValueError:
print("Ошибка: введите корректные числа")
def edit_item(self):
self.show_items()
try:
index = int(input("Введите индекс предмета для редактирования: ")) - 1
if 0 <= index < len(self.items):
item = self.items[index]
print(f"Редактирование: {item}")
name = input(f"Название [{item.name}]: ") or item.name
weight = input(f"Вес [{item.weight}]: ")
weight = float(weight) if weight else item.weight
value = input(f"Ценность [{item.value}]: ")
value = float(value) if value else item.value
self.items[index] = Item(name, weight, value)
self.solver = KnapsackSolver(self.items)
print("Предмет изменен")
else:
print("Неверный индекс")
except ValueError:
print("Ошибка: введите корректный индекс")
def delete_item(self):
self.show_items()
try:
index = int(input("Введите индекс предмета для удаления: ")) - 1
if 0 <= index < len(self.items):
removed = self.items.pop(index)
self.solver = KnapsackSolver(self.items)
print(f"Удален предмет: {removed}")
else:
print("Неверный индекс")
except ValueError:
print("Ошибка: введите корректный индекс")
def set_max_weight(self):
try:
weight = float(input("Введите максимальный вес рюкзака: "))
if weight > 0:
self.knapsack.max_weight = weight
print(f"Максимальный вес установлен: {weight}")
else:
print("Вес должен быть положительным")
except ValueError:
print("Ошибка: введите корректное число")
def show_knapsack(self):
print("\n" + "=" * 50)
print("СОДЕРЖИМОЕ РЮКЗАКА")
print("=" * 50)
print(self.knapsack)
print("=" * 50)
def show_items(self):
print("\n" + "=" * 50)
print("СПИСОК ПРЕДМЕТОВ")
print("=" * 50)
for i, item in enumerate(self.items, 1):
print(f"{i}. {item}")
print("=" * 50)
def solve_problem(self):
if not self.items:
print("Сначала добавьте предметы")
return
print("\nВыберите метод решения:")
print("1. Рекурсивный метод")
print("2. Метод динамического программирования")
print("3. Жадный алгоритм (по максимальному весу)")
print("4. Жадный алгоритм (по максимальному соотношению цена/вес)")
try:
choice = int(input("Ваш выбор: "))
self.knapsack.clear()
start_time = time.time()
if choice == 1:
items, value = self.solver.recursive_solve(self.knapsack.max_weight)
method_name = "Рекурсивный метод"
elif choice == 2:
items, value = self.solver.dp_solve(self.knapsack.max_weight)
method_name = "ДП метод"
elif choice == 3:
items, value = self.solver.greedy_solve_by_weight(self.knapsack.max_weight)
method_name = "Жадный (по весу)"
elif choice == 4:
items, value = self.solver.greedy_solve_by_value_per_weight(self.knapsack.max_weight)
method_name = "Жадный (цена/вес)"
else:
print("Неверный выбор")
return
end_time = time.time()
execution_time = end_time - start_time
for item in items:
self.knapsack.add_item(item)
self.results[method_name] = {
'value': value,
'time': execution_time,
'items': len(items),
'weight': sum(item.weight for item in items)
}
print(f"\nРезультат ({method_name}):")
print(f"Стоимость: {value:.2f}")
print(f"Время выполнения: {execution_time:.6f} сек")
print(f"Количество предметов: {len(items)}")
self.show_knapsack()
except ValueError:
print("Ошибка: введите число от 1 до 4")
def compare_methods(self):
if not self.items:
print("Сначала добавьте предметы")
return
print("\n" + "=" * 80)
print("СРАВНЕНИЕ МЕТОДОВ")
print("=" * 80)
methods = [
("Рекурсивный", self.solver.recursive_solve),
("ДП", self.solver.dp_solve),
("Жадный (вес)", self.solver.greedy_solve_by_weight),
("Жадный (цена/вес)", self.solver.greedy_solve_by_value_per_weight)
]
results = {}
for name, method in methods:
start_time = time.time()
items, value = method(self.knapsack.max_weight)
end_time = time.time()
results[name] = {
'value': value,
'time': end_time - start_time,
'items': len(items),
'weight': sum(item.weight for item in items)
}
print(f"{'Метод':<20} {'Стоимость':<12} {'Время (сек)':<15} {'Предметы':<10} {'Вес':<10}")
print("-" * 80)
for name, data in results.items():
print(f"{name:<20} {data['value']:<12.2f} {data['time']:<15.6f} "
f"{data['items']:<10} {data['weight']:<10.2f}")
best_by_value = max(results.items(), key=lambda x: x[1]['value'])
print(f"\nЛучший метод по стоимости: {best_by_value[0]} ({best_by_value[1]['value']:.2f})")
fastest = min(results.items(), key=lambda x: x[1]['time'])
print(f"Самый быстрый метод: {fastest[0]} ({fastest[1]['time']:.6f} сек)")
print("=" * 80)
def run(self):
while True:
print("\n" + "=" * 50)
print("МЕНЮ")
print("=" * 50)
print("1. Загрузить предметы из файла")
print("2. Добавить предмет")
print("3. Изменить предмет")
print("4. Удалить предмет")
print("5. Задать максимальный вес рюкзака")
print("6. Просмотреть содержимое рюкзака")
print("7. Выбрать способ решения")
print("8. Сравнить способы решения")
print("9. Показать все предметы")
print("0. Выход")
print("=" * 50)
choice = input("Ваш выбор: ")
if choice == '1':
filename = input("Введите имя файла: ")
self.load_from_file(filename)
elif choice == '2':
self.add_item()
elif choice == '3':
self.edit_item()
elif choice == '4':
self.delete_item()
elif choice == '5':
self.set_max_weight()
elif choice == '6':
self.show_knapsack()
elif choice == '7':
self.solve_problem()
elif choice == '8':
self.compare_methods()
elif choice == '9':
self.show_items()
elif choice == '0':
print("Выход из программы")
break
else:
print("Неверный выбор")
def create_sample_file(filename: str = "items.txt"):
sample_data = """ноутбук, 2.5, 500
книга, 1.0, 50
кошелек, 0.3, 100
фонарик, 0.5, 30
вода, 1.5, 10
аптечка, 1.2, 80
куртка, 1.8, 150
еда, 1.0, 40
планшет, 1.0, 300
палатка, 3.0, 200"""
with open(filename, 'w', encoding='utf-8') as f:
f.write(sample_data)
print(f"Создан пример файла {filename}")
if __name__ == "__main__":
create_sample_file("items.txt")
app = KnapsackApp()
app.run()
Соседние файлы в папке 5 курс
