Professional Documents
Culture Documents
algoritmos evolutivos
Daniel Molina Juan Manuel Dodero
Resumen El uso de pruebas autom
aticas es una herramienta muy u
til para detectar errores en el c
odigo,
pero el comportamiento no-determinista de ciertos
operadores de los algoritmos evolutivos impide que
los resultados sean repetibles, con lo que se suele considerar que no son aplicables. En este trabajo se proponen nuevas estrategias de pruebas especficas para
estos casos. Las estrategias propuestas permiten comprobar las caractersticas de los operadores, y hacer
pruebas de bajo nivel sobre los operadores a pesar del
uso de n
umeros seudoaleatorios. Para demostar el uso
estas estrategias, se aplican a un algoritmo gen
etico
estacionario, comprobando c
omo se pueden realizar
pruebas autom
aticas sobre los algoritmos evolutivos.
Palabras clave algoritmos evolutivos, tests, pruebas autom
aticas, no determinismo, behavior driven
development
n
I. Introduccio
Los algoritmos evolutivos [1], AEs, son algoritmos
no deterministas que han demostrado obtener muy
buenos resultados en todo tipo de problemas complejos [2].
Como todo programa, las implementaciones de los
AEs son susceptibles de tener errores en su programaci
on, errores que pueden reducirse por medio de
tecnicas como el uso de pruebas autom
aticas [3].
Especialmente interesante es el uso de Test-Driven
Development que planea desarrollar el software partiendo de la especificaci
on de los tests [4], [5]. Este
enfoque parece permitir obtener una mejora visible
en el ratio de errores [6].
Lamentablemente, el car
acter no determinista
(por el uso de operadores seudoaleatorios) de los AEs
impiden que los resultados sean repetibles, dificultando las pruebas [7], [8], lo que conduce a una falta
de pruebas en partes del algoritmo que pueden ser
crticas.
Sin embargo, en los u
ltimos a
nos han surgido nuevos enfoques, tecnicas y herramientas que abren nuevas posibilidades. Uno de estos nuevos enfoques es
la metodologa Behavior Driven Development, BDD,
que predica especificar las pruebas desde el punto de
vista del cliente, describiendo las funcionalidades requeridas en vez de detalles de implementacion [9].
A la hora de probar una clase, hay que valorar las
dependencias con otras, ya que la parte que se desea
probar puede llamar a su vez a clases auxiliares, lo
cual dificulta las pruebas. Para resolver este problema, ha surgido la tecnica de definir objetos mocks
que mantienen el mismo interfaz de las clases auxiliares, y que permiten probar la clase cuando a
un
Universidad de C
adiz. E-mail: daniel.molina@uca.es
Universidad de C
adiz. E-mail: juanma.dodero@uca.es
2 http://jbehave.org/
3 http://lettuce.it/
Scenario : <D e s c r i p c i o
n>
Given < s e n t e n c e i n i t >
When <s e n t e n c e c o n d i t i o n >
Then <s e n t e n c e e x p e c t e d >
ra 1, en donde la secci
on Given describe el estado
del sistema antes de un evento, When describe las
condiciones del evento que se quiere probar, y Then
indica el resultado esperado tras el evento. La Figura
2 muestra, como ejemplo, una definici
on de pruebas
sobre el operador factorial.
F e a t u r e : Compute f a c t o r i a l
I n o r d e r t o p l a y w i t h BDD
As b e g i n n e r s
We l l implement f a c t o r i a l
Scenario : F a c t o r i a l o f 0
Given I have t h e number 0
When I compute i t s f a c t o r i a l
Then I s e e t h e number 1
@step ( I s e e t h e number ( \ d + ) )
d e f check number ( s t e p , e x p e c t e d ) :
expected = int ( expected )
a s s e r t w o r l d . number == e x p e c t e d
Scenario : F a c t o r i a l o f 1
Given I have t h e number 1
When I compute i t s f a c t o r i a l
Then I s e e t h e number 1
Scenario : F a c t o r i a l o f 2
Given I have t h e number 2
When I compute i t s f a c t o r i a l
Then I s e e t h e number 2
Scenario : F a c t o r i a l o f 5
Given I have t h e number 5
When I compute i t s f a c t o r i a l
Then I s e e t h e number 120
Fig. 2. Definici
on de los tests sobre el operador factorial
Para hacer la prueba se usa el programa BDD asociado (lettuce en este caso). En la Figura 5 se observa la salida cuando no hay error, y en la Figura 6 la
salida cuando el test detecta un error. Se puede observar que indica la comprobacion concreta que no
se cumple.
$ l e t t u c e v 2 .
F a c t o r i a l o f s e v e r a l numbers
1 f e a t u r e (1 passed )
4 s c e n a r i o s (4 passed )
12 s t e p s ( 1 2 p a s s e d )
...
|
|
|
|
|
expected result
1
1
2
120
|
|
|
|
|
Fig. 3. Definici
on concisa de tests sobre factorial
$ l e t t u c e v 3 .
F e a t u r e : Compute f a c t o r i a l
# tests / features / factorial . feature :1
...
Tr ac eb ack ( most r e c e n t c a l l l a s t ) :
F i l e . . . / l e t t u c e / c o r e . py , l i n e 1 1 3 , i n \
call
r e t = s e l f . f u n c t i o n ( s e l f . s t e p , a r g s , kw )
F i l e . . . / t e s t s / f e a t u r e s / s t e p s . py , l i n e 15 \
i n check number
a s s e r t w o r l d . number == e x p e c t e d
AssertionError
1 f e a t u r e (0 passed )
4 s c e n a r i o s (3 passed )
12 s t e p s ( 1 f a i l e d , 11 p a s s e d )
los
tests
el c
odigo del algoritmo como
est
a libremente disponible en
el
la
de
url
F e a t u r e : SSGA I n i t
I n o r d e r t o t e s t SSGA we t e s t t h a t t h e i n i t
p o p u l a t i o n h as t h e r i g h t p o p s i z e ,
d i m e n s i o n , and t h a t i n i t i a l f i t n e s s between
the i n d i v i d u a l s are d i f f e r e n t .
Scenario : I n i t P o p u l a t i o n
Given I have an SSGA a l g o r i t h m \
f o r d i m e n s i o n <d i m e n s i o n >
When I i n i t t h e p o p u l a t i o n w i t h \
<p o p s i z e > i n d i v i d u a l s
Then t h e p o p u l a t i o n s i z e i s <p o p s i z e >
Then d i m e n s i o n f o r e a c h i n d i v i d u a l \
i s <d i m e n s i o n >
Then f i t n e s s i s i n i t i a l i z e d
El algoritmo elegido es un algoritmo genetico estacionario, SSGA, que hace uso del operador de cruce BLX [12]. Como mecanismo de seleccion de
padres, se aplica el criterio Negative Assortative Mating, NAM. El primer padre es elegido de forma aleatoria de la poblaci
on, y para calcular el segundo padre se seleccionan aleatoriamente Nnum soluciones
y se elige la soluci
on m
as alejada del primer padre.
Como mecanismo de reemplazo se elige el Replacement Worst, en el que el nuevo individuo reemplaza
al peor individuo de la poblaci
on, si lo mejora. Se
ha demostrado que esta combinaci
on de seleccion y
reemplazo permite un adecuado equilibrio entre exploraci
on y explotaci
on [13].
Se puede observar que es un algoritmo que aunque simple posee caractersticas tpicas de un algoritmo evolutivo tpico: Es un algoritmo poblacional,
elitista, y con distintas operaciones con componente
aleatorio: cruce, y selecci
on.
F e a t u r e : SSGA C r o s s o v e r
Check f o r BLX0 t h a t c r o s s i n g a s o l u t i o n
w i t h i t s e l f g i v e s t h e same s o l u t i o n ,
and t h a t o f f s p r i n g a r e a l w a y s between
their parents
Scenario : C r o s s o v e r w i t h i t s e l f
Given I have an SSGA a l g o r i t h m
When I i n i t t h e p o p u l a t i o n w i t h \
50 i n d i v i d u a l s
When I s e t t h e same p a r e n t a s mother
When I c r o s s w i t h a l p h a 0
Then t h e c h i l d r e n i s t h e same
Scenario : O f f s p r i n g i s between t h e i r p a r e n t s
Given I have an SSGA a l g o r i t h m
When I i n i t t h e p o p u l a t i o n w i t h \
50 i n d i v i d u a l s
When I s e t randomly two p a r e n t s
When I c r o s s w i t h a l p h a 0
Then t h e c h i l d r e n i s between them
| n u m i t e r a | num eval |
|
1000
|
1000
|
Scenario : SSGA i s e l i t i s t
Given I have a SSGA a l g o r i t h m
When I i n i t t h e p o p u l a t i o n w i t h \
50 i n d i v i d u a l s
When I s t u d y t h e e v o l u t i o n o f t h e \
<i n d i v i d u a l > i n d i v i d u a l
When I run t h e a l g o r i t h m d u r i n g \
<n u m i t e r a > i t e r a t i o n s
Then i t s f i t n e s s i s a l w a y s b e t t e r
Examples :
| individual
|
best
|
worst
|
mean
| num itera
|
1000
|
1000
|
1000
|
|
|
|
criterion
minimum
maximum
mean
|
|
|
|
Fig. 12. C
odigo que modifica los n
umeros seudoaleatorios
T B
ack, D B Fogel, and Z Michalewicz, Eds., Handbook of Evolutionary Computation, IOP Publishing Ltd.,
Bristol, UK, 1997.
Patrick Siarry and Zbigniew Michalewicz, Advances in
metaheuristics for hard optimization, Springer-Verlag
New York Inc, springer edition, 2007.
G J Myers, C Sandler, T Badgett, and T M Thomas,
The art of software testing, 2004.
K Beck, Test-driven development: by example, AddisonWesley Professional, 2003.
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
[13]
Forrest Shull, Grigori Melnik, Burak Turhan, Lucas Layman, Madeline Diep, and Hakan Erdogmus, What Do
We Know about Test-Driven Development?, IEEE Software, vol. 27, no. 6, pp. 1619, 2010.
Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, and Laurie Williams, Realizing quality
improvement through test driven development: results
and experiences of four industrial teams, Empirical
Software Engineering, vol. 13, no. 3, pp. 289302, Feb.
2008.
R.M. Hierons, Testing from a nondeterministic finite state machine using adaptive state counting, IEEE
Transactions on Computers, vol. 53, no. 10, pp. 1330
1342, Oct. 2004.
Gordon Fraser and Franz Wotawa, Test-Case Generation and Coverage Analysis for Nondeterministic Systems Using Model-Checkers, International Conference
on Software Engineering Advances (ICSEA 2007), pp.
4545, 2007.
D Chelimsky, D Astels, Z Dennis, A Hellesoy, B Helmkamp, and D North, The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends,
Pragmatic Bookshelf, 2010.
Madhuri R. Marri, Nikolai Tillmann, Jonathan de Halleux, and Wolfram Schulte, An empirical study of testing file-system-dependent software with mock objects,
2009 ICSE Workshop on Automation of Software Test,
pp. 149153, May 2009.
F Herrera, M Lozano, and A.M. Sanchez, A Taxonomy
for the Crossover Operator for Real-coded Genetic Algorithms, International Journal of Intelligent Systems,
vol. 18, no. 3, pp. 204217, 2003.
L.J. Eshelman and J.D. Schaffer, Real-coded Genetic
Algorithms in Genetic Algorithms by Preventing Incest,
Foundation of Genetic Algorithms 2, pp. 187202, 1993.
D Whitley, The GENITOR Algorithm and Selection
Pressure: Why Rank-Based Allocation of Reproductive
Trials is Best, Proc. of the Third Int. Conf. on Genetic
Algorithms, pp. 116121, 1989.
Inicializaci
on
@step ( I have a SSGA a l g o r i t h m f o r d i m e n s i o n ( \ d + ) )
d e f h a v e c o n f i g u r a t i o n ( s t e p , dim ) :
dim = i n t ( dim )
w o r l d . s s g a = SSGA( f i t n e s s , domain , dim , s i z e=p o p s i z e )
@step ( I i n i t t h e p o p u l a t i o n w i t h ( \ d+) i n d i v i d u a l s )
def i n i t p o p u l a t i o n ( step , popsize ) :
world . p o p s i z e = i n t ( p o p s i z e )
world . s s g a . i n i t P o p u l a t i o n ( i n t ( p o p s i z e ) )
@step ( p o p u l a t i o n s i z e i s ( \ d + ) )
def p o p s i z e r i g h t ( step , p op si z e e xp ec t ed ) :
popsize expected = int ( popsize expected )
( v a l u e s s i z e , v a l u e s d i m )= w o r l d . s s g a . p o p u l a t i o n ( ) . s h a p e
a s s e r t v a l u e s s i z e == p o p s i z e e x p e c t e d
@step ( f i t n e s s i s i n i t i a l i z e d )
def f i t n e s s r i g h t ( step ) :
f i t s = world . s s g a . p o p u l a t i o n f i t n e s s ( )
a s s e r t f i t s . s i z e == w o r l d . p o p s i z e
@step ( a l l f i t n e s s v a l u e s a r e d i f f e r e n t )
def fitness not same ( step ) :
f i t s = world . s s g a . p o p u l a t i o n f i t n e s s ( )
# Check t h e s i z e o f removing e q u a l s f i t n e s s
a s s e r t np . u n i q u e ( f i t s ) . s i z e == w o r l d . p o p s i z e
Selecci
on
@step ( I s e l e c t p a r e n t s w i t h tournament s i z e ( \ d + ) )
def s e t p a r e n t s ( step , t s i z e ) :
w o r l d . n a m t s i z e=i n t ( t s i z e )
@step ( t h e p a r e n t s a r e d i f f e r e n t a f t e r ( \ d+) t e s t s )
def m o t h e r p a r e n t d i f f e r e n t ( step , t e s t s ) :
tests = int ( tests )
for
i in range ( t e s t s ) :
[ mother , p a r e n t ]= w o r l d . s s g a . g e t P a r e n t s ( w o r l d . n a m t s i z e )
a s s e r t mother != p a r e n t
@step ( t h e d i s t a n c e between p a r e n t s i s t h e l o n g e s t )
def best parent ( step ) :
s s g a = world . s s g a
[ motherId , p a r e n t I d ]= s s g a . g e t P a r e n t s ( w o r l d . n a m t s i z e )
population = ssga . population ()
mother = p o p u l a t i o n [ motherId ]
parent = population [ parentId ]
d i s t a n c e s = [ u t i l s . d i s t a n c e ( p o p u l a t i o n [ i ] , mother ) f o r
m a x d i s t a n c e s = np . a r r a y ( d i s t a n c e s ) . max ( )
d i s t a n c e = u t i l s . d i s t a n c e ( p a r e n t , mother )
a s s e r t d i s t a n c e == m a x d i s t a n c e s
i n range ( world . p o p s i z e ) ]
Cruce
@step ( I s e t t h e same p a r e n t a s mother )
def set parents same ( s e l f ) :
p o p u l a t i o n = world . s s g a . p o p u l a t i o n ( )
motherId = random . r a n d i n t ( 0 , w o r l d . s s g a . p o p s i z e )
w o r l d . mother = p o p u l a t i o n [ motherId ]
w o r l d . p a r e n t = w o r l d . mother
@step ( I s e t randomly two p a r e n t s )
def cross set random ( step ) :
p o p u l a t i o n = world . s s g a . p o p u l a t i o n ( )
[ motherId , p a r e n t I d ] = random . r a n d i n t ( 0 , w o r l d . s s g a . p o p s i z e , 2 )
w o r l d . mother = p o p u l a t i o n [ motherId ]
w o r l d . p a r e n t= p o p u l a t i o n [ p a r e n t I d ]
@step ( I c r o s s w i t h a l p h a ( [ \ d . ] + ) )
def a p p l y c r o s s ( s e l f , alpha ) :
alpha = f l o a t ( alpha )
w o r l d . c h i l d r e n = w o r l d . s s g a . c r o s s ( w o r l d . mother , w o r l d . p a r e n t , a l p h a )
@step ( The c h i l d r e n i s t h e same )
def has same children ( s e l f ) :
a s s e r t u t i l s . d i s t a n c e ( w o r l d . c h i l d r e n , w o r l d . p a r e n t )==0
@step ( The c h i l d r e n i s between them )
def is between then ( s e l f ) :
p a r e n t s = np . a r r a y ( [ w o r l d . mother , w o r l d . p a r e n t ] )
m i n p a r e n t = np . amin ( p a r e n t s , a x i s =0)
max parent = np . amax ( p a r e n t s , a x i s =0)
a s s e r t ( w o r l d . c h i l d r e n >= m i n p a r e n t ) . a l l ( ) , B r o k e s i n f e r i o r
a s s e r t ( w o r l d . c h i l d r e n <= max parent ) . a l l ( ) , B r o k e s s u p e r i o r
limit
limit
@step ( t h e p a r e n t s a r e d i f f e r e n t a f t e r ( \ d+) t e s t s )
def m o t h e r p a r e n t d i f f e r e n t ( step , t e s t s ) :
tests = int ( tests )
for
i in range ( t e s t s ) :
[ mother , p a r e n t ]= w o r l d . s s g a . g e t P a r e n t s ( w o r l d . n a m t s i z e )
a s s e r t mother != p a r e n t
@step ( t h e d i s t a n c e between p a r e n t s i s t h e l o n g e s t )
def best ! ! parent ( step ) :
s s g a = world . s s g a
[ motherId , p a r e n t I d ]= s s g a . g e t P a r e n t s ( w o r l d . n a m t s i z e )
population = ssga . population ()
mother = p o p u l a t i o n [ motherId ]
parent = population [ parentId ]
d i s t a n c e s = [ u t i l s . d i s t a n c e ( p o p u l a t i o n [ i ] , mother ) f o r
m a x d i s t a n c e s = np . a r r a y ( d i s t a n c e s ) . max ( )
d i s t a n c e = u t i l s . d i s t a n c e ( p a r e n t , mother )
a s s e r t d i s t a n c e == m a x d i s t a n c e s
i n range ( world . p o p s i z e ) ]
Ejecuci
on
\ begin { l s t l i s t i n g }
d e f m e a s u r e F i t n e s s ( a r g s , kwargs ) :
i f w o r l d . f i t E v a l == [ ] :
w o r l d . f i t E v a l . append ( w o r l d . g e t f i t n e s s ( w o r l d . s s g a . p o p u l a t i o n f i t n e s s ( ) ) )
y i e l d aspects . proceed
w o r l d . f i t E v a l . append ( w o r l d . g e t f i t n e s s ( w o r l d . s s g a . p o p u l a t i o n f i t n e s s ( ) ) )
@step ( I s t u d y t h e e v o l u t i o n o f t h e ( \w+) i n d i v i d u a l )
def study population ( s e l f , individual ) :
if
i n d i v i d u a l == b e s t :
w o r l d . g e t f i t n e s s = np . min
e l i f i n d i v i d u a l == worst :
w o r l d . g e t f i t n e s s = np . max
e l i f i n d i v i d u a l == mean :
w o r l d . g e t f i t n e s s = np . mean
else :
a s s e r t F a l s e , E r r o r , i n d i v i d u a l %s
i s n o t known %i n d i v i d u a l
w o r l d . w r a p i d = a s p e c t s . w i t h w r a p ( m e a s u r e F i t n e s s , SSGA . updateWorst )
@step ( I run t h e a l g o r i t h m d u r i n g ( \ d+) i t e r a t i o n s )
d e f r u n i t e r a t i o n s ( s e l f , numevals ) :
numevals = i n t ( numevals )
world . f i t E v a l = [ ]
w o r l d . numevals = 0
w o r l d . s s g a . run ( maxeval=numevals )
@step ( t h e y were e v a l u a t e d ( \ d+) s o l u t i o n s )
def check eval ( s e l f , solutions ) :
a s s e r t w o r l d . numevals == i n t ( s o l u t i o n s )
@step ( i t s f i t n e s s i s a l w a y s b e t t e r )
def c h e c k f i t n e s s ( s e l f ) :
s i z e = l e n ( world . f i t E v a l )
f i t E v a l = world . f i t E v a l
for
e v a l i n xrange ( s i z e 1):
before = f l o a t ( fitEval [ eval ] )
a f t e r = f l o a t ( f i t E v a l [ e v a l +1])
a s s e r t a f t e r <= b e f o r e
a s p e c t s . w i t h o u t w r a p ( m e a s u r e F i t n e s s , w o r l d . s s g a . updateWorst )