82 views
# Algoritmos 3 practica 1 ej 3 ### Ejercicio 3 MaxiSubconjunto #### Preguntar por complejidad y podas 3. Dada una matriz simétrica $M$ de $n \times n$ números naturales y un número $k$, queremos encontrar un subconjunto $I$ de $\{1, \ldots, n\}$ con $|I| = k$ que maximice $\sum_{i,j \in I} M_{ij}$. Por ejemplo, si $k = 3$ y: $$ M = \begin{pmatrix} 0 & 10 & 10 & 1 \\ -1 & 0 & 5 & 2 \\ -1 & -1 & 0 & 1 \\ -1 & -1 & -1 & 0 \end{pmatrix}, $$ entonces $I = \{1, 2, 3\}$ es una solución óptima. a) Diseñar un algoritmo de *backtracking* para resolver el problema, indicando claramente cómo se codifica una solución candidata, cuáles soluciones son válidas y qué valor tienen, qué es una solución parcial y cómo se extiende cada solución parcial. b) Calcular la complejidad temporal y espacial del mismo. c) Proponer una poda por optimalidad y mostrar que es correcta. #### Resolución (a consultar) ##### a) -inicializar i vacio y tambien un conjunto candidato en vacio - el backtracking toma $I$, el conjunto de indices candidatos, la suma actual, y el indice de inicoi para evitar repeticiones. - una solución candidata es un conjunto $I$, $|I|< k$ que se expande para maximizar la suma $M_{ij}$. - Cada vez que queremos añadir un elem a $I$ calculamos la suma de los elementos asociados a la matriz con $I$ $\cup$ {i} - una solucion es válida si |I| = k y si el valor da $\sum_{i,j \in I} M_{ij}$ - Una solución parcial sería un conjunto I con menos de k o sea $|I| < k$ se extiende añadiendo elementeos i al conjunto $I$ y chequeando la suma $M_{ij}$ #### Código (o algo así) ``` funcion backtracking(I,k,suma_actual_mejor_suma,M): if |I| == k: mejor_suma = suma_actual mejor_conjunto = I return mejor_suma, mejor_conjunto ## caso base ^^ for each elem i 1...n: if i is not in I: I_nuevo = I + {i} suma_nueva = suma_actual + SumaDeElementos(M, I_nuevo) ## Esto es una aux que calcula la suma de valores maximos posibles ## que se pueden añadir if suma_nueva + SumaPosibleRestante(M, I_nuevo,k) <= mejos_suma: Continue ... # poda por optimalidad Backtracking(I_nuevo, k, suma_nueva, mejor_suma,M) ``` pasé por **gpt-4** la consigna y mi código y me entregó lo siguiente: ``` funcion backtracking(I, k, suma_actual, mejor_suma, M): # Si el tamaño de I es igual a k, entonces hemos encontrado una solución. if |I| == k: # Actualizar la mejor suma si la suma actual es mayor que la mejor suma conocida. if suma_actual > mejor_suma: mejor_suma = suma_actual mejor_conjunto = I # Debemos retornar tanto la mejor suma como el mejor conjunto encontrado. return mejor_suma, mejor_conjunto mejor_conjunto_local = I # Recorrer cada elemento para expandir el conjunto I. for each elem i from 1 to n: # Considerar solo si i no está ya en I. if i not in I: I_nuevo = I + {i} suma_nueva = suma_actual + SumaDeElementos(M, I_nuevo) # Suma posible restante considera el máximo potencial para los elementos restantes. if suma_nueva + SumaPosibleRestante(M, I_nuevo, k) <= mejor_suma: continue # Poda por optimalidad. # Recursivamente intentar agregar más elementos a I_nuevo. suma_recursiva, conjunto_recursivo = backtracking(I_nuevo, k, suma_nueva, mejor_suma, M) # Actualizar la mejor suma y el mejor conjunto si se encuentra una mejor en la recursión. if suma_recursiva > mejor_suma: mejor_suma = suma_recursiva mejor_conjunto_local = conjunto_recursivo # Retornar el mejor resultado encontrado en esta llamada recursiva. return mejor_suma, mejor_conjunto_local ``` intenté codear esto pero no estoy seguro si funciona bien ```python def backtracking(I, k, suma_actual, mejor_suma, mejor_conjunto, M): """ Algoritmo de backtracking para encontrar el subconjunto de índices de tamaño k que maximiza la suma de los elementos correspondientes en la matriz M. """ # Comprueba si la combinación actual de índices tiene la longitud deseada k. if len(I) == k: # Si la suma actual es mayor que la mejor suma encontrada hasta ahora, actualiza la mejor suma y el subconjunto. if suma_actual > mejor_suma: mejor_suma = suma_actual mejor_conjunto = I return mejor_suma, mejor_conjunto n = len(M) # Explora todas las posibles extensiones al subconjunto actual I. for i in range(n): if i not in I: I_nuevo = I + [i] suma_nueva = suma_de_elementos(M, I_nuevo) # Aplica la poda si la suma máxima posible es menor o igual a la mejor suma actual. if suma_nueva + suma_posible_restante(M, I_nuevo, k) <= mejor_suma: continue # Poda por optimalidad. # Llamada recursiva al backtracking con el nuevo subconjunto y la nueva suma. mejor_suma, mejor_conjunto = backtracking( I_nuevo, k, suma_nueva, mejor_suma, mejor_conjunto, M ) return mejor_suma, mejor_conjunto ``` - Lo que mi codigo no está haciendo es actualizar la mejor suma y el mejor conjunto si se encuentra una mejor en la recursión. Habría que **preguntar si es necesario** pero yo creería que es fundamental actualizar la suma. ##### b) - Hay $n^k$ posibles subconjuntos, n es el tamaño de la matriz y k el tamaño del subconjunto que queremos encontrar. $\therefore$ $O(n^k)$ - Preguntar si es $O(n^k \times k^2)$ **Porque es algo que me dijo el bot** - Espacial: ¿lineal? No sé, revisar. #### c) Podas - La poda de optimalidad está planteada en el algoritmo y en el inciso a)