- Diamis Alfonso Pérez
- Abraham González Rivero
Nuestro problema se puede modelar como un problema de coloración de grafos, donde cada propuesta de un curso es un vértice del grafo y dos vértices están conectados por una arista si corresponden a dos propuestas que comparten al menos un día en común. Entonces, encontrar k propuestas que no compartan días es equivalente a encontrar un conjunto independiente de k vértices en el grafo.
Para demostrar que la modelación del problema es correcta, debemos demostrar dos cosas:
- Que para toda solución del problema original (encontrar k propuestas que no compartan días), existe una solución correspondiente en el problema de coloración de grafos (encontrar un conjunto independiente de k vértices).
- Que para toda solución del problema de coloración de grafos (encontrar un conjunto independiente de k vértices), existe una solución correspondiente en el problema original (encontrar k propuestas que no compartan días).
Para demostrar la primera afirmación, supongamos que tenemos una solución al problema original que consiste en k propuestas que no comparten días entre sí. Podemos construir un grafo no dirigido G de la siguiente manera:
- Cada propuesta corresponde a un vértice de G.
- Dos vértices están conectados por una arista si corresponden a dos propuestas que comparten al menos un día en común.
Es fácil ver que G es un grafo sin aristas entre los vértices seleccionados (es decir, un conjunto independiente) porque cada propuesta seleccionada no comparte días con las otras propuestas seleccionadas. Por lo tanto, G tiene un conjunto independiente de tamaño k, que representa una solución al problema de coloración de grafos correspondiente.
Para demostrar la segunda afirmación, supongamos que tenemos una solución al problema de coloración de grafos que consiste en un conjunto independiente de k vértices en un grafo G. Podemos interpretar cada vértice del conjunto independiente como una propuesta seleccionada que no comparte días con las otras propuestas seleccionadas. Como cada vértice del conjunto independiente no tiene vecinos en G, esto significa que las propuestas correspondientes no comparten días entre sí. Por lo tanto, el conjunto independiente de vértices en G representa una solución al problema original correspondiente.
Por lo tanto, hemos demostrado que existe una correspondencia biunívoca entre las soluciones del problema original y las soluciones del problema de coloración de grafos, lo que demuestra que la modelación del problema como un problema de coloración de grafos es correcta.
Este problema es NP-completo.
Demostremos que hallar un conjunto independiente de tamaño k en un grafo es NP-completo. Debemos demostrar dos cosas:
- Que el problema pertenece a la clase NP.
- Que el problema es NP-hard, es decir, que se puede reducir en tiempo polinómico a cualquier otro problema en NP.
Para demostrar que el problema pertenece a la clase NP, debemos demostrar que dada una solución propuesta (es decir, un conjunto de vértices que se cree que forman un conjunto independiente de tamaño k en el grafo), se puede verificar en tiempo polinómico si la solución es válida.
Esto se puede hacer simplemente comprobando que ningún par de vértices en la solución está conectado por una arista en el grafo, lo cual se puede hacer en tiempo O(k^2) si se compara cada par de vértices en la solución.
Para demostrar que el problema es NP-hard, podemos reducir el problema del Clique al problema de hallar un conjunto independiente de tamaño k en un grafo.
El problema del Clique consiste en encontrar un conjunto de vértices en un grafo que formen un clique de tamaño k. Supongamos que tenemos un grafo G y queremos encontrar un clique de tamaño k en G. Podemos construir un grafo G' de la siguiente manera:
- El conjunto de vértices de G' es el mismo que el de G.
- Dos vértices en G' están conectados por una arista si y solo si no están conectados por una arista en G.
Es fácil ver que G' es el grafo complemento de G. Entonces, si encontramos un conjunto independiente de tamaño k en G', este conjunto corresponde a un clique de tamaño k en G.
Por lo tanto, si pudiéramos encontrar un conjunto independiente de tamaño k en tiempo polinómico, también podríamos encontrar un clique de tamaño k en tiempo polinómico, y por lo tanto resolveríamos el problema del Clique en tiempo polinómico. Pero el problema del Clique es NP-completo, por lo que el problema de hallar un conjunto independiente de tamaño k también debe ser NP-hard.
En conclusión, hemos demostrado que el problema de hallar un conjunto independiente de tamaño k en un grafo es NP-completo porque pertenece a la clase NP y se puede reducir en tiempo polinómico a otro problema NP-completo conocido, como el problema del Clique.
Un clique en un grafo no dirigido
Para demostrar que
Lo siguiente que probaremos es que
El algoritmo de reducción comienza con una instancia de
Construimos el grafo
Para cada cláusula
-
$v^r_i$ y$v^s_j$ están en diferentes ternas, es decir,$r \neq s$ - sus literales correspondientes son consistentes, es decir,
$l^r_i$ no es la negación de$l^s_j$ .
Podemos construir el grafo para
Debemos demostrar que esta transformación de
Supongamos que
En el otro sentido, supongamos que
En el ejemplo de la figura, una asignación válida para D sería $x_2 = 0 $ y
Note que redujimos una instancia arbitraria de
La aproximación contaria, reducir instancias de
def KProposals(k, dates, checkdates, taken):
if len(taken) == k:
return taken
for i in range(len(dates)):
if Fit(dates[i], taken) and not checkdates[i]:
newTaken = taken.copy()
newTaken.append(dates[i])
checkdates[i] = True
newcheck = checkdates.copy()
return KProposals(k, dates, newcheck, newTaken)
oldcheck = checkdates.copy()
return KProposals(k, dates, oldcheck, taken[:len(taken) - 1])
def Fit(item, itemlist):
for prop in itemlist:
for i in item:
for j in prop:
if i == j:
return False
return True
Una primera solución pudiera ser intentar ir construyendo todos los subconjuntos de tamaño K mientras se comprueba si estos son válidos. Evidentemente si existe la solución, el algoritmo la hallará pues explora todos los subconjuntos de tamaño k posibles.
Luego la complejidad temporal del algoritmo es
El algoritmo que modela nuestro problema a un grafo se encuentra en el fichero "BuildGraph.py" donde nos apoyamos de la biblioteca de python NetworkX para el trabajo con grafos. Se modela siguiendo las condiciones descritas al inicio del informe, se coloca la arista <u,v> si la intersección entre las propuestas u y v no es vacía. Como debemos comparar cada propuesta con el resto de las propuestas para conocer su intersección la complejidad de modelar el grafo es
def WeightedVertex(items,k):
G = buildGraph(items)
for node in G.nodes():
G.nodes[node]['weight'] = 2 ** (-G.degree(nodes))
mis = set()
while G:
node = max(G.nodes(), key=lambda x: G.nodes[x]['weight'])
cover.add(node)
for neighbor in G.neighbors(node):
G.nodes[neighbor]['weight'] = 0
G.remove_node(node)
if len(mis) >=k : return mis[:k]
else: return mis
Tras modelar el grafo el algoritmo le asigna a cada vértice como peso