-
Notifications
You must be signed in to change notification settings - Fork 1
/
README.txt
175 lines (126 loc) · 5.93 KB
/
README.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
Grammatical evolution (GE) is an evolutionary algorithm which uses
formal grammars, written in BNF, to define the search space. PonyGE is
a small (one source file! with some extra examples in separate source
files) but functional implementation of GE in Python. It's intended as
an advertisement and a starting-point for those new to GE, a reference
for implementors and researchers, a rapid-prototyping medium for our
own experiments, and a Python workout. And a pony.
PonyGE is copyright (C) 2009-2012 Erik Hemberg
<erik.hemberg@gmail.com> and James McDermott
<jamesmichaelmcdermott@gmail.com>.
Requirements
------------
PonyGE runs under Python 2.4+ and Python 3.x. The most interesting
example problem (see L-System below) requires Python 2.6+ or 3.x and
Tkinter.
Running PonyGE
--------------
We don't provide any setup script. You can run an example problem (the
default is String-match, see below) just by saying:
$ cd src
$ ./ponyge.py
Each line of the output corresponds to a generation in the evolution,
and tells you the generation number, number of fitness evaluations
which have taken place, average fitness with standard deviation,
average number of codons used (see any GE paper, eg those referenced
below, for definition) with standard deviation and the best
individual found so far. At the end, the best individual is printed
out again.
There are a number of flags that can be used for passing values via
the command-line. For example, running the default problem for 10
generations:
$ ./ponyge.py -g 10
Writing grammars
----------------
Grammars are written in Backus-Naur form, aka BNF. See the examples in
src/grammars. Each rule is composed of a left-hand side (a single
non-terminal), followed by the "goes-to" symbol ::=, followed by a
list of productions separated by the "or" symbol |. Non-terminals are
enclosed by angle brackets <>. For example:
<a> ::= <b>c | d
You can use an "or" symbol or angle bracket in a production. Escape it
using a backslash: \|, \<, \>. You can use the "goes-to" symbol in a
production without escaping it.
Example Problems
----------------
String-match
------------
The grammar specifies words as lists of vowels and consonants. The aim
is to match a target word. This is the default problem: as you can see
in ponyge.py, the necessary grammar and fitness function are specified
by default:
GRAMMAR_FILE, FITNESS_FUNCTION = "grammars/letter.bnf", \
StringMatch("golden")
Max
---
The grammar specifies legal ways of combining numbers using arithmetic
operations. The aim is to create the largest value possible. Use the
following grammar and fitness function (in ponyge.py):
GRAMMAR_FILE, FITNESS_FUNCTION = "grammars/arithmetic.pybnf", \
MaxFitness()
XOR
---
A small version of the standard genetic programming Even-N parity
benchmark. The grammar specifies two inputs, x and y, and allows them
to be combined using AND, OR, and NOT. The aim is to evolve the XOR
function. Use the following grammar and fitness function:
GRAMMAR_FILE, FITNESS_FUNCTION = "grammars/boolean.pybnf", \
XORFitness()
EvenNParity
-----------
A standard genetic programming benchmark. The grammar specifies a list
of N-inputs, and allows them to be combined using AND, OR, NOR and
NAND, reduce(), head() and tail(). The aim is to evolve a function
that outputs true if the parity of the inputs are even. Use the
following grammar and fitness function for N=3:
GRAMMAR_FILE, FITNESS_FUNCTION = "grammars/hofBoolean.pybnf", \
EvenNParityFitness(3)
L-System and P-system
---------------------
The most interesting examples. Run it like this (no need to make any
source code changes):
$ ./start-lsystem.sh
Or:
$ ./start-psystem.sh
You'll be presented with a GUI showing nine drawings in a 3x3 grid of
cells. You click on the ones you like, and click "Next" (or hit space)
to iterate the algorithm. The drawings are made using a custom
L-system or P-system whose possible forms are specified by the
grammar. The files gui.py, drawing.py, lsystem.py, psystem.py,
grammars/lsystem.bnf, grammars/psystem.bnf all belong to this example.
N-Player Iterated Prisoner's Dilemma
------------------------------------
The other most interesting example. The prisoner's dilemma
(en.wikipedia.org/wiki/Prisoner's_dilemma) is a well-known game where
two players must decide whether to cooperate or defect: each is
individually better off to defect, but if they both cooperate they do
better than if they both defect. In the iterated version the players
play against each other multiple times, so it makes sense for them to
establish cooperation. But in the N-player version, cooperation is
less likely to arise. In our implementation, players must choose among
four hard-coded strategies which may be dependent on previous rounds.
In the next version of PonyGE we will add the possibility of more
complex, fine-grained behaviours.
Run it like this, for a basic 2-player game (no need for source code
changes):
./ponyge.py -b grammars/nipd.pybnf -f \
"NPlayerIteratedPrisonersDilemmaFitness(100, 2, 50)" -p 10 -g 50 -e 0 \
-m 0.2
Here, 100 is the number of rounds to play in each game; 2 is the
number of players in each game, sampled randomly from population; 50
is the number of games to play in each generation (should be enough to
make sure every player in population plays often); 10 is the
population size (must be greater than number of players); 50 is the
number of generations; 0 is the elite size (zero here, because in this
coevolutionary setup a player's fitness depends on its opponents, so
players shouldn't keep their fitness from previous generations); and
0.2 is the mutation rate.
Reference
---------
Michael O'Neill and Conor Ryan, "Grammatical Evolution: Evolutionary
Automatic Programming in an Arbitrary Language", Kluwer Academic
Publishers, 2003.
Michael O'Neill, Erik Hemberg, Conor Gilligan, Elliott Bartley, and
James McDermott, "GEVA: Grammatical Evolution in Java", ACM
SIGEVOlution, 2008. http://portal.acm.org/citation.cfm?id=1527066. Get
GEVA: http://ncra.ucd.ie/Site/GEVA.html