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

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 3
    Calcolare la funzione factg dell'esercizio 2 in modo da poter parallelizzare al massimo il calcolo.
    Esercizio 4
    Scrivere un predicato in Erlang che controlli se tue dipi PICT (opportunamente rappresentati)sono uno un sottotipo dell'altro. Lo si faccia cercando di far eseguire il controllo da piu' processi. Si renda inoltre la funzione parametrica, in modo da poter fornire come parametro i tipi base che si intendono utilizzare e quale relazione di sottotipaggio c'e' tra di loro.
  • Possibile soluzione. (by rondey)
    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 12 di Haskell
    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

    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.