From 6b32c4297c4cc72607ad73ac89221783352591d3 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Wed, 31 May 2023 00:07:06 -0300 Subject: [PATCH 01/23] Add initial files --- TP2/archivos_prueba/env10.txt | 31 ++++++ TP2/archivos_prueba/env10b.txt | 30 ++++++ TP2/archivos_prueba/env10c.txt | 34 +++++++ TP2/archivos_prueba/env20.txt | 59 ++++++++++++ TP2/archivos_prueba/env3.txt | 15 +++ TP2/archivos_prueba/env40.txt | 113 ++++++++++++++++++++++ TP2/archivos_prueba/env60.txt | 169 +++++++++++++++++++++++++++++++++ TP2/main.py | 11 +++ 8 files changed, 462 insertions(+) create mode 100644 TP2/archivos_prueba/env10.txt create mode 100644 TP2/archivos_prueba/env10b.txt create mode 100644 TP2/archivos_prueba/env10c.txt create mode 100644 TP2/archivos_prueba/env20.txt create mode 100644 TP2/archivos_prueba/env3.txt create mode 100644 TP2/archivos_prueba/env40.txt create mode 100644 TP2/archivos_prueba/env60.txt create mode 100644 TP2/main.py diff --git a/TP2/archivos_prueba/env10.txt b/TP2/archivos_prueba/env10.txt new file mode 100644 index 0000000..df0fa9f --- /dev/null +++ b/TP2/archivos_prueba/env10.txt @@ -0,0 +1,31 @@ +29 + +0.02 +0.03 +0.135 +0.758 +0.011 +0.05 +0.077 +0.683 +0.939 +0.038 +0.165 +0.224 +0.152 +0.918 +0.049 +0.485 +0.551 +0.79 +0.69 +0.21 +0.097 +0.345 +0.655 +0.962 +0.291 +0.449 +0.164 +0.023 +0.039 diff --git a/TP2/archivos_prueba/env10b.txt b/TP2/archivos_prueba/env10b.txt new file mode 100644 index 0000000..b99c451 --- /dev/null +++ b/TP2/archivos_prueba/env10b.txt @@ -0,0 +1,30 @@ +28 + +0.401 +0.495 +0.002 +0.958 +0.306 +0.473 +0.149 +0.758 +0.694 +0.022 +0.312 +0.13 +0.042 +0.001 +0.164 +0.482 +0.905 +0.044 +0.073 +0.836 +0.02 +0.242 +0.22 +0.65 +0.095 +0.005 +0.526 +0.995 diff --git a/TP2/archivos_prueba/env10c.txt b/TP2/archivos_prueba/env10c.txt new file mode 100644 index 0000000..32d2f5d --- /dev/null +++ b/TP2/archivos_prueba/env10c.txt @@ -0,0 +1,34 @@ +32 + +0.069 +0.574 +0.781 +0.047 +0.219 +0.051 +0.76 +0.037 +0.931 +0.013 +0.04 +0.921 +0.008 +0.928 +0.114 +0.029 +0.414 +0.24 +0.004 +0.217 +0.012 +0.611 +0.007 +0.64 +0.025 +0.032 +0.67 +0.389 +0.211 +0.006 +0.036 +0.964 diff --git a/TP2/archivos_prueba/env20.txt b/TP2/archivos_prueba/env20.txt new file mode 100644 index 0000000..bc46b5e --- /dev/null +++ b/TP2/archivos_prueba/env20.txt @@ -0,0 +1,59 @@ +57 + +0.483 +0.209 +0.663 +0.311 +0.002 +0.769 +0.769 +0.745 +0.918 +0.512 +0.085 +0.136 +0.953 +0.407 +0.144 +0.337 +0.001 +0.488 +0.036 +0.101 +0.321 +0.709 +0.009 +0.591 +0.2 +0.959 +0.021 +0.221 +0.231 +0.253 +0.171 +0.291 +0.867 +0.12 +0.007 +0.105 +0.977 +0.026 +0.231 +0.384 +0.036 +0.001 +0.531 +0.034 +0.158 +0.88 +0.689 +0.445 +0.047 +0.611 +0.555 +0.337 +0.061 +0.004 +0.001 +0.842 +0.005 diff --git a/TP2/archivos_prueba/env3.txt b/TP2/archivos_prueba/env3.txt new file mode 100644 index 0000000..b9b4918 --- /dev/null +++ b/TP2/archivos_prueba/env3.txt @@ -0,0 +1,15 @@ +13 + +0.085 +0.006 +0.008 +0.024 +0.106 +0.357 +0.001 +0.915 +0.643 +0.255 +0.513 +0.039 +0.048 diff --git a/TP2/archivos_prueba/env40.txt b/TP2/archivos_prueba/env40.txt new file mode 100644 index 0000000..33e7141 --- /dev/null +++ b/TP2/archivos_prueba/env40.txt @@ -0,0 +1,113 @@ +111 + +0.129 +0.754 +0.631 +0.958 +0.678 +0.119 +0.81 +0.623 +0.6 +0.042 +0.246 +0.997 +0.714 +0.003 +0.026 +0.162 +0.128 +0.005 +0.014 +0.47 +0.909 +0.671 +0.144 +0.71 +0.008 +0.27 +0.535 +0.162 +0.762 +0.714 +0.627 +0.031 +0.001 +0.617 +0.387 +0.853 +0.032 +0.037 +0.264 +0.332 +0.29 +0.253 +0.012 +0.429 +0.241 +0.668 +0.416 +0.759 +0.045 +0.542 +0.322 +0.013 +0.944 +0.455 +0.339 +0.802 +0.072 +0.803 +0.009 +0.053 +0.021 +0.19 +0.946 +0.002 +0.329 +0.091 +0.24 +0.896 +0.052 +0.185 +0.909 +0.044 +0.05 +0.301 +0.465 +0.033 +0.383 +0.095 +0.274 +0.143 +0.002 +0.837 +0.147 +0.114 +0.026 +0.613 +0.837 +0.01 +0.076 +0.152 +0.005 +0.635 +0.091 +0.373 +0.435 +0.286 +0.026 +0.158 +0.661 +0.4 +0.736 +0.31 +0.942 +0.749 +0.699 +0.191 +0.006 +0.046 +0.116 +0.102 +0.928 diff --git a/TP2/archivos_prueba/env60.txt b/TP2/archivos_prueba/env60.txt new file mode 100644 index 0000000..bfd86a6 --- /dev/null +++ b/TP2/archivos_prueba/env60.txt @@ -0,0 +1,169 @@ +167 + +0.64 +0.096 +0.539 +0.294 +0.586 +0.021 +0.803 +0.978 +0.294 +0.647 +0.022 +0.04 +0.036 +0.267 +0.8 +0.881 +0.815 +0.01 +0.191 +0.026 +0.416 +0.403 +0.119 +0.051 +0.005 +0.952 +0.119 +0.385 +0.033 +0.283 +0.992 +0.916 +0.031 +0.043 +0.585 +0.604 +0.028 +0.36 +0.148 +0.282 +0.215 +0.516 +0.001 +0.047 +0.977 +0.14 +0.881 +0.566 +0.396 +0.168 +0.706 +0.119 +0.289 +0.954 +0.456 +0.886 +0.123 +0.303 +0.771 +0.855 +0.149 +0.558 +0.904 +0.753 +0.259 +0.549 +0.963 +0.065 +0.718 +0.02 +0.04 +0.245 +0.247 +0.018 +0.274 +0.042 +0.061 +0.331 +0.003 +0.804 +0.194 +0.122 +0.057 +0.135 +0.038 +0.21 +0.172 +0.229 +0.013 +0.001 +0.415 +0.004 +0.865 +0.832 +0.451 +0.674 +0.595 +0.741 +0.461 +0.008 +0.48 +0.003 +0.205 +0.052 +0.02 +0.2 +0.001 +0.275 +0.576 +0.878 +0.275 +0.006 +0.446 +0.68 +0.5 +0.544 +0.631 +0.169 +0.114 +0.366 +0.213 +0.634 +0.187 +0.346 +0.56 +0.211 +0.818 +0.606 +0.19 +0.196 +0.001 +0.108 +0.016 +0.197 +0.81 +0.048 +0.003 +0.717 +0.015 +0.021 +0.726 +0.115 +0.405 +0.313 +0.255 +0.127 +0.813 +0.316 +0.378 +0.374 +0.023 +0.98 +0.484 +0.755 +0.019 +0.787 +0.461 +0.03 +0.216 +0.033 +0.604 +0.013 +0.541 +0.074 +0.669 +0.349 +0.492 diff --git a/TP2/main.py b/TP2/main.py new file mode 100644 index 0000000..58c3d2c --- /dev/null +++ b/TP2/main.py @@ -0,0 +1,11 @@ + +def empaquetar(objetos: list, n: int = 1): + solucion = [] + + return solucion + + +if __name__ == '__main__': + objetos = [0.4, 0.2, 0.5, 0.3, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] + solucion = empaquetar(objetos) + print(solucion) From 1e82214a74f48496b49e6fc18dc152dd5aa74a73 Mon Sep 17 00:00:00 2001 From: Ian Shih Date: Wed, 31 May 2023 00:50:53 -0300 Subject: [PATCH 02/23] Invocacion de programa --- TP2/main.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/TP2/main.py b/TP2/main.py index 58c3d2c..dd7263e 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -1,11 +1,61 @@ +import sys +import time -def empaquetar(objetos: list, n: int = 1): - solucion = [] +BT_FLAG = 'E' +APROX_FLAG = 'A' +GREEDY_FLAG = 'A2' + + +def empaquetar_bt(objetos: list, n: int = 1): + solucion = [1] + + return solucion + + +def empaquetar_aprox(objetos: list, n: int = 1): + solucion = [2, 3] return solucion +def empaquetar_greedy(objetos: list, n: int = 1): + solucion = [5, 6, 7] + + return solucion + + +empaquetar_dict = { + BT_FLAG: empaquetar_bt, + APROX_FLAG: empaquetar_aprox, + GREEDY_FLAG: empaquetar_greedy +} + + +def main(): + argumentos = sys.argv[1:] + + if len(argumentos) != 2: + raise ValueError("Cantidad de parametros erronea") + + flags, ruta_datos = argumentos + + flags = flags.split('|') + + paquetes = [] + with open(ruta_datos) as archivo: + paquetes.extend([float(linea.rstrip()) for linea in archivo.readlines()[2:]]) + + start_time = time.time() + cant_paq_x_met = [str(len(empaquetar_dict[flag](paquetes))) for flag in flags] + end_time = time.time() + + print(f"{'|'.join(cant_paq_x_met)}: #Envases") + print(f"Tiempo de ejecucion: {(end_time - start_time) * 1000}") + + if __name__ == '__main__': objetos = [0.4, 0.2, 0.5, 0.3, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] - solucion = empaquetar(objetos) + solucion = empaquetar_bt(objetos) + + main() print(solucion) From 0255fbb71798dd16e5811219bf1db9fbecb079f4 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Wed, 31 May 2023 18:38:09 -0300 Subject: [PATCH 03/23] Add backtracking algorithm Co-authored-by: Ian Shih --- TP2/README.md | 10 ++++++++++ TP2/main.py | 46 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 TP2/README.md diff --git a/TP2/README.md b/TP2/README.md new file mode 100644 index 0000000..33a64cc --- /dev/null +++ b/TP2/README.md @@ -0,0 +1,10 @@ +![](https://i.imgur.com/P0aqOMI.jpg) + +# Trabajo Práctico 1 + +## Integrantes: + +| Nombre | Padrón | Email | +| -------------- | ------ | ------------------- | +| Manuel Sanchez | 107951 | msanchezf@fi.uba.ar | +| Ian Shih | 108349 | ishih@fi.uba.ar | diff --git a/TP2/main.py b/TP2/main.py index dd7263e..b388e83 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -1,13 +1,51 @@ import sys import time +from math import inf +import copy BT_FLAG = 'E' APROX_FLAG = 'A' GREEDY_FLAG = 'A2' +def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> list: + solucion = None + if len(objetos) == 0: return solucion_parcial + + objeto = objetos.pop() + for paquete in solucion_parcial: + if sum(paquete) + objeto <= 1: + paquete.append(objeto) + solucion_actual = empaquetar_bt(objetos, solucion_parcial) + if not solucion or len(solucion_actual) < len(solucion): + solucion = copy.deepcopy(solucion_actual) + paquete.pop() + + solucion_parcial.append([objeto]) + solucion_actual = empaquetar_bt(objetos, solucion_parcial) + if not solucion or len(solucion_actual) < len(solucion): + solucion = copy.deepcopy(solucion_actual) + solucion_parcial.pop() + objetos.append(objeto) -def empaquetar_bt(objetos: list, n: int = 1): - solucion = [1] + return solucion + +def empaquetar_bt(objetos: list, solucion_parcial: list = []) -> int: + solucion = inf + if len(objetos) == 0: return len(solucion_parcial) + + objeto = objetos.pop() + for paquete in solucion_parcial: + if sum(paquete) + objeto <= 1: + paquete.append(objeto) + solucion_actual = empaquetar_bt(objetos, solucion_parcial) + solucion = min(solucion_actual, solucion) + paquete.pop() + + solucion_parcial.append([objeto]) + solucion_actual = empaquetar_bt(objetos, solucion_parcial) + solucion = min(solucion_actual, solucion) + solucion_parcial.pop() + objetos.append(objeto) return solucion @@ -54,8 +92,8 @@ def main(): if __name__ == '__main__': - objetos = [0.4, 0.2, 0.5, 0.3, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] + objetos = [0.4, 0.8, 0.5, 0.1, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] solucion = empaquetar_bt(objetos) - main() + # main() print(solucion) From 4dd72a128ff2e7cda38a4d4c164dcba28a46bb31 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Thu, 1 Jun 2023 01:22:42 -0300 Subject: [PATCH 04/23] Add leaf pruning --- TP2/main.py | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/TP2/main.py b/TP2/main.py index b388e83..9c02d27 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -1,6 +1,6 @@ import sys import time -from math import inf +from math import inf, isclose import copy BT_FLAG = 'E' @@ -29,25 +29,32 @@ def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> li return solucion -def empaquetar_bt(objetos: list, solucion_parcial: list = []) -> int: - solucion = inf - if len(objetos) == 0: return len(solucion_parcial) +def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: int = inf) -> int: + if len(objetos) == 0: + return len(solucion_parcial) + objeto = objetos.pop() for paquete in solucion_parcial: - if sum(paquete) + objeto <= 1: - paquete.append(objeto) - solucion_actual = empaquetar_bt(objetos, solucion_parcial) - solucion = min(solucion_actual, solucion) - paquete.pop() - - solucion_parcial.append([objeto]) - solucion_actual = empaquetar_bt(objetos, solucion_parcial) - solucion = min(solucion_actual, solucion) + if paquete[1] + objeto <= 1 or isclose(paquete[1] + objeto, 1): + paquete[0].append(objeto) + paquete[1] += objeto + solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + mejor_solucion = min(solucion_actual, mejor_solucion) + paquete[1] -= objeto + paquete[0].pop() + + if len(solucion_parcial) + 1 >= mejor_solucion: + objetos.append(objeto) + return mejor_solucion + + solucion_parcial.append([[objeto], objeto]) + solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + mejor_solucion = min(solucion_actual, mejor_solucion) solucion_parcial.pop() objetos.append(objeto) - return solucion + return mejor_solucion def empaquetar_aprox(objetos: list, n: int = 1): @@ -79,15 +86,15 @@ def main(): flags = flags.split('|') - paquetes = [] + objetos = [] with open(ruta_datos) as archivo: - paquetes.extend([float(linea.rstrip()) for linea in archivo.readlines()[2:]]) + objetos.extend([float(linea.rstrip()) for linea in archivo.readlines()[2:]]) start_time = time.time() - cant_paq_x_met = [str(len(empaquetar_dict[flag](paquetes))) for flag in flags] + paquetes_por_metodo = [str(empaquetar_dict[flag](objetos)) for flag in flags] end_time = time.time() - print(f"{'|'.join(cant_paq_x_met)}: #Envases") + print(f"{'|'.join(paquetes_por_metodo)}: #Envases") print(f"Tiempo de ejecucion: {(end_time - start_time) * 1000}") @@ -95,5 +102,5 @@ def main(): objetos = [0.4, 0.8, 0.5, 0.1, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] solucion = empaquetar_bt(objetos) - # main() + main() print(solucion) From 6149bf3bb135351eb1ad752e3df518892f05c30c Mon Sep 17 00:00:00 2001 From: fsh1ft Date: Thu, 1 Jun 2023 15:43:21 -0300 Subject: [PATCH 05/23] Solucion aproximada --- TP2/main.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/TP2/main.py b/TP2/main.py index 9c02d27..1507cfa 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -7,6 +7,9 @@ APROX_FLAG = 'A' GREEDY_FLAG = 'A2' +def solucion_valida(suma_solucion: int) -> bool: + return suma_solucion <= 1 or isclose(suma_solucion, 1) + def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> list: solucion = None if len(objetos) == 0: return solucion_parcial @@ -36,7 +39,7 @@ def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: in objeto = objetos.pop() for paquete in solucion_parcial: - if paquete[1] + objeto <= 1 or isclose(paquete[1] + objeto, 1): + if solucion_valida(paquete[1] + objeto): paquete[0].append(objeto) paquete[1] += objeto solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) @@ -58,15 +61,23 @@ def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: in def empaquetar_aprox(objetos: list, n: int = 1): - solucion = [2, 3] + paquetes = [] + paquete_actual = [] + for objeto in objetos: + if solucion_valida(sum(paquete_actual) + objeto): + paquete_actual.append(objeto) + else: + paquetes.append(paquete_actual) + paquete_actual = [objeto] + + return len(paquetes) - return solucion def empaquetar_greedy(objetos: list, n: int = 1): - solucion = [5, 6, 7] + solucion = [] - return solucion + return len(solucion) empaquetar_dict = { From 853c23914d271b79e3a753b9010354101d373a31 Mon Sep 17 00:00:00 2001 From: fsh1ft Date: Thu, 1 Jun 2023 16:22:55 -0300 Subject: [PATCH 06/23] Mover a distintos archivos --- TP2/empaquetar_aprox.py | 14 ++++++ TP2/empaquetar_bt.py | 29 +++++++++++++ TP2/empaquetar_greedy.py | 4 ++ TP2/main.py | 92 ++++++++++------------------------------ TP2/utils.py | 5 +++ 5 files changed, 74 insertions(+), 70 deletions(-) create mode 100644 TP2/empaquetar_aprox.py create mode 100644 TP2/empaquetar_bt.py create mode 100644 TP2/empaquetar_greedy.py create mode 100644 TP2/utils.py diff --git a/TP2/empaquetar_aprox.py b/TP2/empaquetar_aprox.py new file mode 100644 index 0000000..bdb385f --- /dev/null +++ b/TP2/empaquetar_aprox.py @@ -0,0 +1,14 @@ +from utils import solucion_valida + + +def empaquetar_aprox(objetos: list, n: int = 1): + paquetes = [] + paquete_actual = [] + for objeto in objetos: + if solucion_valida(sum(paquete_actual) + objeto): + paquete_actual.append(objeto) + else: + paquetes.append(paquete_actual) + paquete_actual = [objeto] + + return len(paquetes) \ No newline at end of file diff --git a/TP2/empaquetar_bt.py b/TP2/empaquetar_bt.py new file mode 100644 index 0000000..e702e0c --- /dev/null +++ b/TP2/empaquetar_bt.py @@ -0,0 +1,29 @@ +from utils import solucion_valida +from math import inf + +def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: int = inf) -> int: + if len(objetos) == 0: + return len(solucion_parcial) + + + objeto = objetos.pop() + for paquete in solucion_parcial: + if solucion_valida(paquete[1] + objeto): + paquete[0].append(objeto) + paquete[1] += objeto + solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + mejor_solucion = min(solucion_actual, mejor_solucion) + paquete[1] -= objeto + paquete[0].pop() + + if len(solucion_parcial) + 1 >= mejor_solucion: + objetos.append(objeto) + return mejor_solucion + + solucion_parcial.append([[objeto], objeto]) + solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + mejor_solucion = min(solucion_actual, mejor_solucion) + solucion_parcial.pop() + objetos.append(objeto) + + return mejor_solucion \ No newline at end of file diff --git a/TP2/empaquetar_greedy.py b/TP2/empaquetar_greedy.py new file mode 100644 index 0000000..c3648a2 --- /dev/null +++ b/TP2/empaquetar_greedy.py @@ -0,0 +1,4 @@ +def empaquetar_greedy(objetos: list, n: int = 1): + solucion = [] + + return len(solucion) \ No newline at end of file diff --git a/TP2/main.py b/TP2/main.py index 1507cfa..45020b5 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -1,84 +1,36 @@ import sys import time -from math import inf, isclose -import copy +from empaquetar_aprox import empaquetar_aprox + +from empaquetar_bt import empaquetar_bt +from empaquetar_greedy import empaquetar_greedy BT_FLAG = 'E' APROX_FLAG = 'A' GREEDY_FLAG = 'A2' -def solucion_valida(suma_solucion: int) -> bool: - return suma_solucion <= 1 or isclose(suma_solucion, 1) - -def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> list: - solucion = None - if len(objetos) == 0: return solucion_parcial - - objeto = objetos.pop() - for paquete in solucion_parcial: - if sum(paquete) + objeto <= 1: - paquete.append(objeto) - solucion_actual = empaquetar_bt(objetos, solucion_parcial) - if not solucion or len(solucion_actual) < len(solucion): - solucion = copy.deepcopy(solucion_actual) - paquete.pop() - - solucion_parcial.append([objeto]) - solucion_actual = empaquetar_bt(objetos, solucion_parcial) - if not solucion or len(solucion_actual) < len(solucion): - solucion = copy.deepcopy(solucion_actual) - solucion_parcial.pop() - objetos.append(objeto) - - return solucion - -def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: int = inf) -> int: - if len(objetos) == 0: - return len(solucion_parcial) - - - objeto = objetos.pop() - for paquete in solucion_parcial: - if solucion_valida(paquete[1] + objeto): - paquete[0].append(objeto) - paquete[1] += objeto - solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) - mejor_solucion = min(solucion_actual, mejor_solucion) - paquete[1] -= objeto - paquete[0].pop() - - if len(solucion_parcial) + 1 >= mejor_solucion: - objetos.append(objeto) - return mejor_solucion - - solucion_parcial.append([[objeto], objeto]) - solucion_actual = empaquetar_bt(objetos, solucion_parcial, mejor_solucion) - mejor_solucion = min(solucion_actual, mejor_solucion) - solucion_parcial.pop() - objetos.append(objeto) - - return mejor_solucion - - -def empaquetar_aprox(objetos: list, n: int = 1): - paquetes = [] - paquete_actual = [] - for objeto in objetos: - if solucion_valida(sum(paquete_actual) + objeto): - paquete_actual.append(objeto) - else: - paquetes.append(paquete_actual) - paquete_actual = [objeto] - - return len(paquetes) - +# def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> list: +# solucion = None +# if len(objetos) == 0: return solucion_parcial -def empaquetar_greedy(objetos: list, n: int = 1): - solucion = [] +# objeto = objetos.pop() +# for paquete in solucion_parcial: +# if sum(paquete) + objeto <= 1: +# paquete.append(objeto) +# solucion_actual = empaquetar_bt(objetos, solucion_parcial) +# if not solucion or len(solucion_actual) < len(solucion): +# solucion = copy.deepcopy(solucion_actual) +# paquete.pop() - return len(solucion) +# solucion_parcial.append([objeto]) +# solucion_actual = empaquetar_bt(objetos, solucion_parcial) +# if not solucion or len(solucion_actual) < len(solucion): +# solucion = copy.deepcopy(solucion_actual) +# solucion_parcial.pop() +# objetos.append(objeto) +# return solucion empaquetar_dict = { BT_FLAG: empaquetar_bt, diff --git a/TP2/utils.py b/TP2/utils.py new file mode 100644 index 0000000..041551f --- /dev/null +++ b/TP2/utils.py @@ -0,0 +1,5 @@ +from math import isclose + + +def solucion_valida(suma_solucion: int) -> bool: + return suma_solucion <= 1 or isclose(suma_solucion, 1) \ No newline at end of file From d5acc8d1e14db9b2b9aa03c5b01372039d3c3b01 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Thu, 1 Jun 2023 21:06:20 -0300 Subject: [PATCH 07/23] Add algorithm optimality --- TP2/optimalidad.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 TP2/optimalidad.py diff --git a/TP2/optimalidad.py b/TP2/optimalidad.py new file mode 100644 index 0000000..9a369e6 --- /dev/null +++ b/TP2/optimalidad.py @@ -0,0 +1,31 @@ +from empaquetar_aprox import empaquetar_aprox +from empaquetar_bt import empaquetar_bt +from random import uniform + +def generar_objetos(n): + return [round(uniform(0, 1), 3) for _ in range(n)] + +def error_relativo(solucion_optima, solucion_aproximada): + return abs(solucion_aproximada - solucion_optima) / solucion_optima * 100 + +def main(): + soluciones_optimas = [] + soluciones_aproximadas = [] + error_relativo_total = 0 + for i in range(500): + print("Simulacion", i + 1) + objetos = generar_objetos(15) + + soluciones_aproximadas.append(empaquetar_aprox(objetos)) + print(f"Solucion aproximada: {soluciones_aproximadas[-1]}") + + soluciones_optimas.append(empaquetar_bt(objetos)) + print(f"Solucion optima: {soluciones_optimas[-1]}") + + error_relativo_total += error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1]) + print(f"Error relativo: {error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1])}%\n") + + print(f"Error relativo promedio: {error_relativo_total / len(soluciones_optimas)}%") + +if __name__ == '__main__': + main() From dcbeb78e64943d07fdea8c394cd0754c5e583d08 Mon Sep 17 00:00:00 2001 From: fsh1ft Date: Fri, 2 Jun 2023 11:39:59 -0300 Subject: [PATCH 08/23] Mediciones --- TP2/mediciones.ipynb | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 TP2/mediciones.ipynb diff --git a/TP2/mediciones.ipynb b/TP2/mediciones.ipynb new file mode 100644 index 0000000..13cbb53 --- /dev/null +++ b/TP2/mediciones.ipynb @@ -0,0 +1,95 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import timeit\n", + "from matplotlib import pyplot as plt\n", + "import seaborn as sns\n", + "import random\n", + "\n", + "from empaquetar_aprox import empaquetar_aprox\n", + "from empaquetar_bt import empaquetar_bt\n", + "\n", + "random.seed(0)\n", + "\n", + "sns.set(rc={'figure.facecolor':'white'})" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def generar_objetos(n):\n", + " return [round(random.uniform(0, 1), 3) for _ in range(n)]\n", + "\n", + "def get_time(empaquetar, objetos):\n", + " number_of_executions, total_time = timeit.Timer(lambda: empaquetar(objetos)).autorange()\n", + " return total_time / number_of_executions\n", + "\n", + "\n", + "def plot(empaquetar, label, cases):\n", + " time_to_run = [get_time(empaquetar, case) for case in cases]\n", + " plt.plot([i for i in range(len(cases))], time_to_run, label=label)\n", + " return plt\n", + "\n", + "\n", + "def plot_comparison(cases, title, xlabel):\n", + " plot(empaquetar_bt, 'Backtracking', cases)\n", + " plt.xlabel(xlabel)\n", + " plt.ylabel(\"Tiempo de ejecucion (s)\")\n", + " plt.title(title)\n", + " plt.legend()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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2B1GRERETolJEBERETklJkFERETklJgEERERkVNiEkREREROiUkQEREROSUmQUREROSUmAQRERGRU2ISRERERE6JSRARERE5JSZBRERE5JSYBBEREZFTYhJERERETkla1wE4kosXL2L+/Pn466+/4OnpicGDB2PatGmQyWSV3icIAlauXIn/+7//Q3Z2Ntq0aYPXXnsN4eHhtRO4GXbv3o1vv/0Wp0+fhlKpRIsWLTBmzBgMGzYMIpGowvuio6ORkZFR5vjJkyfh6upqzZDNtm3bNrz22mtljj///POYMWNGhffZ4+cKAGPGjMHvv/9e7rmPPvoIjz32WLnn7OGzTUtLw+rVq3HixAmcP38ewcHB2LlzZ5nrvvzyS6xatQrXrl1Dy5YtkZCQgN69e1dZfmZmJubPn4/ffvsNLi4u6Nu3L1577TV4eXlZozqVqqquubm5+Pzzz7Fv3z5cvnwZMpkMHTp0QEJCAsLCwiot+8iRI3j22WfLHB84cCAWLlxo8bpUxZTPtaLf6127diEkJKTS8m3pcwWqru/Vq1fxyCOPlHuvTCbD33//XWHZtvbZWhuTIAtRKBSIjY1FUFAQlixZgszMTCQmJqKwsBCzZ8+u9N6VK1di8eLFmDFjBsLCwrBhwwaMHz8e27dvR/PmzWupBtWzdu1aNG3aFLNmzYKvry8OHjyIt956C9evX8dLL71U6b39+vXD+PHjjY5VlSjaglWrVqFevXqG1wEBAZVeb4+fKwDMmTMHubm5RsfWrVuHH374AREREZXea+uf7fnz57Fv3z507NgROp0OgiCUuea7777DW2+9hUmTJqF79+7YtWsXXnrpJWzYsKHSBLa4uBgTJkwAAHz44YcoLCzE+++/j5dffhkrVqywVpUqVFVdr127hs2bN2PYsGGYNm0aioqKsGbNGowcORJbt26tMjEAgPfeew/BwcGG176+vhavhylM+VwBoHPnzpg5c6bRsWbNmlVatq19rkDV9fX398fmzZuNjgmCgAkTJqB79+4mPcNWPlurE8gili9fLoSHhws5OTmGY5s2bRLatGkjXL9+vcL7CgsLhc6dOwsffvih4VhRUZHQu3dvYc6cOVaMuGZu3bpV5tibb74pdO7cWdBqtRXe17t3b2Hu3LnWDM3itm7dKoSGhpZb54rY6+dakejoaOH555+v9Bp7+GxL/27O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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cases_k_constant = [generar_objetos(i) for i in range(25)]\n", + "plot_comparison(cases_k_constant, \"Tiempo de ejecucion\" ,\"Cantidad de objetos\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b414e43a26d74b48cc144b3f662ab5d681c186ee Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Fri, 2 Jun 2023 17:02:55 -0300 Subject: [PATCH 09/23] Update graph --- .gitignore | 1 + TP2/mediciones.ipynb | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index bee8a64..ae206ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +out* \ No newline at end of file diff --git a/TP2/mediciones.ipynb b/TP2/mediciones.ipynb index 13cbb53..a650e2c 100644 --- a/TP2/mediciones.ipynb +++ b/TP2/mediciones.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -14,14 +14,14 @@ "from empaquetar_aprox import empaquetar_aprox\n", "from empaquetar_bt import empaquetar_bt\n", "\n", - "random.seed(0)\n", + "random.seed(42)\n", "\n", "sns.set(rc={'figure.facecolor':'white'})" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -50,14 +50,14 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { - "image/png": "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2B1GRERETolJEBERETklJkFERETklJgEERERkVNiEkREREROiUkQEREROSUmQUREROSUmAQRERGRU2ISRERERE6JSRARERE5JSZBRERE5JSYBBEREZFTYhJERERETkla1wE4kosXL2L+/Pn466+/4OnpicGDB2PatGmQyWSV3icIAlauXIn/+7//Q3Z2Ntq0aYPXXnsN4eHhtRO4GXbv3o1vv/0Wp0+fhlKpRIsWLTBmzBgMGzYMIpGowvuio6ORkZFR5vjJkyfh6upqzZDNtm3bNrz22mtljj///POYMWNGhffZ4+cKAGPGjMHvv/9e7rmPPvoIjz32WLnn7OGzTUtLw+rVq3HixAmcP38ewcHB2LlzZ5nrvvzyS6xatQrXrl1Dy5YtkZCQgN69e1dZfmZmJubPn4/ffvsNLi4u6Nu3L1577TV4eXlZozqVqqquubm5+Pzzz7Fv3z5cvnwZMpkMHTp0QEJCAsLCwiot+8iRI3j22WfLHB84cCAWLlxo8bpUxZTPtaLf6127diEkJKTS8m3pcwWqru/Vq1fxyCOPlHuvTCbD33//XWHZtvbZWhuTIAtRKBSIjY1FUFAQlixZgszMTCQmJqKwsBCzZ8+u9N6VK1di8eLFmDFjBsLCwrBhwwaMHz8e27dvR/PmzWupBtWzdu1aNG3aFLNmzYKvry8OHjyIt956C9evX8dLL71U6b39+vXD+PHjjY5VlSjaglWrVqFevXqG1wEBAZVeb4+fKwDMmTMHubm5RsfWrVuHH374AREREZXea+uf7fnz57Fv3z507NgROp0OgiCUuea7777DW2+9hUmTJqF79+7YtWsXXnrpJWzYsKHSBLa4uBgTJkwAAHz44YcoLCzE+++/j5dffhkrVqywVpUqVFVdr127hs2bN2PYsGGYNm0aioqKsGbNGowcORJbt26tMjEAgPfeew/BwcGG176+vhavhylM+VwBoHPnzpg5c6bRsWbNmlVatq19rkDV9fX398fmzZuNjgmCgAkTJqB79+4mPcNWPlurE8gili9fLoSHhws5OTmGY5s2bRLatGkjXL9+vcL7CgsLhc6dOwsffvih4VhRUZHQu3dvYc6cOVaMuGZu3bpV5tibb74pdO7cWdBqtRXe17t3b2Hu3LnWDM3itm7dKoSGhpZb54rY6+dakejoaOH555+v9Bp7+GxL/27O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", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, "metadata": {}, @@ -86,7 +86,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.10.11" }, "orig_nbformat": 4 }, From 0ad5acbe4eefdabc0c9befa4e349664de80e3a00 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Sun, 4 Jun 2023 01:38:55 -0300 Subject: [PATCH 10/23] Change algorithms to return packages --- TP2/empaquetar_aprox.py | 5 +++-- TP2/empaquetar_bt.py | 40 ++++++++++++++++++++++++++++++++++++++-- TP2/main.py | 30 +----------------------------- TP2/mediciones.ipynb | 13 ++++++++----- TP2/optimalidad.py | 11 +++++++---- 5 files changed, 57 insertions(+), 42 deletions(-) diff --git a/TP2/empaquetar_aprox.py b/TP2/empaquetar_aprox.py index bdb385f..cf44d69 100644 --- a/TP2/empaquetar_aprox.py +++ b/TP2/empaquetar_aprox.py @@ -1,7 +1,7 @@ from utils import solucion_valida -def empaquetar_aprox(objetos: list, n: int = 1): +def empaquetar_aprox(objetos: list): paquetes = [] paquete_actual = [] for objeto in objetos: @@ -11,4 +11,5 @@ def empaquetar_aprox(objetos: list, n: int = 1): paquetes.append(paquete_actual) paquete_actual = [objeto] - return len(paquetes) \ No newline at end of file + return paquetes + diff --git a/TP2/empaquetar_bt.py b/TP2/empaquetar_bt.py index e702e0c..d81aac0 100644 --- a/TP2/empaquetar_bt.py +++ b/TP2/empaquetar_bt.py @@ -1,7 +1,7 @@ from utils import solucion_valida from math import inf -def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: int = inf) -> int: +def empaquetar_bt_solo_cantidad(objetos: list, solucion_parcial: list = [], mejor_solucion: int = inf) -> int: if len(objetos) == 0: return len(solucion_parcial) @@ -26,4 +26,40 @@ def empaquetar_bt(objetos: list, solucion_parcial: list = [], mejor_solucion: in solucion_parcial.pop() objetos.append(objeto) - return mejor_solucion \ No newline at end of file + return mejor_solucion + +def copiar_solucion(origen: list, destino: list) -> list: + destino.clear() + for paquete, suma in origen: + destino.append([paquete.copy(), suma]) + +def empaquetar_bt(objetos: list) -> list: + return _empaquetar_bt(objetos, [], []) + +def _empaquetar_bt(objetos: list, solucion_parcial: list, mejor_solucion: list) -> list: + if len(objetos) == 0: + return solucion_parcial + + objeto = objetos.pop() + for paquete in solucion_parcial: + if solucion_valida(paquete[1] + objeto): + paquete[0].append(objeto) + paquete[1] += objeto + solucion_actual = _empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + if not mejor_solucion or len(solucion_actual) < len(mejor_solucion): + copiar_solucion(solucion_actual, mejor_solucion) + paquete[1] -= objeto + paquete[0].pop() + + if mejor_solucion and len(solucion_parcial) + 1 >= len(mejor_solucion): + objetos.append(objeto) + return mejor_solucion + + solucion_parcial.append([[objeto], objeto]) + solucion_actual = _empaquetar_bt(objetos, solucion_parcial, mejor_solucion) + if not mejor_solucion or len(solucion_actual) < len(mejor_solucion): + copiar_solucion(solucion_actual, mejor_solucion) + solucion_parcial.pop() + objetos.append(objeto) + + return mejor_solucion diff --git a/TP2/main.py b/TP2/main.py index 45020b5..c3b92b1 100644 --- a/TP2/main.py +++ b/TP2/main.py @@ -1,7 +1,6 @@ import sys import time from empaquetar_aprox import empaquetar_aprox - from empaquetar_bt import empaquetar_bt from empaquetar_greedy import empaquetar_greedy @@ -9,29 +8,6 @@ APROX_FLAG = 'A' GREEDY_FLAG = 'A2' - -# def empaquetar_bt_con_paquetes(objetos: list, solucion_parcial: list = []) -> list: -# solucion = None -# if len(objetos) == 0: return solucion_parcial - -# objeto = objetos.pop() -# for paquete in solucion_parcial: -# if sum(paquete) + objeto <= 1: -# paquete.append(objeto) -# solucion_actual = empaquetar_bt(objetos, solucion_parcial) -# if not solucion or len(solucion_actual) < len(solucion): -# solucion = copy.deepcopy(solucion_actual) -# paquete.pop() - -# solucion_parcial.append([objeto]) -# solucion_actual = empaquetar_bt(objetos, solucion_parcial) -# if not solucion or len(solucion_actual) < len(solucion): -# solucion = copy.deepcopy(solucion_actual) -# solucion_parcial.pop() -# objetos.append(objeto) - -# return solucion - empaquetar_dict = { BT_FLAG: empaquetar_bt, APROX_FLAG: empaquetar_aprox, @@ -54,7 +30,7 @@ def main(): objetos.extend([float(linea.rstrip()) for linea in archivo.readlines()[2:]]) start_time = time.time() - paquetes_por_metodo = [str(empaquetar_dict[flag](objetos)) for flag in flags] + paquetes_por_metodo = [str(len(empaquetar_dict[flag](objetos))) for flag in flags] end_time = time.time() print(f"{'|'.join(paquetes_por_metodo)}: #Envases") @@ -62,8 +38,4 @@ def main(): if __name__ == '__main__': - objetos = [0.4, 0.8, 0.5, 0.1, 0.7, 0.6, 0.1, 0.4, 0.2, 0.2] - solucion = empaquetar_bt(objetos) - main() - print(solucion) diff --git a/TP2/mediciones.ipynb b/TP2/mediciones.ipynb index a650e2c..b613bd8 100644 --- a/TP2/mediciones.ipynb +++ b/TP2/mediciones.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 7, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -21,7 +21,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -41,6 +41,7 @@ "\n", "def plot_comparison(cases, title, xlabel):\n", " plot(empaquetar_bt, 'Backtracking', cases)\n", + " plot(empaquetar_aprox, 'Algoritmo aproximado', cases)\n", " plt.xlabel(xlabel)\n", " plt.ylabel(\"Tiempo de ejecucion (s)\")\n", " plt.title(title)\n", @@ -50,17 +51,19 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEXCAYAAACzhgONAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAzBElEQVR4nO3deZxT1dnA8V+SWZlhd9hU3NBHXFlFBcRWrKLW1oriVsR9X2qttYoL7iKv1q2tVbCKIiqI1gqiSF0Q3BBFBB6xoqCi7EtCMpNM8v5xb4ZhGEJmyTKT5/txnMnNvfc8ZzLkyTnn3nM8sVgMY4wxZnu8mQ7AGGNMdrNEYYwxJiFLFMYYYxKyRGGMMSYhSxTGGGMSskRhjDEmobxMB2CMiDwEHOE+3A9YCgTdx48BrVX1nkzEtiMi8giwWlVvbaTzfQYcqarrG+N8SZQ3FbhWVRemozzTNHnsPgqTTUTkW2Coqn6S6ViS0diJwphsZC0Kk9VE5FZgJ1W9XER2Bh4BugL5wERVvUtEdgdmul+Huc9dC1wE7At8ApzuHvcO8DZwMOABLlfV90QkH7gfOAqoBD4E/qCqm2rE0wp4wj1+BRABZrnP1RpfLXVqDTwIHOju9xbwJ1WNiEgMKFPV1SJyHnApThfxGjfWxSJSCjwM9HfLfxm4EXgSWKCqY9xy/hV/LCL74LTOOgBR4A5Vfb56YhaRC4Er3fr/7Jb3lXuejW68uwKLgdNU1Z/wxTPNho1RmKZkPDBOVXsDhwCDReRU97k9gH+r6v44b7wP4iSH/YGBwKHufl2B6araA7geeN5NEiOBLjgJ4GCcfxv31RLDKJxusX2BUwBJMr7qHgDmuvv1BHYCrqm+g4gMAs4GBqpqT2A08JL79G1AEdAd6IGTMAbV+hvbYiLwovv7OQ64y0168fJ+CVwH/EJVDwYmAC+LiMfdpTdwrFtmF7fuJkdYi8I0CSJSgvNm2E5Ebnc3l+K8UX4EhIFX3e3/A2ar6kb32B+BdsCPwDpVnQCgqtNEpBI4CBgC3KiqYfeYh3E+qdc0GLhaVWPAKhGZkkR8L9Q4xwnAIW6LAaC4lnKOB7oBs0WqclE7EWnnxnCNqlbifPof5MYwopbz4B5zME5LCFVdDuzlPhff7VjgeVVd5e7zLxF5ENjdff51VS13j/kC5/dpcoQlCtNU+HC6ig5X1c0AIrITEML5RF7hvnnHhbdznkiNx16cN9uarWsvTrdQTTE3jprnSxRfbXU5RVUXufu1cc9bc5/xqvpndx8vzif5dW6ZVfuLyK7A5lpiK6gRY/VjBFhWo741edjyOwhW216zHNPMWdeTaRLc1sEHuF007pvr+8Bv6niqMhE51j3Hr3ESyhfAdOBiEcl335QvA96s5fjXgfNExCsibePl1zG+6cAfRMQjIoXAv4HLa+zzBnC6iHR2H1+M06UGMAM4242hEJiE06pYBfRxy98Jp8stHttcnK6seGJ5H2hdI6ZhIlLm7nMOzrjI17XEb3KMJQrTlJwBHOp2fXwIPKeqz9bxHCHg9yLyOc4A8G/dLpw7gJ+Az4BFOJ+kr6rl+FtxkstinK6uL+oR35VAiXvsfPf76Oo7qOp04F7gTRGZ7577d26raRRQAXwOzAOmqupLOAPcnUVEgWdxBu2rx3aqW+9XgfNV9adq5b2JM3YyU0S+xEkqJ6hqtJb4TY6xy2NNznCvjlqgqqWZjqU27uDyBqCFqgZ3tL8x6WItCmOygIj0xWml/MuShMk21qIwxhiTkLUojDHGJGSJwhhjTELN4T6KQqAvznQKlRmOxRhjmgof0Bn4GChPtGNzSBR9gfcyHYQxxjRRA3HnK9ue5pAoVgCsWxcgGq37wHz79qWsWZO7c5vlcv1zue6Q2/W3uvvxej20bVsC7ntoIs0hUVQCRKOxeiWK+LG5LJfrn8t1h9yuv9W9yg677G0w2xhjTEKWKIwxxiTUHLqetisWi7Fu3SoqKkJsOzmnY+VKL9Fo7k5nk8v1T67uHgoKimjbtgyPxyZMNbmpWScKv38DHo+Hjh13weOpvfGUl+clEsnNN0rI7fonU/dYLMr69avx+zfQsmWb9ARmTJZp1l1PwaCfli3bbDdJGLMjHo+Xli3bEgzm5hUyxkAzTxTRaCU+X7NuNJk08PnyiEbtXk6Tu5p1ogCsX9k0mP0NmWwUqohw7d/e58tv16a8rGafKLLJp59+wtFHD2TEiDM4++zTOfPMoTz11Nh6nefyyy/cZvsrr7zEm2++3ihx1nb+e+65ncWLFzb4/MaYhlu3qZy1G8vZFKhIeVnWL5NmIt155JF/ArB582bOOusUjjjiF+yxx54NPveCBfPp2bN3g8+zPddff1PKzm2MqZtA0FkKvbS4tqXdG5cligwqLw/h9XopLS1l5swZTJz4DOXl5ZSXl3P99SPp0aMXS5Yoo0ffRXl5iFatWnPzzbdvdY4XXniOd9/9L6eddiazZr3L3Lkf0779TsyYMZ0NGzbwww/LueSSK6moqKj1/F99pdx99x07PP+YMQ9x7bVXcu65Tktj/PgnKSoq4ttvl7LXXt245ZY7yc/P58UXJzJ58vOUlrZkt912o0uXXTjvvIvS9js1Jlf4g2EASixRNJ73v1jBrPnbTmni8UBD124acFBn+h/YOal9VRcxYsQZxGJRvv9+Ob/85dG0a9eeV16ZzOjRf6VNmzb85z+vMGHCeHr06MWoUTdxySVX0L//QKZMmcSLL07ksMP6A/Daa//mnXdmMmbMQxQXFzNgwBH07Nmbfv0OY8aM6bRu3ZrRox8gGo3yhz9cVuv5b7nlRi6+eMfnLyoq2qoeCxbM59lnJ7HTTmVcdNEIPvxwDp06deall15g7Njx5OXlc8UVF9Glyy4N++UaY2pliaIZq9n1dN11VzNhwtPcddd9vP/+eyxb9h3z5s3F6/Wyfv161qxZTf/+AwE46aShgDOGsHTp/xg9+k5GjbqL4uLiWsvab78DAPB6vY1+/j322IsOHToCsNtue7Bp00a+/34Zhx8+kJISZ0nqwYOPYdOmjY31qzPGVBMIOYmitMgSRaPpf2Dtn/ozecNZixYtOOKIX/D+++8xdeqrHHPMcRx8cE/22qsbkye/QF7e1i9PeXk5q1evco8t4S9/uZkHH7yffv0Or/XNvLCwEHAS0vnnD2/U8xcUFFT97PF4iMVieL0+YrHcvHnPmHTzB8N4PR6KC30pL8uuesqgyspK5s2bS1FRIV6vl+HDz6V377588MFsotEopaWldOjQkY8//gCA6dOnMnbsYwB07NiJAQMG0bNnL5544h8A+Hw+Kiu3vd5/+fJljXL+HenTpy9z5rxPIOAnHA7zzjsz7dJSY1IkEIpQUpyXln9jOdOiyBbxMQqAUChI9+77c911N3LPPbdzxhlDKSoqokePXvz0kzOecvPNtzNmzN08+uhDtG7dhptuuo1ly76tOt9ll13F738/jF/9agh9+hzCY4/9jdLS0q3K7NZtb7p126fW89966x3ce+9dSZ1/R/bcsxtDh57GRRedS3FxMW3atKlq1RhjGpc/GKYkDd1OAJ5YQ0dyM293YOmaNf5t5pf/6afv6NRpt4QH5/JcR9C49V+27DvmzJnFsGFnAnD99ddwwgm/ZcCAIxrl/I2tLnVP5m+pqSkra8mqVZsyHUZGNIe63/fcPMKRKDf8vm6XxMfr7vV6aN++FGAP4NtEx6S0RSEitwCnug9fU9XrRGQwcD9QDDyvqiPdfXsAjwOtgXeBi1U1ksr4TOPq1KkzixYt5Pe/PxWPx8MhhxxWNVBujGlcgWCYdq2KdrxjI0hZonATwq+AnjhzfL8uIqcD9wKDgOXAayIyRFWnAc8A56vqByIyFrgA+Huq4jONr6CggFtvvTPTYRiTE/yhMLt2KN3xjo0glYPZK4A/qmqFqoaBRcA+wBJVXeq2Fp4BThGR3YBiVf3APfZfwCkpjM0YY5q0QDCSlnsoIIUtClX9Mv6ziOwNDAMeYuuFvFcAuwBdtrPdGGNMDeFIlPJwZdNPFHEisj/wGnAtEAakxi5RoLbru+o0wuoOymxl5UoveXk7bjQls09zlsv1T7buXq+XsrKWKY4m/ZpjnZLVlOu+ZkMQgM5lpfWqR12PSfVgdn9gMnC1qk4UkUFAp2q7dAZ+BH7Yzvak1XbVUzQa3eFVLXbVU+7Wvy51j0ajTf4qmZqaw5U/9dXU6/79KmchrVhl3f8ua7nqaYdS9lFSRHYFXgbOUNWJ7uYPnaekm4j4gDOAaar6HRByEwvAcGBaqmIzxpimLBCf56koPbfCpbLP4VqgCLhfRD4Tkc+AEe7XZGAhsBiY5O5/JvCAiCwCSnDGM5qlb775mgED+vD2229VbRs69NesWFGnRlStZs16p+pO6rFjH+Pzz+c1+JyZlIo1MLa33oYxTUV8QsB0TDEOqR3Mvgq4ajtPH1zL/p8Dh6Qqnmzy2muvcuSRR/Hyy5M58sijGvXcAwYMYsCAQQDMmzc3petTpIOtgWHMtgKh9K1FATk0hUf4q/cJ67vbbI9PaNcQ+XIE+fv03/GOQCQS4Y03pvHoo49zySXn8sMP37Pzzrts9fx9993F/PmfUVbWAY/Hw9lnn0evXn14+ulxvPHGNLxeL337Hsqll17JypU/88c/XkHr1m0oKCjkmGOGMG/eXHr16oPqIu699w7uumsMDzwwmn32ET755CPKy8u5+uo/MWnS83z77TeceurpDBt2JqFQiHvvvYOvv/4Kr9fLaaedxZAhJ2wVfyDg5+67b2fVqpWsXr2KHj16MnLkbcybN5dx4/6Jz5fHypU/sd9++/PnP9/EmjWrt4rvgQce4aGH/o9PPvkYjweOOeY4zjprBC++OJG3336LRx75J/Pnf87dd49i3LhnuO66P1StgfH00+OIxeDHH7/nyCOPoqSkhPfee4dYLMaYMQ/Srl17Jk9+ntdfn0ooFMTr9TJq1N3svvsefPTRBzz00P0UFBSw2267V9Vn2bLvGD36TjZt2khRUTFXX30t3bvv36C/B2NSrWqK8TRN4ZG7l7tkyJw5s+jUqRNdu+7GwIFH8sork7d6/uWXJxEKBZkwYTI33HALixYtrDpu1qx3GTt2POPGPcsPPyzn5ZedY5ct+46bb76dBx/8W9V5hgw5AZHu/PnPI9lrr25V259++nmOOeY4/vrX+7jzztH84x9P8OSTTwAwbtxjtG7dmvHjX+DBB//BuHGP8/XXS7aKb/bsWey99z489tiTTJw4hQULvkB1MQALF37JH/94HRMmTKa8vIKXXnphm/hefnkyP//8M0899RyPP/4077wzk9mzZzF06DC8Xi8vvfQi9957OzfccAstWpRsVfbChV9yww03M378C7z88iTatGnL2LHj6dZtb2bMeINAwM+7777DI488xvjxLzBw4JFMmfIiFRUV3HnnLdxxx72MG/fMVvNP3X77TZxyymk89dRErrjiGkaO/DMVFalfWtKYhggEw+T5vBTkp+ctPGdaFPn79K/1U3+6r/qZOvVVBg8+BoCjjjqaUaNu4oILLq16/uOPP+TXvz4Jj8dDp06d6d27LwBz537C4MHHUFjo3LJ//PEnMm3aaxx++ADatm1H585ddlj2oYc69e/UqTP7738gRUVFlJZ2we/fVFVGvKunTZs2DBx4BPPmzaVbt72rznH00ceycOECXnhhAt9+u5QNGzYQDG4GoEePnnTtujsAxx57HP/+9xQGDfrlVvF9+unHHHfcCfh8Pnw+H0cfPYS5cz/i8MMH8Je/3Mzw4cM46aRTOOigHtvEv+eee9Gxo3NxXOvWbejTx+mp7NixE5s2baSkpJRbb72DGTPeYPnyZXz44Wz23lv45puvad++jN133wNwkujjj/+dzZs38/333zNo0C8BOOCAA2nVqhXLln23VZ2NyTb+YDhtM8dCDiWKbLBu3VrmzHmfxYsX8eKLE4nFYmzatHGrQe3t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", "text/plain": [ "
" ] }, - "metadata": {}, + "metadata": { + "needs_background": "light" + }, "output_type": "display_data" } ], diff --git a/TP2/optimalidad.py b/TP2/optimalidad.py index 9a369e6..3a4711a 100644 --- a/TP2/optimalidad.py +++ b/TP2/optimalidad.py @@ -2,6 +2,9 @@ from empaquetar_bt import empaquetar_bt from random import uniform +OBJETOS_POR_SIMULACION = 15 +SIMULACIONES = 1000 + def generar_objetos(n): return [round(uniform(0, 1), 3) for _ in range(n)] @@ -12,14 +15,14 @@ def main(): soluciones_optimas = [] soluciones_aproximadas = [] error_relativo_total = 0 - for i in range(500): + for i in range(SIMULACIONES): print("Simulacion", i + 1) - objetos = generar_objetos(15) + objetos = generar_objetos(OBJETOS_POR_SIMULACION) - soluciones_aproximadas.append(empaquetar_aprox(objetos)) + soluciones_aproximadas.append(len(empaquetar_aprox(objetos))) print(f"Solucion aproximada: {soluciones_aproximadas[-1]}") - soluciones_optimas.append(empaquetar_bt(objetos)) + soluciones_optimas.append(len(empaquetar_bt(objetos))) print(f"Solucion optima: {soluciones_optimas[-1]}") error_relativo_total += error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1]) From 9329786281f2f32b247bf79e8be1f7f7ef91d7b8 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Sun, 4 Jun 2023 14:02:38 -0300 Subject: [PATCH 11/23] Move generar_objetos to utils --- TP2/mediciones.ipynb | 6 ++---- TP2/optimalidad.py | 5 +---- TP2/utils.py | 7 ++++++- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/TP2/mediciones.ipynb b/TP2/mediciones.ipynb index b613bd8..03d73de 100644 --- a/TP2/mediciones.ipynb +++ b/TP2/mediciones.ipynb @@ -10,6 +10,7 @@ "from matplotlib import pyplot as plt\n", "import seaborn as sns\n", "import random\n", + "from utils import generar_objetos\n", "\n", "from empaquetar_aprox import empaquetar_aprox\n", "from empaquetar_bt import empaquetar_bt\n", @@ -25,9 +26,6 @@ "metadata": {}, "outputs": [], "source": [ - "def generar_objetos(n):\n", - " return [round(random.uniform(0, 1), 3) for _ in range(n)]\n", - "\n", "def get_time(empaquetar, objetos):\n", " number_of_executions, total_time = timeit.Timer(lambda: empaquetar(objetos)).autorange()\n", " return total_time / number_of_executions\n", @@ -56,7 +54,7 @@ "outputs": [ { "data": { - "image/png": "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qpWsXr2KHj16MnLkbcybN5dx4/6Jz5fHypU/sd9++/PnP9/EmjWrt4rvgQce4aGH/o9PPvkYjweOOeY4zjprBC++OJG3336LRx75J/Pnf87dd49i3LhnuO66P1StgfH00+OIxeDHH7/nyCOPoqSkhPfee4dYLMaYMQ/Srl17Jk9+ntdfn0ooFMTr9TJq1N3svvsefPTRBzz00P0UFBSw2267V9Vn2bLvGD36TjZt2khRUTFXX30t3bvv36C/B2NSrWqK8TRN4ZG7l7tkyJw5s+jUqRNdu+7GwIFH8sork7d6/uWXJxEKBZkwYTI33HALixYtrDpu1qx3GTt2POPGPcsPPyzn5ZedY5ct+46bb76dBx/8W9V5hgw5AZHu/PnPI9lrr25V259++nmOOeY4/vrX+7jzztH84x9P8OSTTwAwbtxjtG7dmvHjX+DBB//BuHGP8/XXS7aKb/bsWey99z489tiTTJw4hQULvkB1MQALF37JH/94HRMmTKa8vIKXXnphm/hefnkyP//8M0899RyPP/4077wzk9mzZzF06DC8Xi8vvfQi9957OzfccAstWpRsVfbChV9yww03M378C7z88iTatGnL2LHj6dZtb2bMeINAwM+7777DI488xvjxLzBw4JFMmfIiFRUV3HnnLdxxx72MG/fMVvNP3X77TZxyymk89dRErrjiGkaO/DMVFalfWtKYhggEw+T5vBTkp+ctPGdaFPn79K/1U3+6r/qZOvVVBg8+BoCjjjqaUaNu4oILLq16/uOPP+TXvz4Jj8dDp06d6d27LwBz537C4MHHUFjo3LJ//PEnMm3aaxx++ADatm1H585ddlj2oYc69e/UqTP7738gRUVFlJZ2we/fVFVGvKunTZs2DBx4BPPmzaVbt72rznH00ceycOECXnhhAt9+u5QNGzYQDG4GoEePnnTtujsAxx57HP/+9xQGDfrlVvF9+unHHHfcCfh8Pnw+H0cfPYS5cz/i8MMH8Je/3Mzw4cM46aRTOOigHtvEv+eee9Gxo3NxXOvWbejTx+mp7NixE5s2baSkpJRbb72DGTPeYPnyZXz44Wz23lv45puvad++jN133wNwkujjj/+dzZs38/333zNo0C8BOOCAA2nVqhXLln23VZ2NyTb+YDhtM8dCDiWKbLBu3VrmzHmfxYsX8eKLE4nFYmzatHGrQe3t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", + "image/png": "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cdx771i6dRPmzv2CsrIyrr76H0ye/CJLlvzMaaedwaBBZ1FaWspdd93K//73I16vl9NPP5ujjz5ui/j9/mLuuOMWiopWsmpVET169GTUqJuZN+8rJk58DJ8vi5UrV7D77ntw/fWjWb161Rbx3Xvvg9x//7+YO/dLPB448shjOPvsIbz88gt8+OH7PPjgY8yf/w133DGGiROf5brrrqlaA+PppycSCsHvv//KIYccTuPGjfnkk48IhUKMG3cfLVu2YsqUF5kxYzqlpSV4vV7GjLmDnXbqwhdffM79999DTk4OnTvvVNWepUt/YezY29i4cQN5eflcffVwdtttj+3692BMohWHS4wnqUeRqgl3FwEPq2oZgKoWA8eEXxSRfwETiSNRuFPRt7BypZesLKfTVOn1bLV41vYW1fJ6PVXn2ZbZs2fTvn17dt65CwcddCivv/4KV1xxNQA+n5fXX3+FsrJSXnppKitWLOesswbh83n54ovZzJr1MU8++RxZWVn885//4I03XuHAAwewdOkvvPLKQ3To0IE333wdj8fD8cefwPTpbzB06DBEuuHxePB6PUya9DKPP/4o9913N88++yJr165l8OAzOOusc3jiicdo3rw5zz8/mXXr1nL++YPp3r07u+7arSr+OXNmIyLceefdVFRUcMYZJ/PTT4rP5+WHH77n6aefp1OnzowceT2vvjqZQw45bIv4Jk9+iaKilTz33ItUVJRz6aUXseuuu3L66WfwyScf8tprk3n55RcZPXoMTZs2wePx4PM5f7cLFnzP88+/TLNmzTj66IFceeU1PPXUc9xyy4188MG7HHfcCXzyyUc88sh48vLyeOyxR3j11clceeU13HbbTTz44H/o0mVnbrvt5qr3/NZbb+Ccc4Zw6KGH89138xk16npeeunVLarjOu+xl8LCJtv17yQdNcQ2xao+tz3k8ZLl87Bjx+a1+vyKt+2pShR/BY4IPxCRTsBAVZ3oPuUBKuI5YE21noLBYFUtH1/XA8nveuCf9qurWkexHuONN17j8MOPIBAIcthhAxkzZjRDh14CQGVlkDlzPuP440+isjJEYWE7evfuQ2VlkC+++ILDDz+SrCznA+yYY47nrbem0bdvP1q0aEmbNu0IBIIEgyFCoRCBQJBQKERlZbDq9/32O5BAIEibNu3Yffe9yMrKpX37DmzcuJFA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", "text/plain": [ "
" ] diff --git a/TP2/optimalidad.py b/TP2/optimalidad.py index 3a4711a..1fc2597 100644 --- a/TP2/optimalidad.py +++ b/TP2/optimalidad.py @@ -1,13 +1,10 @@ from empaquetar_aprox import empaquetar_aprox from empaquetar_bt import empaquetar_bt -from random import uniform +from utils import generar_objetos OBJETOS_POR_SIMULACION = 15 SIMULACIONES = 1000 -def generar_objetos(n): - return [round(uniform(0, 1), 3) for _ in range(n)] - def error_relativo(solucion_optima, solucion_aproximada): return abs(solucion_aproximada - solucion_optima) / solucion_optima * 100 diff --git a/TP2/utils.py b/TP2/utils.py index 041551f..b81b940 100644 --- a/TP2/utils.py +++ b/TP2/utils.py @@ -1,5 +1,10 @@ from math import isclose +from random import uniform def solucion_valida(suma_solucion: int) -> bool: - return suma_solucion <= 1 or isclose(suma_solucion, 1) \ No newline at end of file + return suma_solucion <= 1 or isclose(suma_solucion, 1) + + +def generar_objetos(n: int, n_decimales: int = 3): + return [round(uniform(0, 1), n_decimales) for _ in range(n)] From 57e8bada57a6a28b51e53e5c631dfdfd0f898788 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Sun, 4 Jun 2023 15:08:43 -0300 Subject: [PATCH 12/23] Fix aprox --- TP2/empaquetar_aprox.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TP2/empaquetar_aprox.py b/TP2/empaquetar_aprox.py index cf44d69..73f5fb2 100644 --- a/TP2/empaquetar_aprox.py +++ b/TP2/empaquetar_aprox.py @@ -11,5 +11,7 @@ def empaquetar_aprox(objetos: list): paquetes.append(paquete_actual) paquete_actual = [objeto] + paquetes.append(paquete_actual) + return paquetes From 8e026d5e6d790e3e1292b092214dc3a7b25264a5 Mon Sep 17 00:00:00 2001 From: Ian Shih Date: Sun, 4 Jun 2023 15:58:40 -0300 Subject: [PATCH 13/23] Relacion entre solucion aproximada y backtracking Co-authored-by: Manuel Sanchez --- TP2/optimalidad.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/TP2/optimalidad.py b/TP2/optimalidad.py index 1fc2597..280404d 100644 --- a/TP2/optimalidad.py +++ b/TP2/optimalidad.py @@ -12,6 +12,8 @@ def main(): soluciones_optimas = [] soluciones_aproximadas = [] error_relativo_total = 0 + + relaciones_total = 0 for i in range(SIMULACIONES): print("Simulacion", i + 1) objetos = generar_objetos(OBJETOS_POR_SIMULACION) @@ -22,10 +24,20 @@ def main(): soluciones_optimas.append(len(empaquetar_bt(objetos))) print(f"Solucion optima: {soluciones_optimas[-1]}") + relaciones_total += soluciones_aproximadas[-1] / soluciones_optimas[-1] + + print("Relacion entre soluciones:", soluciones_aproximadas[-1] / soluciones_optimas[-1]) + + suma_total = sum(objetos) + + assert((suma_total / len(objetos)) <= (soluciones_aproximadas[-1] / soluciones_optimas[-1])) + + error_relativo_total += error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1]) print(f"Error relativo: {error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1])}%\n") print(f"Error relativo promedio: {error_relativo_total / len(soluciones_optimas)}%") + print(f"Relacion entre aproximacion promedio: {relaciones_total / len(soluciones_optimas)}") if __name__ == '__main__': main() From 7d92ae282b105c55fe2af3682e8f6e65d308b438 Mon Sep 17 00:00:00 2001 From: Ian Shih Date: Sun, 4 Jun 2023 19:41:11 -0300 Subject: [PATCH 14/23] Update README --- TP2/README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/TP2/README.md b/TP2/README.md index 33a64cc..b13eb5a 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -8,3 +8,32 @@ | -------------- | ------ | ------------------- | | Manuel Sanchez | 107951 | msanchezf@fi.uba.ar | | Ian Shih | 108349 | ishih@fi.uba.ar | + +### Clase de complejidad +Vamos a considerar el problema de empaquetamiento como un problema de decision. Es decir, dada una lista de objetos, se busca responder la siguiente pregunta: "¿Se puede empaquetar dichos objetos usando a lo sumo $k$ envases de tamaño 1?". + +Para demostrar que un problema es NP-Completo se deben cumplir 2 condiciones: + +Dado un problema $X$: +* Una solucion al problema $X$ se puede verificar en tiempo polinomial. +* Otro problema $Y$ NP-Completo se puede reducir al problema $X$, de forma que $X \ge_p Y$. Es decir, resolver $X$ es al menos tan dificil como resolver $Y$. + +Analicemos si una solucion a nuestro problema se puede verificar en tiempo polinomial. Como entrada, esperamos recibir una lista de paquetes, y un valor $k$ que representa la cantidad de paquetes. Para saber si una solucion es valida, lo primero que verificamos es que la suma de objetos de cada paquete no supere 1. Una vez verificado esto, nos fijamos si la cantidad de paquetes es menor o igual a $k$. En codigo seria asi: + +```py +for paquete in paquetes: + if sum(paquete) > 1: + return False + +return len(paquetes) <= k +``` + +Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo + +### Complejidad temporal +Con el fin de simplificar el analisis, consideraremos a nuestro algoritmo como si fuera un algoritmo de _fuerza bruta_, es decir, que no realiza ningun tipo de poda del arbol de llamados recursivos con el fin de acelerar la velocidad de ejecucion. La complejidad real del algoritmo va a ser similar a la obtenida gracias al analisis (mas/menos ciertas constantes). + +Para simplificar el analisis, podemos asumir que el algoritmo de fuerza bruta crea $n$ paquetes, $n$ siendo la cantidad de objetos a empaquetar. Esto se puede hacer debido a que una de las soluciones a la que va a llegar fuerza bruta, sera la solucion donde cada paquete tendra un solo objeto. + +Cada vez que tengamos que agregar un nuevo objeto a un paquete, nuestro algoritmo prueba si el objeto se puede colocar en cada uno de mis n paquetes, a la vez, probamos si el resto de los paquetes agregados, se pueden distribuir a otros paquetes + From 030e76b234f4929e9a6c28f39db9cd0ce5c17eff Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 19:03:46 -0300 Subject: [PATCH 15/23] Finish TP2 Co-authored-by: Ian Shih --- TP2/README.md | 157 +++++++++++++++++++++++++++-- TP2/empaquetar_aprox.py | 10 +- TP2/empaquetar_aprox_2.py | 14 +++ TP2/empaquetar_greedy.py | 4 - TP2/graficos/complejidad_aprox.png | Bin 0 -> 30244 bytes TP2/graficos/complejidad_bt.png | Bin 0 -> 19481 bytes TP2/main.py | 5 +- TP2/mediciones.ipynb | 67 +++++++++--- TP2/optimalidad.py | 61 +++++++---- 9 files changed, 271 insertions(+), 47 deletions(-) create mode 100644 TP2/empaquetar_aprox_2.py delete mode 100644 TP2/empaquetar_greedy.py create mode 100644 TP2/graficos/complejidad_aprox.png create mode 100644 TP2/graficos/complejidad_bt.png diff --git a/TP2/README.md b/TP2/README.md index b13eb5a..fff60fc 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -9,7 +9,8 @@ | Manuel Sanchez | 107951 | msanchezf@fi.uba.ar | | Ian Shih | 108349 | ishih@fi.uba.ar | -### Clase de complejidad +### Algoritmo de Backtracking +#### Clase de complejidad Vamos a considerar el problema de empaquetamiento como un problema de decision. Es decir, dada una lista de objetos, se busca responder la siguiente pregunta: "¿Se puede empaquetar dichos objetos usando a lo sumo $k$ envases de tamaño 1?". Para demostrar que un problema es NP-Completo se deben cumplir 2 condiciones: @@ -28,12 +29,156 @@ for paquete in paquetes: return len(paquetes) <= k ``` -Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo +Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo. -### Complejidad temporal -Con el fin de simplificar el analisis, consideraremos a nuestro algoritmo como si fuera un algoritmo de _fuerza bruta_, es decir, que no realiza ningun tipo de poda del arbol de llamados recursivos con el fin de acelerar la velocidad de ejecucion. La complejidad real del algoritmo va a ser similar a la obtenida gracias al analisis (mas/menos ciertas constantes). +Por otro lado, proponemos reducir el problema de Subset Sum al problema de empaquetamiento. Este problema trata sobre, dado un set de numeros $S$ y un numero objetivo $n$, buscar si existe un subset de $S$ cuyos objetos sumen exactamente $n$. Por ejemplo: +```txt +S = [1, 8, 16, 4, 10, 9] +n = 15 +``` + +Para poder reducir esto al problema de empaquetamiento, lo primero que hay que hacer es filtrar a todos aquellos numeros que sean mayores que $n$. En nuestro caso: +```txt +[1, 8, 16, 4, 10, 9] --> [1, 8, 4, 10, 9] +``` + +Debido a que el problema de empaquetamiento solo trabaja con numeros del 0 al 1, dividimos todos los numeros restantes por $n$. +```txt +n = 15 +[1, 8, 4, 10, 9] --> [1/15, 8/15, 4/15, 10/15, 9/15] --> [0.067, 0.533, 0.267, 0.667, 0.6] +``` + +Luego, aplicamos el algoritmo de empaquetamiento. Si conseguimos una solucion en la que un paquete este completo (que sus objetos sumen exactamente 1), entonces significa que efectivamente existe un subset de $S$ tal que sus objetos sumen $n$. + +Ejemplo del algoritmo de reduccion +```py +def reducir_a_objetos(set, n): + nuevo = [] + for elem in set: + if elem > n: continue + nuevo.push(elem / n) + return nuevo +``` + +#### Complejidad temporal +Con el fin de simplificar el analisis, consideraremos a nuestro algoritmo de _backtracking_ como si fuera un algoritmo de _fuerza bruta_, es decir, que no realiza ningun tipo de poda del arbol de llamados recursivos con el fin de acelerar la velocidad de ejecucion. La complejidad real del algoritmo de _backtracking_ va a ser similar a la obtenida gracias al analisis (mas/menos ciertas constantes). + +La peor solucion posible, es decir, la que mas paquetes ocupe será la que tenga un objeto por paquete. Por lo tanto, la cantidad total de paquetes seria $n$, siendo esta la cantidad de objetos a empaquetar. Es por ello que proponemos que, inicialmente, el algoritmo crea los $n$ paquetes en donde intentara almacenar los $n$ productos. No necesariamente se usaran los $n$ paquetes, pero de esta forma se contemplan todas las soluciones (la cantidad de paquetes es siempre menor o igual a la cantidad de productos). + +El algoritmo de _fuerza bruta_ prueba todas las combinaciones posibles, incluso las que son invalidas (las que contienen paquetes cuyos objetos sumen mas de 1). La cantidad de llamados recursivos sera igual a las combinaciones posibles de soluciones. Por ejemplo, si tenemos: +```txt +S = [0.1, 0.2, 0.3] +``` + +Entonces, las soluciones posibles se ven algo asi: + +```txt +[[0.1, 0.2, 0.3], [], []] +[[0.1, 0.2], [0.3], []] +[[0.1, 0.2], [], [0.3]] +[[0.1, 0.3], [0.2], []] +[[0.1], [0.2, 0.3], []] +[[0.1], [0.2], [0.3]] +[[0.1], [], [0.2, 0.3]] +[[0.2, 0.3], [0.1], []] +... +[[], [], [0.1, 0.2, 0.3]] +``` + +Cada elemento puede ir en $n$ paquetes distintos. Al tener $n$ objetos, la cantidad total de combinaciones es $n^n$. Debido a que el algoritmo prueba todas las combinaciones posibles y las operaciones que hace (sin considerar la recursion) se resuelven en $O(1)$, podemos concluir que el algoritmo tiene una complejidad de O($n^n$) + + +### Algoritmo aproximado +#### Complejidad temporal +La complejidad temporal del algoritmo aproximado es $O(N)$ debido a que se iteran todos los objetos y se ejecutan instrucciones $O(1)$ dentro del ciclo. + +#### Analisis de aproximacion +Para calcular la cota $r(A)$ para nuestro algoritmo de aproximacion, se consideraran los siguientes puntos: + +* $A(I)$ es la cantidad de paquetes generados por nuestro algoritmo de aproximacion +* $z(I)$ es la cantidad de paquetes generados por nuestro algoritmo optimo + + +* La suma de los objetos de 2 paquetes adyacentes es superior a 1. Esto es debido a que si se creo un paquete nuevo, necesariamente el primer objeto del nuevo paquete no entraba en el paquete anterior. Sea $P_i$ la suma de los elementos del paqute $i$, tenemos que: +$$ +P_i + P_{i+1} > 1 +$$ + +A raiz del ultimo punto, deducimos que la suma de los objetos de todos los paquetes es mayor a $\frac{A(I)}{2}$. +$$ +P_1 + P_2 > 1 +\\ +P_3 + P_4 > 1 +\\ +P_5 + P_6 > 1 +\\ +\vdots +\\ +P_{A(I)-1} + P_{A(I)} > 1 +$$ +Al sumar todas las desigualdades, obtenemos que: +$$ +\sum_{i=1}^{A(I)} P_i > \frac{A(I)}{2} +$$ + +Asimismo, sabemos que el mejor empaquetamiento posible es aquel en el cual los elementos llenan todos los paquetes de forma perfecta. Esta es la mejor solucion a la que puede llegar el algoritmo optimo. Sea $x_i$ el valor del objeto $i$, y $n$ la cantidad total de objetos: +$$ +z(I) \ge \sum_{i=1}^{n} a_i = \sum_{i=1}^{A(I)} P_i +$$ + +Con todo lo planteado anteriormente, llegamos a la siguiente inecuacion +$$ +z(I) \ge \sum_{i=1}^{n} a_i > \frac{A(I)}{2} +$$ + +Por lo tanto: +$$ +z(I) \ge \frac{A(I)}{2} \Rightarrow \frac{A(I)}{z(I)} \le 2 = r(A) +$$ + +En conclusion, el algoritmo provisto es una 2-aproximacion de la solucion optima. + +### Algoritmo aproximado 2 +Para nuestro algoritmo aproximado 2, se hacen los siguientes pasos: +* Se ordena de mayor a menor la lista de objetos: +* Por cada objeto, nos fijamos si entra en algun paquete: + * Si entra lo agregamos, y pasamos al siguiente objeto. + * Si no entra en ningun paquete, se crea un paquete nuevo, se agrega el objeto y pasamos al siguiente objeto. + +#### Complejidad temporal +La complejidad temporal de este algoritmo es $O(n^2)$. Esto se debe a que el peor caso posible es aquel en el que cada objeto ocupa un paquete entero. Por lo tanto, cada objeto al ser insertado debe pasar por cada paquete probando si entra o no. Al tener $n$ paquetes y $n$ objetos, la complejidad final es $O(n^2)$. + +Debido a que la complejidad de la insercion de los objetos en los paquetes es mayor a la complejidad de ordenar los paquetes de mayor a menor (la cual es $O(n log n)$), esta no afecta a la notacion Big-O del algoritmo. + +### Comparaciones de optimalidad +Ejecutando el archivo `optimalidad.py` observamos los siguientes numeros + +Algoritmo aproximado: +* Error relativo promedio: 17.6471% +* Maximo r(A): 1.5714 +* Promedio r(A): 1.1764 + +Algoritmo aproximado 2: +* Error relativo promedio: 0.1206% +* Maximo r(A2): 1.25 +* Promedio r(A2): 1.0012 + +A partir de esto podemos sacar las siguientes conclusiones +* La cota calculada para el algoritmo aproximado se cumple ya que el maximo $r(A)$ calculado es menor a 2. +* A pesar de ser una 2-aproximacion, la solucion obtenida por el algoritmo aproximado es, en promedio, tan solo un 17% mayor a la solucion optima. +* El algoritmo aproximado 2 obtiene mejores resultados que el algoritmo aproximado 1, al obtener un menor error relativo y un menor $r(A2)$. + + +### Comparaciones de tiempos de ejecucion + +![Grafico de todos los algoritmos](graficos/complejidad_bt.png) + +En el grafico, es posible observar como la forma de crecimiento del algoritmo optimo es mucho mas elevada que la de los algoritmos aproximados, los cuales apenas pueden ser observados como una linea horizontal sobre el eje. Esto es un claro indicio del crecimiento exponencial que presenta el algoritmo optimo, a diferencia de las complejidades polinomiales que tienen las aproximaciones. El crecimiento exponencial implica que, al agregar mas elementos, el tiempo de ejecucion aumente de forma muy elevada. + +Debido a que la complejidad del algoritmo optimo es muy alta, no es posible discernir las formas de crecimiento de cada algoritmo. Por lo tanto, decidimos realizar un grafico solo con los algoritmos mas "veloces", es decir con las aproximaciones, de forma que podamos compararlas entre ellas. -Para simplificar el analisis, podemos asumir que el algoritmo de fuerza bruta crea $n$ paquetes, $n$ siendo la cantidad de objetos a empaquetar. Esto se puede hacer debido a que una de las soluciones a la que va a llegar fuerza bruta, sera la solucion donde cada paquete tendra un solo objeto. +![Grafico de los algoritmos aproximados](graficos/complejidad_aprox.png) -Cada vez que tengamos que agregar un nuevo objeto a un paquete, nuestro algoritmo prueba si el objeto se puede colocar en cada uno de mis n paquetes, a la vez, probamos si el resto de los paquetes agregados, se pueden distribuir a otros paquetes +En este grafico es mas facil diferenciar las curvas de los algoritmos aproximados. Podemos ver que la curva naranja, perteneciente al algoritmo aproximado 2, crece mas rapidamente que la curva azul, del algoritmo aproximado 1 (el provisto por la catedra). +Esta diferencia se debe a que el algoritmo aproximado 2, tiene una complejidad de $O(n^2)$, mientras que la del algoritmo aproximado 1 es $O(n)$. Es decir, el tiempo de ejecucion del algoritmo 2 crece de forma cuadratica, mientras que el del algoritmo 1 es lineal, resultando en esta diferencia marcada en la forma de crecimiento. \ No newline at end of file diff --git a/TP2/empaquetar_aprox.py b/TP2/empaquetar_aprox.py index 73f5fb2..7b57efe 100644 --- a/TP2/empaquetar_aprox.py +++ b/TP2/empaquetar_aprox.py @@ -3,15 +3,15 @@ def empaquetar_aprox(objetos: list): paquetes = [] - paquete_actual = [] + paquete_actual = [[], 0] for objeto in objetos: - if solucion_valida(sum(paquete_actual) + objeto): - paquete_actual.append(objeto) + if solucion_valida(paquete_actual[1] + objeto): + paquete_actual[0].append(objeto) + paquete_actual[1] += objeto else: paquetes.append(paquete_actual) - paquete_actual = [objeto] + paquete_actual = [[objeto], objeto] paquetes.append(paquete_actual) return paquetes - diff --git a/TP2/empaquetar_aprox_2.py b/TP2/empaquetar_aprox_2.py new file mode 100644 index 0000000..13a0fc8 --- /dev/null +++ b/TP2/empaquetar_aprox_2.py @@ -0,0 +1,14 @@ +from utils import solucion_valida + +def empaquetar_aprox_2(objetos: list): + objetos_ordenados = sorted(objetos, reverse=True) + solucion = [] + for objeto in objetos_ordenados: + for paquete in solucion: + if solucion_valida(paquete[1] + objeto): + paquete[0].append(objeto) + paquete[1] += objeto + break + else: + solucion.append([[objeto], objeto]) + return solucion diff --git a/TP2/empaquetar_greedy.py b/TP2/empaquetar_greedy.py deleted file mode 100644 index c3648a2..0000000 --- a/TP2/empaquetar_greedy.py +++ /dev/null @@ -1,4 +0,0 @@ -def empaquetar_greedy(objetos: list, n: int = 1): - solucion = [] - - return len(solucion) \ No newline at end of file diff --git a/TP2/graficos/complejidad_aprox.png b/TP2/graficos/complejidad_aprox.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5e0e481c5818a6a982c03b15b6ebb784468949 GIT binary patch literal 30244 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

S|nS#d< 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" ] }, - "metadata": { - "needs_background": "light" + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cases = [[generar_objetos(i) for _ in range(N_DATASETS)] for i in range(CASES)]\n", + "plot_comparison(cases, \"Tiempo de ejecucion\" ,\"Cantidad de objetos\")" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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c4wZMwZJkjh8+DA2m63ccjUaDTabrcQH6z333ENERAQmkwmTyURkZCRQOMng2LFjvPzyy4wYMYKkpCQuXbqELMsMHDiQX3/9latXrwKwefPmUq9Z3nGDBw9m48aN9ja+++67vPLKKyXKGDx4MJs2bbL30tatW0efPn3Q6XRAYVZkRVHIyspi+/btJbIEl3cdtVptDyplXUelUjFs2DDy8vJ45JFHWLhwIefOnSsW9IS6SfRwhHph4cKFrFq1iocffhi1Wo3ZbOb+++9nxowZQOE37ueee46GDRvi7OxMnz59uHTpUrllent706lTJ0aPHs0XX3xh3/7www9z6dIlQkJCcHd3p3nz5gA0bNiQp556igcffBB3d3c8PDzo1asXcXFxDBgwgFmzZvHYY4/h6upaZmbe9u3bl3ncpEmTSEpK4i9/+QuSJOHv718s23WRiRMncuXKFSZNmoQsyzRv3pzw8HD7fjc3NyZMmEBBQQHTpk2jX79+XL58uULXGTBgADNmzECr1TJ37txSr6PRaJgzZw4vv/wyGo0GSZJ488037QFPqLtEtmhBEBw6efIkTzzxBPv27avpqgh3MTGkJghCuX744QeefPJJJk+eXNNVEe5yoocjCIIgVAvRwxEEQRCqhQg4giAIQrUQAUcQBEGoFiLgCIIgCNVCBBxBEAShWoiAIwiCIFSL/wdlb3NimlxSUQAAAABJRU5ErkJggg==", + "text/plain": [ + "

" + ] }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "cases_k_constant = [generar_objetos(i) for i in range(25)]\n", - "plot_comparison(cases_k_constant, \"Tiempo de ejecucion\" ,\"Cantidad de objetos\")" + "cases_aprox_only = [[generar_objetos(i)] for i in range(CASES_APROX)]\n", + "\n", + "plot_comparison_aprox_only(cases_aprox_only, \"Tiempo de ejecucion\" ,\"Cantidad de objetos\")" ] } ], diff --git a/TP2/optimalidad.py b/TP2/optimalidad.py index 280404d..56c98bf 100644 --- a/TP2/optimalidad.py +++ b/TP2/optimalidad.py @@ -1,43 +1,70 @@ from empaquetar_aprox import empaquetar_aprox from empaquetar_bt import empaquetar_bt +from empaquetar_aprox_2 import empaquetar_aprox_2 from utils import generar_objetos OBJETOS_POR_SIMULACION = 15 SIMULACIONES = 1000 +CONSTANTE_DE_APROXIMACION = 2 def error_relativo(solucion_optima, solucion_aproximada): return abs(solucion_aproximada - solucion_optima) / solucion_optima * 100 +def empaquetar(objetos, empaquetamiento, soluciones, label): + soluciones.append(len(empaquetamiento(objetos))) + print(f"{label}: {soluciones[-1]}") + +def calcular_r(solucion_aproximada, solucion_optima, label, relaciones): + r = solucion_aproximada / solucion_optima + print(f"{label}: {r}") + relaciones.append(r) + +def imprimir_resultados_r(relaciones, label): + print(f"Maximo {label}: {max(relaciones)}") + print(f"Promedio {label}: {sum(relaciones)/len(relaciones)}") + +def calcular_error(solucion_optima, solucion_aproximada, label): + error = error_relativo(solucion_optima, solucion_aproximada) + print(f"{label}: {error_relativo(solucion_optima, solucion_aproximada)}%") + + return error + def main(): soluciones_optimas = [] soluciones_aproximadas = [] + soluciones_aproximadas_2 = [] + + error_relativo_total = 0 + error_relativo_total_2 = 0 - relaciones_total = 0 + relaciones = [] + relaciones_2 = [] + for i in range(SIMULACIONES): print("Simulacion", i + 1) objetos = generar_objetos(OBJETOS_POR_SIMULACION) - soluciones_aproximadas.append(len(empaquetar_aprox(objetos))) - print(f"Solucion aproximada: {soluciones_aproximadas[-1]}") - - soluciones_optimas.append(len(empaquetar_bt(objetos))) - print(f"Solucion optima: {soluciones_optimas[-1]}") - - relaciones_total += soluciones_aproximadas[-1] / soluciones_optimas[-1] + empaquetar(objetos, empaquetar_aprox, soluciones_aproximadas, "Solucion (aproximada)") + empaquetar(objetos, empaquetar_bt, soluciones_optimas, "Solucion optima") + empaquetar(objetos, empaquetar_aprox_2, soluciones_aproximadas_2, "Solucion (aproximada 2)") - print("Relacion entre soluciones:", soluciones_aproximadas[-1] / soluciones_optimas[-1]) + calcular_r(soluciones_aproximadas[-1], soluciones_optimas[-1], "r(A)", relaciones) + calcular_r(soluciones_aproximadas_2[-1], soluciones_optimas[-1], "r(A2)", relaciones_2) - suma_total = sum(objetos) + assert((soluciones_aproximadas[-1] / soluciones_optimas[-1]) <= CONSTANTE_DE_APROXIMACION) + assert((soluciones_aproximadas[-1] / soluciones_optimas[-1]) >= 1) - assert((suma_total / len(objetos)) <= (soluciones_aproximadas[-1] / soluciones_optimas[-1])) - - - error_relativo_total += error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1]) - print(f"Error relativo: {error_relativo(soluciones_optimas[-1], soluciones_aproximadas[-1])}%\n") + error_relativo_total += calcular_error(soluciones_optimas[-1], soluciones_aproximadas[-1], "Error relativo (aproximada)") + error_relativo_total_2 += calcular_error(soluciones_optimas[-1], soluciones_aproximadas_2[-1], "Error relativo (aproximada 2)") + print() - print(f"Error relativo promedio: {error_relativo_total / len(soluciones_optimas)}%") - print(f"Relacion entre aproximacion promedio: {relaciones_total / len(soluciones_optimas)}") + print("===== Resultados =====") + print(f"Error relativo promedio (aproximado): {error_relativo_total / len(soluciones_optimas)}%") + print(f"Error relativo promedio (aproximado 2): {error_relativo_total_2 / len(soluciones_optimas)}%") + imprimir_resultados_r(relaciones, "r(A)") + imprimir_resultados_r(relaciones_2, "r(A2)") + if __name__ == '__main__': main() From b3dd7308ecc96ae319f7d18da4dc1a1d76bdefbd Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 19:07:52 -0300 Subject: [PATCH 16/23] Fix complexity aprox algorithm --- TP2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TP2/README.md b/TP2/README.md index fff60fc..564d502 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -90,7 +90,7 @@ Cada elemento puede ir en $n$ paquetes distintos. Al tener $n$ objetos, la canti ### Algoritmo aproximado #### Complejidad temporal -La complejidad temporal del algoritmo aproximado es $O(N)$ debido a que se iteran todos los objetos y se ejecutan instrucciones $O(1)$ dentro del ciclo. +La complejidad temporal del algoritmo aproximado de la catedra es $O(N)$. Esto se debe a que hay un unico ciclo `for` que recorre la lista de objetos. Si un objeto no entra en el paquete actual, se cierra el paquete y se agrega a la lista de paquetes, luego se crea un paquete nuevo e inserta el objeto alli. Gracias a esta simple logica, el algoritmo solo recorre la lista de paquetes una vez, resultando en la complejidad mencionada. #### Analisis de aproximacion Para calcular la cota $r(A)$ para nuestro algoritmo de aproximacion, se consideraran los siguientes puntos: From 7f1396c201e9a34123814c2816706234652f512e Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 19:08:36 -0300 Subject: [PATCH 17/23] Format --- TP2/README.md | 67 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/TP2/README.md b/TP2/README.md index 564d502..d8d0543 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -10,14 +10,17 @@ | Ian Shih | 108349 | ishih@fi.uba.ar | ### Algoritmo de Backtracking + #### Clase de complejidad + Vamos a considerar el problema de empaquetamiento como un problema de decision. Es decir, dada una lista de objetos, se busca responder la siguiente pregunta: "¿Se puede empaquetar dichos objetos usando a lo sumo $k$ envases de tamaño 1?". Para demostrar que un problema es NP-Completo se deben cumplir 2 condiciones: Dado un problema $X$: -* Una solucion al problema $X$ se puede verificar en tiempo polinomial. -* Otro problema $Y$ NP-Completo se puede reducir al problema $X$, de forma que $X \ge_p Y$. Es decir, resolver $X$ es al menos tan dificil como resolver $Y$. + +- Una solucion al problema $X$ se puede verificar en tiempo polinomial. +- Otro problema $Y$ NP-Completo se puede reducir al problema $X$, de forma que $X \ge_p Y$. Es decir, resolver $X$ es al menos tan dificil como resolver $Y$. Analicemos si una solucion a nuestro problema se puede verificar en tiempo polinomial. Como entrada, esperamos recibir una lista de paquetes, y un valor $k$ que representa la cantidad de paquetes. Para saber si una solucion es valida, lo primero que verificamos es que la suma de objetos de cada paquete no supere 1. Una vez verificado esto, nos fijamos si la cantidad de paquetes es menor o igual a $k$. En codigo seria asi: @@ -32,17 +35,20 @@ return len(paquetes) <= k Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo. Por otro lado, proponemos reducir el problema de Subset Sum al problema de empaquetamiento. Este problema trata sobre, dado un set de numeros $S$ y un numero objetivo $n$, buscar si existe un subset de $S$ cuyos objetos sumen exactamente $n$. Por ejemplo: + ```txt S = [1, 8, 16, 4, 10, 9] n = 15 ``` Para poder reducir esto al problema de empaquetamiento, lo primero que hay que hacer es filtrar a todos aquellos numeros que sean mayores que $n$. En nuestro caso: + ```txt [1, 8, 16, 4, 10, 9] --> [1, 8, 4, 10, 9] ``` Debido a que el problema de empaquetamiento solo trabaja con numeros del 0 al 1, dividimos todos los numeros restantes por $n$. + ```txt n = 15 [1, 8, 4, 10, 9] --> [1/15, 8/15, 4/15, 10/15, 9/15] --> [0.067, 0.533, 0.267, 0.667, 0.6] @@ -51,6 +57,7 @@ n = 15 Luego, aplicamos el algoritmo de empaquetamiento. Si conseguimos una solucion en la que un paquete este completo (que sus objetos sumen exactamente 1), entonces significa que efectivamente existe un subset de $S$ tal que sus objetos sumen $n$. Ejemplo del algoritmo de reduccion + ```py def reducir_a_objetos(set, n): nuevo = [] @@ -61,11 +68,13 @@ def reducir_a_objetos(set, n): ``` #### Complejidad temporal + Con el fin de simplificar el analisis, consideraremos a nuestro algoritmo de _backtracking_ como si fuera un algoritmo de _fuerza bruta_, es decir, que no realiza ningun tipo de poda del arbol de llamados recursivos con el fin de acelerar la velocidad de ejecucion. La complejidad real del algoritmo de _backtracking_ va a ser similar a la obtenida gracias al analisis (mas/menos ciertas constantes). La peor solucion posible, es decir, la que mas paquetes ocupe será la que tenga un objeto por paquete. Por lo tanto, la cantidad total de paquetes seria $n$, siendo esta la cantidad de objetos a empaquetar. Es por ello que proponemos que, inicialmente, el algoritmo crea los $n$ paquetes en donde intentara almacenar los $n$ productos. No necesariamente se usaran los $n$ paquetes, pero de esta forma se contemplan todas las soluciones (la cantidad de paquetes es siempre menor o igual a la cantidad de productos). El algoritmo de _fuerza bruta_ prueba todas las combinaciones posibles, incluso las que son invalidas (las que contienen paquetes cuyos objetos sumen mas de 1). La cantidad de llamados recursivos sera igual a las combinaciones posibles de soluciones. Por ejemplo, si tenemos: + ```txt S = [0.1, 0.2, 0.3] ``` @@ -87,24 +96,27 @@ Entonces, las soluciones posibles se ven algo asi: Cada elemento puede ir en $n$ paquetes distintos. Al tener $n$ objetos, la cantidad total de combinaciones es $n^n$. Debido a que el algoritmo prueba todas las combinaciones posibles y las operaciones que hace (sin considerar la recursion) se resuelven en $O(1)$, podemos concluir que el algoritmo tiene una complejidad de O($n^n$) - ### Algoritmo aproximado + #### Complejidad temporal + La complejidad temporal del algoritmo aproximado de la catedra es $O(N)$. Esto se debe a que hay un unico ciclo `for` que recorre la lista de objetos. Si un objeto no entra en el paquete actual, se cierra el paquete y se agrega a la lista de paquetes, luego se crea un paquete nuevo e inserta el objeto alli. Gracias a esta simple logica, el algoritmo solo recorre la lista de paquetes una vez, resultando en la complejidad mencionada. #### Analisis de aproximacion + Para calcular la cota $r(A)$ para nuestro algoritmo de aproximacion, se consideraran los siguientes puntos: -* $A(I)$ es la cantidad de paquetes generados por nuestro algoritmo de aproximacion -* $z(I)$ es la cantidad de paquetes generados por nuestro algoritmo optimo +- $A(I)$ es la cantidad de paquetes generados por nuestro algoritmo de aproximacion +- $z(I)$ es la cantidad de paquetes generados por nuestro algoritmo optimo +La suma de los objetos de 2 paquetes adyacentes es superior a 1. Esto es debido a que si se creo un paquete nuevo, necesariamente el primer objeto del nuevo paquete no entraba en el paquete anterior. Sea $P_i$ la suma de los elementos del paqute $i$, tenemos que: -* La suma de los objetos de 2 paquetes adyacentes es superior a 1. Esto es debido a que si se creo un paquete nuevo, necesariamente el primer objeto del nuevo paquete no entraba en el paquete anterior. Sea $P_i$ la suma de los elementos del paqute $i$, tenemos que: $$ P_i + P_{i+1} > 1 $$ A raiz del ultimo punto, deducimos que la suma de los objetos de todos los paquetes es mayor a $\frac{A(I)}{2}$. + $$ P_1 + P_2 > 1 \\ @@ -116,22 +128,27 @@ P_5 + P_6 > 1 \\ P_{A(I)-1} + P_{A(I)} > 1 $$ + Al sumar todas las desigualdades, obtenemos que: + $$ \sum_{i=1}^{A(I)} P_i > \frac{A(I)}{2} $$ Asimismo, sabemos que el mejor empaquetamiento posible es aquel en el cual los elementos llenan todos los paquetes de forma perfecta. Esta es la mejor solucion a la que puede llegar el algoritmo optimo. Sea $x_i$ el valor del objeto $i$, y $n$ la cantidad total de objetos: + $$ z(I) \ge \sum_{i=1}^{n} a_i = \sum_{i=1}^{A(I)} P_i -$$ +$$ Con todo lo planteado anteriormente, llegamos a la siguiente inecuacion + $$ z(I) \ge \sum_{i=1}^{n} a_i > \frac{A(I)}{2} $$ Por lo tanto: + $$ z(I) \ge \frac{A(I)}{2} \Rightarrow \frac{A(I)}{z(I)} \le 2 = r(A) $$ @@ -139,35 +156,41 @@ $$ En conclusion, el algoritmo provisto es una 2-aproximacion de la solucion optima. ### Algoritmo aproximado 2 + Para nuestro algoritmo aproximado 2, se hacen los siguientes pasos: -* Se ordena de mayor a menor la lista de objetos: -* Por cada objeto, nos fijamos si entra en algun paquete: - * Si entra lo agregamos, y pasamos al siguiente objeto. - * Si no entra en ningun paquete, se crea un paquete nuevo, se agrega el objeto y pasamos al siguiente objeto. + +- Se ordena de mayor a menor la lista de objetos: +- Por cada objeto, nos fijamos si entra en algun paquete: + - Si entra lo agregamos, y pasamos al siguiente objeto. + - Si no entra en ningun paquete, se crea un paquete nuevo, se agrega el objeto y pasamos al siguiente objeto. #### Complejidad temporal + La complejidad temporal de este algoritmo es $O(n^2)$. Esto se debe a que el peor caso posible es aquel en el que cada objeto ocupa un paquete entero. Por lo tanto, cada objeto al ser insertado debe pasar por cada paquete probando si entra o no. Al tener $n$ paquetes y $n$ objetos, la complejidad final es $O(n^2)$. Debido a que la complejidad de la insercion de los objetos en los paquetes es mayor a la complejidad de ordenar los paquetes de mayor a menor (la cual es $O(n log n)$), esta no afecta a la notacion Big-O del algoritmo. ### Comparaciones de optimalidad + Ejecutando el archivo `optimalidad.py` observamos los siguientes numeros Algoritmo aproximado: -* Error relativo promedio: 17.6471% -* Maximo r(A): 1.5714 -* Promedio r(A): 1.1764 + +- Error relativo promedio: 17.6471% +- Maximo r(A): 1.5714 +- Promedio r(A): 1.1764 Algoritmo aproximado 2: -* Error relativo promedio: 0.1206% -* Maximo r(A2): 1.25 -* Promedio r(A2): 1.0012 + +- Error relativo promedio: 0.1206% +- Maximo r(A2): 1.25 +- Promedio r(A2): 1.0012 A partir de esto podemos sacar las siguientes conclusiones -* La cota calculada para el algoritmo aproximado se cumple ya que el maximo $r(A)$ calculado es menor a 2. -* A pesar de ser una 2-aproximacion, la solucion obtenida por el algoritmo aproximado es, en promedio, tan solo un 17% mayor a la solucion optima. -* El algoritmo aproximado 2 obtiene mejores resultados que el algoritmo aproximado 1, al obtener un menor error relativo y un menor $r(A2)$. +- La cota calculada para el algoritmo aproximado se cumple ya que el maximo $r(A)$ calculado es menor a 2. +- A pesar de ser una 2-aproximacion, la solucion obtenida por el algoritmo aproximado es, en promedio, tan solo un 17% mayor a la solucion optima. +- El algoritmo aproximado 2 obtiene mejores resultados que el algoritmo aproximado 1, al obtener un menor error relativo y un menor $r(A2)$. ### Comparaciones de tiempos de ejecucion @@ -179,6 +202,6 @@ Debido a que la complejidad del algoritmo optimo es muy alta, no es posible disc ![Grafico de los algoritmos aproximados](graficos/complejidad_aprox.png) -En este grafico es mas facil diferenciar las curvas de los algoritmos aproximados. Podemos ver que la curva naranja, perteneciente al algoritmo aproximado 2, crece mas rapidamente que la curva azul, del algoritmo aproximado 1 (el provisto por la catedra). +En este grafico es mas facil diferenciar las curvas de los algoritmos aproximados. Podemos ver que la curva naranja, perteneciente al algoritmo aproximado 2, crece mas rapidamente que la curva azul, del algoritmo aproximado 1 (el provisto por la catedra). -Esta diferencia se debe a que el algoritmo aproximado 2, tiene una complejidad de $O(n^2)$, mientras que la del algoritmo aproximado 1 es $O(n)$. Es decir, el tiempo de ejecucion del algoritmo 2 crece de forma cuadratica, mientras que el del algoritmo 1 es lineal, resultando en esta diferencia marcada en la forma de crecimiento. \ No newline at end of file +Esta diferencia se debe a que el algoritmo aproximado 2, tiene una complejidad de $O(n^2)$, mientras que la del algoritmo aproximado 1 es $O(n)$. Es decir, el tiempo de ejecucion del algoritmo 2 crece de forma cuadratica, mientras que el del algoritmo 1 es lineal, resultando en esta diferencia marcada en la forma de crecimiento. From 36fcf433b9dabcb1064f7fdd9ba9d5a21fe66efe Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 19:09:11 -0300 Subject: [PATCH 18/23] Fix latex not displaying correctly --- TP2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TP2/README.md b/TP2/README.md index d8d0543..780a2ba 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -168,7 +168,7 @@ Para nuestro algoritmo aproximado 2, se hacen los siguientes pasos: La complejidad temporal de este algoritmo es $O(n^2)$. Esto se debe a que el peor caso posible es aquel en el que cada objeto ocupa un paquete entero. Por lo tanto, cada objeto al ser insertado debe pasar por cada paquete probando si entra o no. Al tener $n$ paquetes y $n$ objetos, la complejidad final es $O(n^2)$. -Debido a que la complejidad de la insercion de los objetos en los paquetes es mayor a la complejidad de ordenar los paquetes de mayor a menor (la cual es $O(n log n)$), esta no afecta a la notacion Big-O del algoritmo. +Debido a que la complejidad de la insercion de los objetos en los paquetes es mayor a la complejidad de ordenar los paquetes de mayor a menor (la cual es $O(n log n)$ ), esta no afecta a la notacion Big-O del algoritmo. ### Comparaciones de optimalidad From 0b52725bebcee4c98a0bcb06f0969923d2ad4ffe Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 20:44:38 -0300 Subject: [PATCH 19/23] Fix latex display error on github --- TP2/README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/TP2/README.md b/TP2/README.md index 780a2ba..3ffecaf 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -115,17 +115,21 @@ $$ P_i + P_{i+1} > 1 $$ -A raiz del ultimo punto, deducimos que la suma de los objetos de todos los paquetes es mayor a $\frac{A(I)}{2}$. +A raiz del ultimo punto, deducimos que la suma de los objetos de todos los paquetes es mayor a $\frac{A(I)}{2}$. Esto se deduce gracias a que: $$ P_1 + P_2 > 1 -\\ +$$ +$$ P_3 + P_4 > 1 -\\ +$$ +$$ P_5 + P_6 > 1 -\\ +$$ +$$ \vdots -\\ +$$ +$$ P_{A(I)-1} + P_{A(I)} > 1 $$ From 347c68afc888ee9f36ab356cae73aa5a381ee93c Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Mon, 5 Jun 2023 20:47:06 -0300 Subject: [PATCH 20/23] Fix latex --- TP2/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TP2/README.md b/TP2/README.md index 3ffecaf..f12219a 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -120,15 +120,19 @@ A raiz del ultimo punto, deducimos que la suma de los objetos de todos los paque $$ P_1 + P_2 > 1 $$ + $$ P_3 + P_4 > 1 $$ + $$ P_5 + P_6 > 1 $$ + $$ \vdots $$ + $$ P_{A(I)-1} + P_{A(I)} > 1 $$ From 80568e4d42acc7405826edfca9ac93e46f4a5f8f Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Fri, 16 Jun 2023 22:25:33 -0300 Subject: [PATCH 21/23] Fix verificar_solucion and approximation analysis Co-authored-by: Ian Shih --- TP2/README.md | 61 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/TP2/README.md b/TP2/README.md index edb40f2..adc8fb5 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -22,14 +22,21 @@ Dado un problema $X$: - Una solucion al problema $X$ se puede verificar en tiempo polinomial. - Otro problema $Y$ NP-Completo se puede reducir al problema $X$, de forma que $X \ge_p Y$. Es decir, resolver $X$ es al menos tan dificil como resolver $Y$. -Analicemos si una solucion a nuestro problema se puede verificar en tiempo polinomial. Como entrada, esperamos recibir una lista de paquetes, y un valor $k$ que representa la cantidad de paquetes. Para saber si una solucion es valida, lo primero que verificamos es que la suma de objetos de cada paquete no supere 1. Una vez verificado esto, nos fijamos si la cantidad de paquetes es menor o igual a $k$. En codigo seria asi: +Analicemos si una solucion a nuestro problema se puede verificar en tiempo polinomial. Como entrada, esperamos recibir una lista de objetos, una solucion, y un valor $k$ que representa la cantidad de paquetes. Para saber si una solucion es valida, lo primero que verificamos es que la suma de objetos de cada paquete en la solucion no supere 1. A la vez, nos fijamos que todos los objetos de la lista de objetos original hayan sido empaquetados en la solucion. Si falta alguno o si hay algun objeto de mas en un paquete (que no pertenezca a los objetos originales), la solucion sera invalida. Una vez verificado esto, nos fijamos si la cantidad de paquetes es menor o igual a $k$. En codigo seria asi: ```py -for paquete in paquetes: - if sum(paquete) > 1: - return False - -return len(paquetes) <= k +def verificar_solucion(objetos, solucion, k): + for paquete in solucion: + if sum(paquete) > 1: + return False + + for objeto in paquete: + try: + objetos.remove(objeto) + except: + return False + + return (len(paquetes) <= k) and len(objetos) == 0 ``` Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo. @@ -109,7 +116,7 @@ Para calcular la cota $r(A)$ para nuestro algoritmo de aproximacion, se consider - $A(I)$ es la cantidad de paquetes generados por nuestro algoritmo de aproximacion - $z(I)$ es la cantidad de paquetes generados por nuestro algoritmo optimo -La suma de los objetos de 2 paquetes adyacentes es superior a 1. Esto es debido a que si se creo un paquete nuevo, necesariamente el primer objeto del nuevo paquete no entraba en el paquete anterior. Sea $P_i$ la suma de los elementos del paqute $i$, tenemos que: +La suma de los objetos de 2 paquetes adyacentes es superior a 1. Esto es debido a que si se creo un paquete nuevo, necesariamente el primer objeto del nuevo paquete no entraba en el paquete anterior. Sea $P_i$ la suma de los elementos del paqute $i$, tenemos que, y considerando que la cantidad de paquetes es par: $$ P_i + P_{i+1} > 1 @@ -161,6 +168,46 @@ $$ z(I) \ge \frac{A(I)}{2} \Rightarrow \frac{A(I)}{z(I)} \le 2 = r(A) $$ +Por el otro lado, si tenemos una cantidad impar de paquetes, vemos que: + +$$ +P_1 + P_2 > 1 +$$ + +$$ +P_3 + P_4 > 1 +$$ + +$$ +P_5 + P_6 > 1 +$$ + +$$ +\vdots +$$ + +$$ +P_{A(I)-2} + P_{A(I)-1} > 1 +$$ + +Si lo expresamos como una sumatoria y agregamos el ultimo paquete: + +$$ +(\sum_{i=1}^{A(I)-1} P_i) + P_{A(I)} > \frac{A(I)-1}{2} + P_{A(I)} +$$ + +Por el mismo motivo descrito anteriormente, el mejor empaquetamiento posible es aquel en el que todos los paquetes estan llenos. Por lo tanto: + +$$ +z(I) \ge \sum_{i=1}^{n} a_i = (\sum_{i=1}^{A(I)-1} P_i) + P_{A(I)} +$$ + +Nuevamente, llegamos a lo siguiente: + +$$ +z(I) \ge \frac{A(I)-1}{2} \Rightarrow \frac{A(I)-1}{z(I)} \le 2 = r(A) +$$ + En conclusion, el algoritmo provisto es una 2-aproximacion de la solucion optima. ### Algoritmo aproximado 2 From 5d85c8576efdf525b21108498628c6785719a4c6 Mon Sep 17 00:00:00 2001 From: Manuel Sanchez Date: Fri, 16 Jun 2023 22:47:47 -0300 Subject: [PATCH 22/23] Add reduccion --- TP2/README.md | 56 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/TP2/README.md b/TP2/README.md index adc8fb5..acbb271 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -41,37 +41,63 @@ def verificar_solucion(objetos, solucion, k): Todas estas operaciones se pueden hacer en tiempo polinomial. Consecuentemente, se cumple la primera condicion de un problema NP-Completo. -Por otro lado, proponemos reducir el problema de Subset Sum al problema de empaquetamiento. Este problema trata sobre, dado un set de numeros $S$ y un numero objetivo $n$, buscar si existe un subset de $S$ cuyos objetos sumen exactamente $n$. Por ejemplo: +Por otro lado, proponemos reducir el *Partition Problem* al problema de empaquetamiento. Este problema trata sobre, dado un set de numeros $S$, buscar si existe una particion de 2 subsets de $S$ tal que los elementos de los subsets sumen lo mismo. Por ejemplo: ```txt S = [1, 8, 16, 4, 10, 9] -n = 15 +S1 = [8, 16] --> Suma: 24 +S2 = [1, 4, 10, 9] --> Suma: 24 ``` -Para poder reducir esto al problema de empaquetamiento, lo primero que hay que hacer es filtrar a todos aquellos numeros que sean mayores que $n$. En nuestro caso: +Debido a que el problema de empaquetamiento solo trabaja con numeros del 0 al 1, dividir todos los elementos del set $S$ por $\frac{n}{2}$ siendo $n$ la suma de los elementos del set $S$. De esta forma, obtenemos el set $S'$ cuya suma de los elementos sera igual a 2. Esto significa que si fueramos a empaquetar estos elementos, el mejor empaquetamiento posible seria usar 2 paquetes. En nuestro caso: ```txt -[1, 8, 16, 4, 10, 9] --> [1, 8, 4, 10, 9] +n/2 = 48/2 = 24 +S = [1, 8, 16, 4, 10, 9] --> [1/24, 8/24, 16/24, 4/24, 10/24, 9/24] ``` -Debido a que el problema de empaquetamiento solo trabaja con numeros del 0 al 1, dividimos todos los numeros restantes por $n$. +Ahora si, aplicamos el algoritmo de empaquetamiento. Si el algoritmo logra obtener una solucion en la que unicamente se usen 2 paquetes, entonces podemos afirmar que el *Partition Problem* tiene solucion. Incluso podemos obtener cual es dicha solucion. Si recordamos, habiamos dividido los elementos por $\frac{n}{2}$ por lo que habria que volver a transformarlos al problema original. Para ello, los multiplicamos por $\frac{n}{2}$. De esta forma, tendremos los subsets $S_1$ y $S_2$, los cuales tendran una suma de elementos igual, cuyo valor sera $n/2$. ```txt -n = 15 -[1, 8, 4, 10, 9] --> [1/15, 8/15, 4/15, 10/15, 9/15] --> [0.067, 0.533, 0.267, 0.667, 0.6] -``` +S = [1/24, 8/24, 16/24, 4/24, 10/24, 9/24] +S1 = [8/24, 16/24] --> Suma: 1 +S2 = [1/24, 4/24, 10/24, 9/24] --> Suma: 1 -Luego, aplicamos el algoritmo de empaquetamiento. Si conseguimos una solucion en la que un paquete este completo (que sus objetos sumen exactamente 1), entonces significa que efectivamente existe un subset de $S$ tal que sus objetos sumen $n$. +Convirtiendolos al problema original: +S1 = [8, 16] --> Suma: 24 +S2 = [1, 4, 10, 9] --> Suma: 24 +``` Ejemplo del algoritmo de reduccion ```py -def reducir_a_objetos(set, n): - nuevo = [] - for elem in set: - if elem > n: continue - nuevo.push(elem / n) - return nuevo +def reducir_a_empaquetamiento(set_partition): + n = sum(set_partition) + objetos_empaquetamiento = [] + + for elem in set_partition: + objetos_empaquetamiento.push(elem / (n / 2)) + + return objetos_empaquetamiento + +def partition_problem(set_partition): + n = sum(set_partition) + objetos_empaquetamiento = reducir_a_empaquetamiento(set_partition) + solucion_empaquetamiento = empaquetar(objetos_empaquetamiento) + solucion_partition = [] + + if (len(solucion_empaquetamiento) > 2): + return False + + for paquete in solucion_empaquetamiento: + subset = [] + + for elem in paquete: + subset.push(elem * n / 2) + + solucion_partition.push(subset) + + return solucion_partition ``` #### Complejidad temporal From e7ad19401bc207b613e58ada7d0a31e6531b7778 Mon Sep 17 00:00:00 2001 From: fsh1ft Date: Sun, 18 Jun 2023 22:39:04 -0300 Subject: [PATCH 23/23] Fix --- TP2/README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/TP2/README.md b/TP2/README.md index acbb271..68e79f2 100644 --- a/TP2/README.md +++ b/TP2/README.md @@ -222,16 +222,28 @@ $$ (\sum_{i=1}^{A(I)-1} P_i) + P_{A(I)} > \frac{A(I)-1}{2} + P_{A(I)} $$ +Simplificamos a la siguiente expresion + +$$ +\sum_{i=1}^{A(I)-1} P_i > \frac{A(I)-1}{2} +$$ + Por el mismo motivo descrito anteriormente, el mejor empaquetamiento posible es aquel en el que todos los paquetes estan llenos. Por lo tanto: $$ -z(I) \ge \sum_{i=1}^{n} a_i = (\sum_{i=1}^{A(I)-1} P_i) + P_{A(I)} +z(I) \ge \sum_{i=1}^{n} a_i = \sum_{i=1}^{A(I)} P_i +$$ + +Reemplazando con la expresion anterior: + +$$ +z(I) \ge \sum_{i=1}^{A(I)} P_i > \sum_{i=1}^{A(I)-1} P_i > \frac{A(I)-1}{2} $$ Nuevamente, llegamos a lo siguiente: $$ -z(I) \ge \frac{A(I)-1}{2} \Rightarrow \frac{A(I)-1}{z(I)} \le 2 = r(A) +z(I) > \frac{A(I)-1}{2} \Rightarrow \frac{A(I)-1}{z(I)} < 2 = r(A) $$ En conclusion, el algoritmo provisto es una 2-aproximacion de la solucion optima.