1
Fork 0
mirror of https://github.com/Steffo99/appunti-magistrali.git synced 2024-11-22 18:44:17 +00:00
appunti-steffo/9 - Algoritmi distribuiti/3 - Computazione distribuita/3 - Spanning tree/traversal+ protocol.md

4.4 KiB

algoritmo di spanning tree construction che migliora il traversal protocol.

[!Summary] Le entità del grafo vengono visitate sequenzialmente attraverso una depth-first search.

In ogni momento, a solo una entità è permesso visitarne altre, e questo permesso è tracciato attraverso un token metaforico.

Comportamento

L'entità iniziatore singolo viene inizializzata a LEADER, mentre le altre vengono inizializzate a IDLE.

==Questo modello è brutto e sbagliato nel caso ci sia un grafo di un nodo solo...==

visit_next(self)

Definiamo una funzione che si ripeterà più volte che invia il token al primo nodo non visitato dal nodo attuale, e quando non rimangono più token, notifica il nodo genitore.

impl Entity {
	fn visit_next(self) {
		if self.unvisited.length() > 0 {
			state!(VISITED);
			let entity = self.unvisited.pop();
			send!(entity, Token::Forward);
		}
		else {
			if(self.parent) {
				send!(self.parent, Token::Finished);
			}
			state!(DONE);
		}
	}
}

LEADER

L'entità LEADER notifica tutti i suoi vicini che è stata visitata:

spontaneously!({
	self.unacknowledged = self.neighbours.clone();
	self.unvisited = self.neighbours.clone();
	self.parent = null;
	self.children = vec![];
	send!(self.unvisited, Visited::Sender);
})

Quando tutti i vicini hanno risposto, inizia la visita:

on_receive!(
	Visited::Receiver => {
		self.unacknowledged.remove(sender);
		if self.unacknowledged.length() == 0 {
			state!(VISITED);
			self.visit_next();
		}
	}
)

IDLE

Una entità IDLE è in attesa di ricevere il token metaforico.
Quando lo riceve, notifica tutti i vicini della cosa, come fatto dal leader:

spontaneously!({
	self.unacknowledged = self.neighbours.clone();
	self.unvisited = self.neighbours.clone();
	self.children = vec![];
})

on_receive!(
	Token::Forward => {
		self.parent = sender;
		self.unvisited.remove(sender);
		send!(self.unvisited, Visited::Sender);
	}

	Visited::Receiver => {
		self.unacknowledged.remove(sender);
		if self.unacknowledged.length() == 0 {
			state!(VISITED);
			self.visit_next();
		}		
	}

	Visited::Sender => {
		self.unvisited.remove(sender);
		send!(sender, Visited::Receiver);
	}
)

VISITED

Una entità VISITED ha già ricevuto il token metaforico in precedenza.

Può ricevere solo un Token::Finished, che indica che l'entità mittente ha terminato l'elaborazione; essa viene aggiunta all'albero, e poi la visita continua:

on_receive!(
	Token::Finished => {
		self.children.push(sender);
		self.visit_next();
	}
)

Non è possibile che riceva Visited::Sender, in quanto è già stata rimossa da self.unvisited.

Per lo stesso motivo, Token::BackEdge sono stati rimossi dall'algoritmo.

DONE

Un entità DONE sa tutte le informazioni possibili sui suoi vicini.

Non fa nient'altro.

algoritmo corretto

==...==

costo computazionale distribuito

Comunicazione

Tutti i canale di comunicazione vengono visitati due volte, uno da Visited::Sender, e uno da Visited::Receiver: \color{LightCoral} 2 \cdot Channels

In più, tutti i nodi tranne il leader invieranno almeno una volta Token::Forward e Token::Finished.

\color{SpringGreen} 2 \cdot (Entities - 1)

Dunque, il numero di messaggi inviati sarà: {\color{LightCoral} 2 \cdot Channels} + {\color{SpringGreen} 2 \cdot (Entities - 1)}

Essendo il grafo connesso, (Entities - 1) è obbligatoriamente minore di Channels, quindi possiamo riscrivere la riga precedente come: {\color{LightCoral} 2 \cdot Channels} + {\color{SpringGreen} 2 \cdot Channels}

4 \cdot Channels

In notazione asintotica, è: \Large O(Channels)

Note

Coincide asintoticamente con il lower bound.

Tempo

L'invio di Visited::Sender e Visited::Receiver corrisponde al tempo di attraversamento di un albero: \color{SkyBlue} 2 \cdot (Entities - 1)

In più, tutte le entità devono inviare sequenzialmente Token::Forward e Token::Finished: \color{Lavender} 2 \cdot Entities

Dunque, il tempo necessario sarà: {\color{SkyBlue} 2 \cdot (Entities - 1)} + {\color{Lavender} 2 \cdot Entities}

4 \cdot Entities - 2

In notazione asintotica, è: \Large O(Entities)

Note

Coincide asintoticamente con il lower bound.