ESERCIZI Actors Model and ERLANG

Esercizio 1
Il seguente modulo Erlang permette di calcolare una funzione map che restituisce lo stesso valore della funzione Haskell
map f [] = []

map f (x:xs) = (f x):(map f xs)
ma in modo tale che ogni valore della lista di output viene calcolato da un processo (Actor) differente
-module(mapfun).
-export([map/2,compute/3]).


collectRes([]) -> [];

collectRes([ID|IDs]) -> receive
                           {ID,Res} -> [Res|collectRes(IDs)]
                        end.


map(_,[]) -> [];

map(F,List) ->

         ComputingActors = [spawn(mapfun,compute,[F,X,self()]) || X <- List ], 
         
         collectRes(ComputingActors).                             



compute(F,X,Collector) -> Res = F(X),
                          Collector!{self(),Res}.
Ricopiare e commentare il codice descrivendo sinteticamente il suo funzionamento.
Esercizio 2

Esercizio 3

Esercizio 4

Esercizio 5

Esercizio 6

Esercizio 7

Esercizio 8

Esercizio 9

Esercizio 10

Esercizio 11
Descrivere il modello di concorrenza ad attori (Actors Model of Concurrency).

Esercizio 12


Esercizio 13
Definire una funzione map in Erlang che restituisca lo stesso valore della seguente funzione Haskell
map f [] = []
map f (x:xs) = (f x):(map f xs)
ma in cui ogni valore della lista di output venga calcolato da un processo (Actor) differente

  • Possibile soluzione.
    Esercizio 14 (non banale)
    Modificare il programma in [AAVV] Erlang Examples relativo alle espressioni regolari, in modo che la funzione create prenda un argomento che rappresenta la funzione di transizione di un automa a stati finiti, crei l'automa corrispondente e restituisca il PID del manager. Assumiamo che gli automi generati da create siano dei riconoscitori di linguaggi regolari su {a,b,c}. La funzione di transizione si puo' rappresentare come lista di quadruple (i primi tre elementi di una quadrupla corrispondono ad una riga della tabella associata alla funzione di transizione, mentre il quarto elemento descrive se lo stato e' o meno dfinale).

  • Possibile soluzione.
    Esercizio 15

    Il seguente modulo Erlang permette di calcolare una funzione map che restituisce lo stesso valore della funzione Haskell
    map f [] = []
    
    map f (x:xs) = (f x):(map f xs)
    
    ma in modo tale che ogni valore della lista di output viene calcolato da un processo (Actor) differente.
    -module(mapfun).
    -export([map/2,compute/3]).
    
    
    collectRes([]) -> [];
    
    collectRes([ID|IDs]) -> receive
                               {ID,Res} -> [Res|collectRes(IDs)]
                            end.
    
    
    map(_,[]) -> [];
    
    map(F,List) ->
    
             ComputingActors = [spawn(mapfun,compute,[F,X,self()]) || X <- List ], 
             
             collectRes(ComputingActors).                             
    
    
    
    compute(F,X,Collector) -> Res = F(X),
                              Collector!{self(),Res}.
    
    Modificare il modulo Erlang in modo che i risultati vengano ricevuti dalla funzione collectRes in qualsiasi ordine e poi riordinati correttamente.
  • Possibile soluzione.
    Esercizio 17

    Si consideri la seguente estensione del programma usable dell'esercizio 1
    usable Yor pred = False
    
    usable (Frunz n m y1 y2) pred = (pred n)||(pred m)||(usable y1)||(usable y2)
    
    In considerazione del fatto che il predicato pred in input possa essere molto pesante dal punto di vista computazionale, si scriva un programma Erlang in modo che il calcolo dei valori booleani (pred n) venga eseguito da processi indipendenti.
    Supporre che elementi del tipo di dato Yunz vengano rappresentati da liste con le seguenti forme: [yor] per rappresentare uno Yor, e [frunz,N,M,Y1,Y2] per rappresentare Yunz che non sono Yor (ovviamente N ed M saranno numeri e Y1 ed Y2 due liste che rappresentano due Yunz).
  • Possibile soluzione.
    Esercizio 18

    Si consideri la seguente funzione Haskell
    factg g 0 = g 1
    
    factg g n = (g n)*(factg g (n-1))
    
    Poiche' il calcolo di (g n) potrebbe richiedere tempo, vogliamo definire la stessa funzione in Erlang in modo che il calcolo di (g n) venga eseguito da un processo, mentre altri processi si occupano del calcolo di (factg g (n-1)).
  • Possibile soluzione.
    Esercizio 19

    Scrivere il corrispettivo Erlang della funzione Haskell treeapply definita da
    data BT a = Leaf a | Node a (BT a) (BT a)
    
    treeapply   f (Leaf x)       = x
    treeappply  f (Node n t1 t2) = f n (treeapply f t1) (treeapply f t2)
    
    Il programma Erlang deve far si che la computazione sia parallelizzabile il piu' possibile.
    Supporre di aver definito in Erlang un modulo
    -module(bt)
    -export(leaf/1, nodeLabel/3, getRoot/1, subtreeL/1, subtreeR/1, isLeaf/1)
    

  • Possibile soluzione.
    Esercizio 20

    Scrivere un modulo Erlang contenente una funzione (insieme ad altre) che permetta di creare attori che corrispondano ad oggetti appartenenti alle seguente classe OCaml:
      class cell =
       object (self:'self)
       val mutable contents = 0
       method read = contents
       method write new_cont = contents <- new_cont
       method eq (c:`self) = (self#read=c#read)
      end;;
    
    Commentare il codice.
  • Possibile soluzione.
    Esercizio 21
    Si consideri il sistema degli N filosofi a cena, con N forchette sul tavolo, parzialmente implementato nel seguente codice Erlang.
    -module(diningPhil).
    -export([create/1,looptable/1,loopphil/1]).
    
    
    % Funzione ausiliaria che restituisce la coppia degli indici delle forchette
    % associate al filosofo M-esimo (N èl numero totale di filosofi)
    forks(M, N) ->
    	if
    		(M =:= 1) -> {N, 1};
    		true -> {M - 1, M}
    	end.
    
                       
    create(N) ->   
    
       Table = spawn(diningPhil,looptable,[[true| | X<- lists:seq(1,N)]]),
    
       Phils = [spawn(diningPhil,loopphil,[forks(X,N),X,Table]) || X <- lists:seq(1,N)]
    
       true.
    
    
    loopphil({L,R},NumPhil,Table) ->  think(),
                                       ......
                                       eat(),
                                       ......
    
    looptable(ListForksAvailable) -> ...
    
    
    
    Si completi il codice solamente della funzione loopphil. Si assuma che le funzioni think() e eat() siano gia' implementate e che il comportamento di ogni filosofo sia: pensare, mandare richiesta di acquisizione prima forchetta al tavolo, ricevere concessione forchetta, mandare richiesta di acquisizione seconda forchetta al tavolo, ricevere concessione forchetta, mangiare, rilasciare le forchette, e di nuovo cosi', all'infinito. Si assuma che nel sistema non ci sia alcuna politica per evitare uno stallo.

  • Possibile soluzione.
    Esercizio 22
    Implementare in Erlang la funzione che, presa una funzione F ed un numero N, restituisca la somma degli F(i) con i che va da 1 ad N.
    Poiche' il calcolo di F(i) potrebbe risultare pesante dal punto di vista computazionale, si faccia in modo che ogni singolo valore F(i) venga calcolato da un processo apposito.

  • Possibile soluzione.
    Esercizio XX


  • Possibile soluzione.