mirror of
https://github.com/Steffo99/appunti-magistrali.git
synced 2024-11-27 04:14:19 +00:00
127 lines
2.8 KiB
Markdown
127 lines
2.8 KiB
Markdown
[[algoritmo]] di [[spanning tree construction]].
|
|
|
|
> [!Summary]
|
|
> Le [[entità]] del grafo vengono visitate sequenzialmente attraverso una [[depth-first search]].
|
|
>
|
|
> In ogni momento, a solo una [[entità]] è permesso eseguire codice, e questo permesso è tracciato attraverso un [[token metaforico]].
|
|
|
|
## [[Comportamento]]
|
|
|
|
L'[[entità]] [[iniziatore singolo|iniziatrice]] viene inizializzata a `LEADER`, mentre le altre vengono inizializzate a `IDLE`.
|
|
|
|
==Questo modello è brutto...==
|
|
|
|
### `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.
|
|
```rust
|
|
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` inizia la visita:
|
|
```rust
|
|
spontaneously!({
|
|
self.unvisited = self.neighbours.clone();
|
|
self.parent = null;
|
|
self.children = vec![];
|
|
state!(VISITED);
|
|
self.visit_next();
|
|
})
|
|
```
|
|
|
|
### `IDLE`
|
|
|
|
Una [[entità]] `IDLE` è in attesa di ricevere il [[token metaforico]]:
|
|
```rust
|
|
on_receive!(
|
|
Token::Forward => {
|
|
self.parent = sender;
|
|
self.unvisited.remove(sender);
|
|
state!(VISITED);
|
|
self.visit_next();
|
|
}
|
|
)
|
|
```
|
|
|
|
### `VISITED`
|
|
|
|
Una [[entità]] `VISITED` ha già ricevuto il [[token metaforico]] in precedenza, e se lo riceve, lo rifiuta con `Token::BackEdge`, che porta a una nuova visita da parte del mittente:
|
|
```rust
|
|
on_receive!(
|
|
Token::Forward => {
|
|
self.unvisited.remove(sender);
|
|
send!(sender, Token::BackEdge);
|
|
}
|
|
Token::BackEdge => {
|
|
self.visit_next();
|
|
}
|
|
)
|
|
```
|
|
|
|
Può anche ricevere un `Token::Finished`, che indica che l'[[entità]] mittente ha terminato l'elaborazione; essa viene aggiunta all'albero, e poi la visita continua:
|
|
```rust
|
|
on_receive!(
|
|
Token::Finished => {
|
|
self.children.push(sender);
|
|
self.visit_next();
|
|
}
|
|
)
|
|
```
|
|
|
|
### `DONE`
|
|
|
|
Un [[entità]] `DONE` sa tutte le informazioni possibili sui suoi vicini.
|
|
|
|
Non fa nient'altro.
|
|
|
|
## [[algoritmo corretto|Correttezza]]
|
|
|
|
==...==
|
|
|
|
## [[costo computazionale distribuito|Costo computazionale]]
|
|
|
|
### [[Comunicazione]]
|
|
|
|
Tutti i [[canale di comunicazione|canali]] vengono visitati due volte, uno da `Token::Forward`, e uno da `Token::BackEdge` o `Token::Finished`:
|
|
$$
|
|
2 \cdot Channels
|
|
$$
|
|
|
|
In [[notazione asintotica]], è:
|
|
$$
|
|
\Large O(Channels)
|
|
$$
|
|
|
|
> [!Note]
|
|
> Coincide strettamente con il lower bound.
|
|
|
|
### [[Tempo]]
|
|
|
|
Essendo la visita del grafo sequenziale, il tempo richiesto coincide con il costo di comunicazione:
|
|
$$
|
|
2 \cdot Channels
|
|
$$
|
|
|
|
In [[notazione asintotica]], è:
|
|
$$
|
|
\Large O(Channels)
|
|
$$
|
|
|
|
> [!Warning]
|
|
> Non coincide con il lower bound!
|