Extended summary of code building genetic programming
1. UNIVERSITÀ DEGLI STUDI DI
TRIESTE
Dipartimento di Ingegneria e Architettura
Laurea Triennale in Ingegneria Elettronica e
Informatica
Extended Summary of Code Building
Genetic Programming
20 luglio 2021
Laureando Relatore
Martina Maione Chiar.mo Prof. Andrea De Lorenzo
Anno Accademico 2020/2021
3. Capitolo 1
Introduzione
Obiettivo della ricerca
Lo scopo principale di questa ricerca è trovare un sistema per la program-
mazione automatica comparabile alle abilità umane, che idealmente
• produca programmi che gestiscano tipi di dati arbitrari
• supporti la manipolazione di tipi polimorfici
• utilizzi porzioni di codice preesistenti
• non richieda un’ulteriore configurazione per l’utilizzo di astrazioni di
un problema specifico
Tale struttura deve produrre un codice sorgente eseguibile in ogni ambiente.
Importanza
In questo modo il sistema di programmazione automatica avrebbe un for-
te impatto sullo sviluppo di software, in particolare potrebbe essere utiliz-
zato per aggiustare bugs, ottimizzare l’utilizzo delle risorse dei software e
soprattutto risolvere problemi complicati per i programmatori.
1
4. Capitolo 2
Sistemi alternativi di sintesi di
un programma
Esistono alcuni sistemi per la sintesi di programmi molto efficienti, come
PushGP e G3P, che però non rispettano le caratteristiche sopra citate.
2.1 PushGP
PushGP utilizza un linguaggio Push basato su stack.
Lo svantaggio consistente di PushGP è che non riesce a sviluppare programmi
che utilizzano tipi di dati arbitrari senza definire istruzioni aggiuntive, il che
implica la costruzione di un sistema PushGP ad hoc per sfruttare le astrazioni
preesistenti.
2.2 G3P
G3P utilizza una grammatica per ogni tipo di dato supportato.
Il vantaggio di G3P è la produzione di codice sorgente type-safe nell’host lan-
guage e la possibilità di contenere assegnazioni di variabili, flusso di controllo
e iterazione. Tuttavia, per supportare tipi di dati aggiuntivi, bisogna creare
e integrare grammatiche aggiuntive, la cui esatta implementazione influisce
sulle prestazioni del sistema.
Quindi, serve un sistema simile a PushGP e G3P in termini di performance,
ma con delle capacità in più.
2
5. Capitolo 3
Code Building Genetic
Programming
Analizziamo quindi CBGP, una struttura per la sintesi di programmi che ge-
stisce qualsiasi tipo di funzione, supporta tipi polimorfici, integra con porzio-
ni di codice esistenti e trascrive i programmi in codice sorgente interpretabile
dai programmatori umani.
3.1 Struttura dei programmi
CBGP produce come output un grafo diretto e aciclico (DAG), i cui nodi
sono le funzioni e le cui foglie rappresentano dei valori costanti o input.
3.1.1 Espressioni
Le espressioni, ovvero nodi generici, contengono un valore con la relativa
specifica sul tipo di dati. I tipi di espressioni utilizzati sono:
• costanti
• input
• funzioni
• metodi
• costruttori
• funzioni di ordine superiore.
Le costanti e gli input sono foglie che non richiedono nessun argomento.
Se il tipo di dato associato è collection, union o polimorfic, la specifica rap-
presenterà il tipo e le sue parti.
A differenza delle costanti, che restituiscono sempre lo stesso valore, gli input
3
6. CAPITOLO 3. CODE BUILDING GENETIC PROGRAMMING
restituiscono il valore dell’input specifico del programma.
I metodi e i costruttori contengono parti di una definizione di classe pre-
esistente.
Le funzioni sono espressioni che accettano argomenti e restituiscono un
valore. Tutte le espressioni simili a funzioni hanno la stessa tipologia di spe-
cifica: una mappatura dal nome al tipo dell’argomento e un tipo aggiuntivo
che corrisponde al return value.
Se il numero di argomenti è nullo, le funzioni e i costruttori possono essere
foglie, mentre i metodi no, perché vengono considerati funzioni che hanno
come argomento implicito il class instance object.
3.1.2 Funzioni di ordine superiore
Poiché è difficile rappresentare la maggior parte delle forme di iterazione
tramite grafi aciclici, CBGP si avvale delle funzioni di ordine superiore per
manipolare le strutture dati, come ad esempio map e filter.
Le funzioni di ordine superiore sono funzioni che accettano come argo-
mento una o più funzioni e restituiscono una funzione.
3.2 Creazione delle espressioni
I linguaggi di programmazione utilizzano degli strumenti per controlli sul
funzionamento del codice, sia statici che in fase di esecuzione.
3.2.1 Type checking
Un esempio è typing, nella libreria standard di Python, che si occupa del
type check, inserendo dei suggerimenti sul tipo al momento della definizione
di una funzione; inoltre, supporta il confronto dei tipi in fase di esecuzione.
CBGP crea le specifiche sui valori e sulle funzioni all’interno delle espres-
sioni utilizzando le annotazioni sul tipo di Python. Per i tipi polimorfici, le
annotazioni possono rappresentare tipi di dati generici o anche specifici.
3.2.2 Reflection
Un altro strumento utile è la riflessione, per scoprire e manipolare le infor-
mazioni sulle funzioni, i tipi, i valori definiti nell’ambiente e sulle relative
specifiche.
Ciò permette a CBGP di poter gestire e manipolare gli oggetti e di essere,
quindi, inserito in un qualsiasi ambiente in fase di esecuzione, con codice
esistente e dipendenze esterne, creando un insieme di espressioni a partire
dalle variabili, funzioni e classi date. L’unica condizione è che ci sia una
4
7. CAPITOLO 3. CODE BUILDING GENETIC PROGRAMMING
specifica disponibile per tutto ciò che CBGP gestisce.
Conclusione
Quindi, CBGP può sintetizzare programmi che utilizzano codice scritto da
umani, codice sintetizzato precedentemente e librerie esterne, senza modifi-
che o configurazioni aggiuntive. Di conseguenza, le sue prestazioni possono
essere migliorate da uno sviluppatore esterno creando astrazioni aggiuntive.
3.3 Reificazione delle espressioni
Creato l’insieme di espressioni, i programmi DAG vengono costruiti tramite
composizione di espressioni a cui vengono assegnati dei nodi figli, che hanno
tutti gli argomenti richiesti dalla specifica e che devono essere programmi
DAG validi, come ad esempio le costanti, gli input e le funzioni con arity
nulla.
È possibile reificare un’espressione, cioè migliorare e concretizzare la specifica
di una sua istanza, conoscendo la specifica precisa di un’espressione figlia.
Le regole di reificazione in CBGP sono le seguenti:
3.4 Composizione di programmi
Per costruire i programmi DAG, CBGP si ispira al processo di compilazione
basato su stack di PushGP, il quale traduce le espressioni in un programma
type-safe e reificato. In questo modo è improbabile che il programma produca
errori a run-time.
L’input del processo è un insieme di espressioni e la specifica per il valore di
ritorno del programma.
5
8. CAPITOLO 3. CODE BUILDING GENETIC PROGRAMMING
Procedimento
1. Le espressioni vengono inserite in una stack exec dell’interprete Push
per essere processate una alla volta. L’interprete Push di CBGP con-
tiene 2 stack in più rispetto a PushGP: una per i DAG e una per le
definizioni di funzioni anonime
2. Finché la stack exec non è vuota, viene tolto l’ultimo elemento e
processato a seconda del suo tipo.
3. Appena la stack exec è vuota, si estraggono gli elementi dalla stack
DAG finché non viene trovato un DAG il cui tipo del valore di ritorno
è quello giusto.
Se non si produce alcun programma valido, bisogna gestire la situazione con
delle funzioni di errore.
3.5 Compilazione dei programmi
Rappresentazione del genoma
CBGP si ispira profondamente alla programmazione genetica, in cui gli in-
dividui vengono definiti tramite un genoma lineare, cioè una sequenza di
espressioni e di due tipologie di sequenze (open token e close token).
Fasi di traduzione e compilazione
1. I genomi vengono tradotti in codice push
2. Il codice push viene compilato in un programma DAG
Semplificazione del genoma
Viene, poi, implementata una strategia di selezione “evolutiva” degli indi-
vidui avente come fine la semplificazione del genoma, senza compromettere
la performance. Infatti, genomi semplificati implicano programmi DAG con
performance migliori.
3.6 Valutazione dei programmi
Dopo la traduzione del genoma in codice Push e la compilazione in un pro-
gramma DAG, si ha la fase di valutazione del programma da parte di una
funzione di errore su un insieme di casi di addestramento contenenti coppie
di input-output.
- Se la compilazione non produce un programma che restituisce il tipo richie-
sto per il problema, viene assegnato un errore all’individuo per ogni caso di
addestramento.
6
9. CAPITOLO 3. CODE BUILDING GENETIC PROGRAMMING
- Se si ha un’eccezione in fase di esecuzione, può essere catturata e viene
assegnato un errore al caso di addestramento.
Vantaggi
• Un vantaggio è che, mentre PushGP richiede un’esecuzione separata
dell’interprete per ogni caso, CBGP compila i programmi DAG una
sola volta e poi valuta l’individuo su tutti i casi
• Un altro aspetto importante è che, anche se la valutazione è la fase più
costosa del ciclo evolutivo, CBGP riesce a ridurre tali costi.
3.7 Creazione di codice sorgente
Nota la sintassi dell’host language, si può creare codice sorgente a partire da
un programma DAG, in modo da rendere l’output di CBGP interpretabile
dai programmatori umani, riutilizzabile e non vincolato ad un ambiente spe-
cifico.
Conclusione
La creazione di codice sorgente, che include chiamate a funzioni e meto-
di, porta quindi ad una cooperazione tra programmatori umani e strutture
ausiliarie di sintesi di un programma.
7
10. Capitolo 4
Analisi delle performance di
CBGP
In questo studio sono stati considerati dei problemi benchmark per dimo-
strare la capacità di CBGP di gestire tipi polimorfici, tramite il problema
“Filter Bounds”, e di integrare con codebase esistenti, tramite i problemi
“Days Between” e “Prefix Paths”.
Inoltre, si è andato a testare CBGP su un altro insieme standard di pro-
blemi, preso dal “General Program Synthesis Benchmark Suite”, andando a
confrontare CBGP con PushGP e G3P.
Risultati
Da queste analisi si vede che CBGP è efficiente o comunque confrontabile in
termini di performance ad altri sistemi per quanto riguarda alcuni problemi,
mentre è poco efficiente su altri.
8
11. CAPITOLO 4. ANALISI DELLE PERFORMANCE DI CBGP
Si noti, però, che ci sono delle differenze nelle funzioni supportate: men-
tre PushGP e G3P selezionano un sottoinsieme di operazioni e tipi di dati
supportati da includere prima dell’esecuzione e che cambia ad ogni proble-
ma, CBGP utilizza tutte le funzioni e classi, causando talvolta prestazioni
peggiori.
9
12. Conclusioni e studi futuri
In conclusione, CBGP è il primo sistema di programmazione genetica con
la capacità di sintetizzare programmi con tipi di dati arbitrari e polimorfici
e che è in grado di riutilizzare porzioni di codice preesistente, riducendo la
necessità di configurazioni aggiuntive.
Tali caratteristiche rendono CBGP un sistema facilmente utilizzabile e ver-
satile.
4.1 Ricerche future
Per gli studi futuri, è interessante analizzare in dettaglio l’ampio campo di
applicazione di CBGP e testare su un insieme più vasto di problemi le sue
abilità.
Un altro aspetto da approfondire è l’utilizzo di algoritmi di ottimizzazione
per la produzione di programmi più efficienti in termini di risorse e più facili
da convertire in codice sorgente.
Infine, sarebbe utile un’implementazione di CBGP che consideri più infor-
mazioni rispetto al tipo di dati, evitando la maggior parte degli errori in fase
di esecuzione.
10
13. Bibliografia
[1] Pantridge E.R., Spector L.A. GECCO ’20: Proceedings of the 2020
Genetic and Evolutionary Computation Conference on Code Building
Genetic Programming, 25 june 2020, New York, NY, United States.
11