Corso di Ottimizzazione Combinatoria (IN440)

Esercizi e sorgenti dei programmi

Algoritmo di Kruskal

Il seguente programmino Python è una codifica dell'algoritmo di Kruskal per il calcolo dell'albero ricoprente di costo minimo (MST - Minimum Spanning Tree) di un grafo non orientato con pesi non negativi assegnati agli spigoli.

Codifica in linguaggio Python 3.x

#
#   MST-Kruskal.py
#
#   Dato un grafo non orientato casuale con pesi posivi
#   assegnati agli spigoli, calcola l'albero ricoprente
#   di peso minimo usando l'algoritmo di Kruskal
#

import networkx as nx
import numpy    as np
from   random import *

def makeSet(x, s):
   s[x] = x
   return

def findSet(x, s):
   return(s[x])

def union(x, y, s):
   z = s[y]
   for i in range(len(s)):
      if s[i] == z: s[i] = s[x]
   return

def randomWeightedGraph(G, n, P, Wmax):
   for v in range(1,n+1):
      G.add_node(v)
   for u in range(1,n):
      for v in range(u+1,n+1):
         x = random()
         if x>0 and x<=P:
            w = randint(1,Wmax)
            G.add_edge(u,v,weight=w)
   return

#   Inizio del programma: genero il grafo casuale
g = nx.Graph()
n = int(input("Numero di vertici: "))
s = np.empty((n+1), dtype=int)
p = float(input("Probabilita': "))
peso = int(input("Peso massimo per gli spigoli: "))
randomWeightedGraph(g, n, p, peso)

#   PASSO 1: costruisco l'albero T = (V, E) con V(T) = V(G)
t = nx.Graph()
for v in g:
   t.add_node(v)

#   PASSO 2-4: creo l'insieme S[v] per ogni v vertice di G
for v in g:
   makeSet(v, s)

#   PASSO 5: costruisco l'insieme degli spigoli E(G) come
#      una matrice e ordino gli spigoli in base al peso crescente
e = g.number_of_edges()
print("numero di spigoli", e)
w = np.zeros((2*e, 3), dtype=int)
e = 0
for u in g:
   for v in g.neighbors(u):
      print(u, v, g[u][v]['weight'])
      w[e][0] = u
      w[e][1] = v
      w[e][2] = g[u][v]['weight']
      e = e + 1
w = w[w[:, 2].argsort()]

#   PASSO 4: seleziono gli spigoli (u,v) in ordine di peso crescente e
#      se u e v non appartengono allo stesso insieme unisco gli insiemi
#      s[i] e s[v] e aggiungo lo spigolo (u,v) all'abero T
for i in range(e):
   if findSet(w[i][0], s) != findSet(w[i][1], s):
      t.add_edge(w[i][0], w[i][1], weight=w[i][2])
      union(w[i][0], w[i][1], s)

print("\nAlbero ricoprente:")
for u in t:
   for v in t.neighbors(u):
      print(u, v, t[u][v]['weight'])

Università degli Studi Roma Tre - Dipartimento di Matematica e Fisica - Corso di laurea in Matematica - Corso di Ottimizzazione Combinatoria (IN440)

Author: Marco Liverani - Last modified: Wednesday April 02, 2025 - Document URI: https://193.204.165.209/users/liverani/IN440/kruskal.shtml