Menu Chiudi

Programmare senza un linguaggio di programmazione 2/3

Il modello del mercatino

Un esempio concreto

Vedi anche Programmare senza un linguaggio di programmazione 1/3. Introduzione a Blockly inoltre propone una serie di videotutorial introduttivi a questo generatore di codice.

Per spiegare meglio la nostra idea di coding la applicheremo a un problema concreto. Quello che segue è la cronaca (in sintesi) di una esperienza di laboratorio proposta al gruppo che si è occupato del Modello affine per la distribuzione della ricchezza. Quando abbiamo affrontato il laboratorio studenti e studentesse avevano già approfittato del corso introduttivo a Blockly presente su questo sito.

Vogliamo costruire un’app che replichi il modello del mercatino di Anirban Chakraborty. Il modello funziona in questo modo: un gruppo di individui, spesso chiamati agenti, hanno una ricchezza iniziale che supporremo uguale per tutti. Coppie di agenti, selezionati a caso, svolgono semplici transazioni finanziarie che prevedono lo spostamento di una certa quantità di ricchezza (una frazione della ricchezza posseduta dal più povero dei due) a vantaggio di un agente scelto casualmente. Lo scopo è studiare la distribuzione della ricchezza che si ottiene dopo un gran numero di transazioni.

Una prima stesura

Dopo un’ampia discussione sul modello e la simulazione con alcuni semplici esempi la bozza l’algoritmo è stato formalizzato in questo modo:

ripeti n volte
  scegli due agenti
  scegli una frazione della ricchezza del più povero
  scegli a caso un agente
  aumenta la ricchezza dell’agente scelto
  diminuisci la ricchezza dell’altro agente

Se facciamo riferimento alla definizione di algoritmo che abbiamo presentato nel primo articolo appare evidente che siamo ben lontani dall’obiettivo. In particolare:

  • non è definito chiaramente un input del programma;
  • non è chiaro quanto vale la ricchezza degli agenti;
  • ma soprattutto nessuna delle istruzioni è chiara ed elementare.

Input

Concentrando l’attenzione soprattutto sul primo punto critico (l’input) abbiamo realizzato una nuova stesura dell’algoritmo:

transazioni = numero di transazioni
numeroAgenti = numero degli agenti
ricchezzaTotale = la ricchezza di tutti gli agenti
ricchezzaAgenti = ricchezzaTotale / numeroAgenti
ripeti n volte
  scegli due agenti
  scegli una frazione della ricchezza del più povero
  scegli a caso un agente
  aumenta la ricchezza dell’agente scelto
  diminuisci la ricchezza dell’altro agente

Le modifiche più importanti riguardano proprio i valori, i parametri iniziali del modello (e quindi dell’algoritmo). Ora è chiaro (e leggibile, grazie a una scelta oculata dei nomi delle variabili) quante saranno le transazioni da eseguire, quanti gli agenti e la ricchezza posseduta da ciascuno di loro (anche se non è evidente come memorizzare la ricchezza di ciascuno quando sarà modificata dalle transazioni). Molto meno chiara invece è la procedura per scegliere i due agenti e le procedure per aumentare e diminuire la ricchezza di ciascun agente coinvolto sono molto ambigue.

Scelta dei due agenti

La scelta dei due agenti è una procedura abbastanza complessa anche perché il secondo non può essere uguale al primo. Proviamo a incapsulare in una funzione a parte questo processo. Procediamo in questo modo: scegliamo il primo agente e solo successivamente il secondo in modo che sia differente dal primo (le tre righe in grassetto sono commenti che hanno lo scopo di rendere più chiaro l’obiettivo della mini-procedura).

ScegliAgente(n, p)
    restituisce un agente scelto a caso diverso da p
    n è il numero degli agenti, p l’agente già scelto
    zero se si sta scegliendo il primo
    u = p
    ripeti finché u = p
        u = numero casuale tra 1 e n
    restituisci u

Questa porzione di codice si può tradurre in Blockly e testare immediatamente.

Il blocco di colore viola racchiude la procedura ScegliAgente e specifica anche i due parametri n e p. Il blocco si chiude restituendo l’identificatore dell’agente scelto. Notare che Blockly permette di commentare una procedura/funzione.

La procedura si può mettere alla prova con un piccolo programma di soli sei blocchi.

ScegliAgente è chiamata due volte: la prima con il parametro p pari a zero, la seconda volta p è uguale al valore scelto nel primo caso in questo modo il secondo agente non sarà uguale al primo.

Quando si iniziano a creare funzioni e procedure con Blockly può essere utile leggere Blockly: istruzioni per l’uso 1 su questo stesso sito, ci sono alcune cose da sapere su come il generatore di codice di Google tratta le variabili.

Una seconda stesura

A questo punto siamo pronti per una seconda versione del nostro programma (in grassetto sono evidenziate le due righe in cui usiamo la procedura ScegliAgente). Contemporaneamente abbiamo modificato la fase di inizializzazione supponendo di memorizzare la ricchezza di ogni agente in una lista (la quarta riga della procedura qui di seguito).

transazioni = numero di transazioni
numeroAgenti = numero degli agenti
ricchezzaTotale = la ricchezza di tutti gli agenti
ricchezzaAgenti =  crea una lista con tutti gli elementi pari a ricchezzaAgenti:    
                   ricchezzaTotale / numeroAgenti
ripeti transazioni volte
    v = ScegliAgente(numeroAgenti, 0)
    w = ScegliAgente(numeroAgenti, v)
    delta = frazione di minimo(tra ricchezza di v e w)
    Scegli a caso un agente
    Aumenta la ricchezza dell’agente
    Diminuisci la ricchezza dell’altro agente

La lista della ricchezza degli agenti

La frase:

crea una lista con tutti gli elementi pari a ricchezzaAgenti:                                                           
                                           ricchezzaTotale / numeroAgenti

richiede tutta una serie di operazioni e quindi potrebbe essere utile racchiudere queste operazioni in una nuova mini-procedura che si occupa solo di inizializzare la lista (le righe in grassetto sono commenti e non codice da eseguire).

CreaListaRicchezzaAgenti(n, r)
    crea una lista contenente la ricchezza di ogni agente
    inizialmente la ricchezza è uguale per tutti
    n è il numero degli agenti
    r la ricchezza totale (di tutti gli agenti)
    l = crea una lista vuota
    ripeti n volte
        in l aggiungi un elemento: r / n
    restituisci l

Questa funzione crea la lista l che ha un elemento per ogni agente e la riempie con il valore medio della ricchezza.

Ecco la funzione CreaListaRicchezzaAgenti implementata con Blockly. La funzione restituisce la lista della ricchezza degli agenti che sarà usata nel seguito del programma.

Come già visto, anche questa funzione può essere immediatamente messa alla prova con un semplice programma di due soli blocchi:

Si chiede la creazione di una lista con dieci elementi (dieci agenti) e ogni elemento della lista avrà come valore la ricchezza media (1000/10). Il blocco print visualizza a video la lista.

La seconda stesura ora è decisamente migliore (in grassetto è evidenziata la riga che richiama la funzione appena realizzata).

transazioni = numero di transazioni
numeroAgenti = numero degli agenti
ricchezzaTotale = la ricchezza di tutti gli agenti
ricchezzaAgenti = CreaListaRicchezzaAgenti(numeroAgenti,ricchezzaTotale)
ripeti transazioni volte
    v = ScegliAgente(numeroAgenti, 0)
    w = ScegliAgente(numeroAgenti, v)
    delta = frazione casuale di minimo(tra ricchezza di v e w)
    Scegli a caso un agente
    Aumenta la ricchezza dell’agente
    Diminuisci la ricchezza dell’altro agente

Una terza stesura

A questo punto dobbiamo precisare meglio le frasi Aumenta la ricchezza dell’agente e DIminuisci la ricchezza dell’agente perché i valori corrispondenti devono essere prelevati dalla lista e reinseriti nella lista per l’aggiornamento. Dopo un po’ di lavoro, non facile a dire la verità, si arriva a una versione migliore. L’agente che ottiene vantaggio dalla transazione è scelto calcolando un numero casuale tra 0 e 1 e confrontandolo con il valore medio 0.5 (le righe corrispondenti sono evidenziate in grassetto).

ripeti transazioni volte
    v = ScegliAgente(numeroAgenti, 0)
    w = ScegliAgente(numeroAgenti, v)
    rv = ricchezzaAgenti[v]
    rw = ricchezzaAgenti[w]
    delta = frazione casuale * minimo(rv, rw)
    if numero casuale tra zero e 1 < 0.5
      rv = rv + dw
      rw = rw – dw
    else
      v = v - dw
      w = w + dw
    ricchezzaAgenti[v] = rv
    ricchezzaAgenti[w] = rw

Stesura finale

Possiamo ora concludere racchiudendo il modello del mercatino in un’unica funzione che accetta come parametri i valori iniziali della simulazione (numero degli agenti, ricchezza totale e numero delle transazioni) e restituisce la lista della ricchezza dei singoli agenti dopo aver eseguito le transazioni richieste. In questo caso il programma principale diventa più leggero e leggibile (in grassetto la riga della procedura che richiama la funzione ModelloMercatino.

transazioni = numero di transazioni
numeroAgenti = numero degli agenti
ricchezzaTotale = la ricchezza di tutti gli agenti
visualizza ModelloMercatino(numeroAgenti, ricchezzaTotale, transazioni)
La funzione ModelloMercatino implementata con Blockly. I blocchi in colore blu più scuro sono quelli che si occupano di gestire la lista della ricchezza degli agenti. La funzione restituisce la lista l che contiene proprio queste ricchezze, modificate dalla simulazione.

Per concludere, un paio di esempio di come è possibile utilizzare il codice generato da Blockly in altri ambienti.

Articoli correlati