connessioni fra oggetti Java:
circuito elettronico:
nazioni confinanti:
cose connesse
niente oggetti, circuiti elettronici, nazioni, ecc.
pallini con numeri o scritte
frecce
stesse connessioni
non dipende dalla provenienza
permette algoritmi generali
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stesso problema per tutti
seguire le frecce
problemi su cose completamente diverse
stesso problema se visto su grafi:
problemi diversi ⇒ stesso problema su grafi
stesso algoritmo
pallini con frecce
come lo memorizzo in un programma?
Pyton:
grafo = ({1,2,3,4}, { (1,2), (1,3), (2,3), (2,4) })
|
|
|
|
memorizzati come…
|
|
|
|
|
({1,2,3,4},
{(1,2), (1,3), (2,3), (2,4)}) |
({1,2,3,4},
{(1,2), (1,3), (2,3), (2,4)}) |
({1,2,3,4},
{(1,2), (1,3), (2,3), (2,4)}) |
stesso grafo, visualizzazioni diverse
stesso grafo, visualizzazioni diverse
disegnare un grafo, data la sua memorizzazione:
raffigurazione di un grafo (graph drawing)
grafo specificato come testo
lo visualizza in vari modi
digraph G {
1 -> 2;
1 -> 3;
2 -> 3;
2 -> 4;
}
digraph G {
1 -> 2;
1 -> 3;
2 -> 3;
2 -> 4;
}
DIgraph = DIrected graph
gli archi sono freccie, hanno una direzione
grafo non diretto =
gli archi sono segmenti
graph invece di digraph
segmenti 1--2, 1--3, ecc. invece di frecce
digraph G {
1 -> 2;
1 -> 3;
2 -> 4;
subgraph cluster_x {
2 -> 3;
style = filled;
label = x;
color = lightblue;
}
1 [shape=diamond, style=filled, color=red];
}
digraph G {
…
subgraph cluster_x {
2 -> 3;
…
}
…
}
sottografo cluster_…
il nome deve iniziare con cluster
contiene i nodi fra le graffe
2 -> 3
quindi nodi 2 e 3
digraph G {
…
subgraph cluster_x {
…
style = filled;
label = x;
color = lightblue;
}
1 [shape=diamond, style=filled, color=red];
}
nodi riempiti, colorati, etichettati
anche per gli interi cluster
memorizzarlo nella variabile grafo
stamparlo
grafo = ( (1,2,3,4), { (1,2), (1,3), (2,3), (2,4) } )
print(grafo)
metodo arco(grafo, a, b) per vedere se c'è la freccia da a a b
# presenza di un arco fra due nodi
def arco(grafo, a, b):
return (a,b) in grafo[1];
# prove
print('1->2:', arco(grafo, 1, 2))
print('2->1:', arco(grafo, 2, 1))
print('1->4:', arco(grafo, 1, 4))
perchè "nodi" e "arco"?
scrivere un metodo successori(grafo, nodo) che trova tutti i nodi che sono alla fine di un arco che parte dal nodo
# successori di un nodo
def successori(grafo, nodo):
return { b for (a,b) in grafo[1] if a == nodo }
# prova: successori di 1
print('successori di 1:', successori(grafo, 1))
i grafi servono a molte cose
in molti serve verificare se c'è un arco (freccia)
o trovare tutti i successori di un nodo (pallino)
fare una classe Grafo
class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi
dichiara una classe in Python
ogni oggetto contiene un insieme nodi
e un insieme archi
class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi
aggiunte utili:
class Grafo:
# costruttore
def __init__(self, nodi, archi):
self.nodi = nodi
self.archi = archi
# conversione in stringa
def __str__(self):
n = "nodi: " + ' ' + ' '.join({str(p) for p in self.nodi})
a = "archi: " + ' '.join({"\n " + str(a[0]) + "->" + str(a[1]) for a in self.archi})
return n + "\n"+ a
# presenza di un arco
def arco(self, partenza, arrivo):
if partenza not in self.nodi:
return False
if arrivo not in self.nodi:
return False
return (partenza,arrivo) in self.archi
# insieme dei successori di un nodo
def setsuccessori(self, nodo):
return {b for (a,b) in self.archi if a == nodo}
from tabella import Grafo
# grafo di esempio
grafo = Grafo({1,2,3,4}, { (1,2), (1,3), (2,3), (2,4) })
print(grafo)
print()
# presenza arco e successori
print('1->2:', grafo.arco(1, 2))
print('2->1:', grafo.arco(2, 1))
print('1->4:', grafo.arco(1, 4))
print()
print('successori di 1:', grafo.setsuccessori(1))
esercizio: memorizzarlo in un oggetto
grafo = Grafo({ 1,2,3,4 },
{ (1,2), (2,1), (2,3), (3,2), (2,4), (4,2), (3,4), (4,3) })
print(grafo)
grafo = Grafo({1,2,3,4,5,6},
{ (1,6),
(2,4),
# 3
# 4
(5,3),
(6,2), (6,3), (6,4), (6,5) })
print(grafo)
# classe Grafo class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi …
in seguito: archi memorizzati in altro modo
non con un insieme
# classe Grafo class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi # insieme degli archi def insiemearchi(self): return self.archi
ovvio: l'insieme degli archi è self.archi
non ovvio: funziona anche con archi memorizzati in altro modo
# classe Grafo class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi # insieme degli archi def insiemearchi(self): …
si trova l'insieme degli archi
si ritorna al posto di self.archi
# classe Grafo class Grafo: # costruttore def __init__(self, nodi, archi): self.nodi = nodi self.archi = archi # insieme dei nodi def insiemenodi(self): return self.nodi # insieme degli archi def insiemearchi(self): …
stessa cosa per i nodi
metodo che ritorna l'insieme dei nodi
funziona anche se i nodi non sono memorizzati come un insieme