Implementación de un SMA de negociación basado en subastas

Anuncio
Implementación de un SMA de negociación basado
en subastas electrónicas
Estudiante: Rodolfo de Benito Arango
Ingeniería en Informática
Consultor: David Isern Alarcón
Junio 2009
Agradecimientos
A mi hijo Carlos por aceptar que su padre siempre estuviera estudiando. A mi mujer Ana
por ayudarme a seguir, a pesar de las dificultades. A ambos por sacrificar tantos fines de
semana. A mis padres por su apoyo y ánimos. Al resto de mi familia por su comprensión.
A mi consultor David Isern Alarcón, por sus consejos, orientaciones y aliento.
A la Universitat Oberta de Catalunya por darme la oportunidad de completar mis estudios y
por su estupendo modelo de enseñanza-aprendizaje.
-2/106-
Índice de contenidos
Capítulo
1.
­
Introducción......................................................................................................... 6
1.1.
Justificación
del
PFC
y
contexto
en
el
que
se
desarrolla................................................... 6
1.2.
Objetivos
del
PFC ........................................................................................................................... 8
1.2.1.
Objetivos
generales
y
alcance.............................................................................................................. 8
1.2.2.
Objetivos
específicos .............................................................................................................................11
1.3.
Planificación
de
trabajo............................................................................................................ 12
1.3.1.
División
del
trabajo
en
tareas
y
estimación
de
tiempos ........................................................12
1.3.2.
Identificación
de
hitos ..........................................................................................................................14
1.3.3.
Planificación
temporal..........................................................................................................................15
Capítulo
2.
­
Especificación
de
requisitos ........................................................................ 17
2.1.
Conceptos
principales
del
sistema ....................................................................................... 17
2.1.1.
Tipos
de
subastas....................................................................................................................................17
2.1.2.
Agentes........................................................................................................................................................17
2.1.3.
Estrategias
de
negociación .................................................................................................................19
2.1.4.
Historial
de
transacciones ..................................................................................................................20
2.1.5.
Problemas
a
solventar
en
el
sistema ..............................................................................................20
2.2.
Diagrama
de
casos
de
uso........................................................................................................ 21
2.3.
Descripción
textual
de
casos
de
uso..................................................................................... 21
2.3.1.
Registrar
subasta ....................................................................................................................................22
2.3.2.
Determinar
ganador ..............................................................................................................................22
2.3.3.
Bajar
precio ...............................................................................................................................................22
2.3.4.
Crear
compra ............................................................................................................................................23
2.3.5.
Pujar .............................................................................................................................................................23
2.3.6.
Localizar
subasta ....................................................................................................................................23
Capítulo
3.
­
Especificación
del
SMA .................................................................................. 24
3.1.
Modelo
de
roles ........................................................................................................................... 24
3.2.
Modelo
de
entorno ..................................................................................................................... 26
3.3.
Modelo
de
tareas......................................................................................................................... 28
3.4.
Modelo
de
ontologías ................................................................................................................ 29
3.5.
Modelo
de
coordinación........................................................................................................... 30
3.5.1.
Negociación
subastador
inglesa
y
Comprador...........................................................................30
3.5.2.
Negociación
subastador
holandesa
y
Comprador ....................................................................30
3.5.3.
Suscripción
comprador
y
subastador ............................................................................................31
3.5.4.
Búsqueda
de
subastas.
Comprador
‐
Buscador
‐
Casa
de
subastas...................................32
Capítulo
4.
­
Implementación............................................................................................... 34
4.1.
Diagrama
de
clases .................................................................................................................... 34
4.2.
Implementación
de
los
agentes ............................................................................................. 35
4.3.
Comunicación
entre
agentes................................................................................................... 35
4.4.
Implementación
de
los
comportamientos
(behaviours) .............................................. 36
4.4.1.
Comportamientos
de
subastadores ................................................................................................36
4.4.2.
Comportamientos
de
compradores ................................................................................................37
4.4.3.
Comportamientos
que
inician
una
petición ................................................................................37
4.4.4.
Comportamientos
que
responden
a
una
petición ....................................................................38
4.5.
Implementación
de
las
estrategias....................................................................................... 38
4.5.1.
Interfaces
utilizados
en
las
estrategias .........................................................................................38
4.5.2.
Clases
que
implementan
el
interface
ICfgApuesta ...................................................................38
-3/106-
4.5.3.
Clases
que
implementan
el
interface
ICfgSubasta ....................................................................38
4.6.
Clases
de
información
manejada
en
la
subasta ................................................................ 38
4.7.
Estructura
de
paquetes............................................................................................................. 39
4.8.
Librerías
utilizadas .................................................................................................................... 40
4.9.
Distribución
final........................................................................................................................ 40
Capítulo
5.
­
Ejecución ............................................................................................................ 41
5.1.
Ejecución
del
SMA....................................................................................................................... 41
5.2.
Test
de
ejecución ........................................................................................................................ 41
5.2.1.
Muestra
de
flujo
de
mensajes
en
el
test
de
la
subasta
inglesa.............................................44
5.2.2.
Muestra
de
intercambio
de
mensajes
de
negociación
entre
subastador
y
compradores
en
el
test
de
la
subasta
inglesa .........................................................................................45
5.2.3.
Muestra
de
flujo
de
mensajes
en
el
test
de
la
subasta
holandesa ......................................46
5.2.4.
Muestra
de
intercambio
de
mensajes
de
negociación
entre
subastador
y
compradores
en
el
test
de
la
subasta
holandesa...................................................................................47
5.2.5.
Muestra
de
mensajes
entre
el
agente
Subastador,
el
agente
DF
y
el
agente
CasaSubastas.........................................................................................................................................................48
5.2.6.
Rondas
y
pujas
obtenidas
en
el
test
de
la
subasta
inglesa ....................................................49
5.2.7.
Rondas
y
pujas
obtenidas
en
el
test
de
la
subasta
holandesa .............................................49
5.3.
Sistema
de
logging...................................................................................................................... 50
Capítulo
6.
­
Conclusiones
y
propuestas
de
mejora ...................................................... 51
Anexo
A.
Clases
Java
implementadas ................................................................................ 55
Clase
AgenteBase ................................................................................................................................................55
Clase
AgenteCasaSubastas ..............................................................................................................................57
Clase
AgenteSubastador...................................................................................................................................64
Clase
AgenteBuscador.......................................................................................................................................67
Clase
AgenteComprador ..................................................................................................................................68
Clase
SubastadorBehaviour............................................................................................................................72
Clase
SubastadorHolandesaBehaviour......................................................................................................73
Clase
SubastadorInglesaBehaviour.............................................................................................................76
Clase
CompradorInglesaIncrementalBehaviour ...................................................................................79
Clase
CompradorHolandesaNRondasBehaviour...................................................................................82
Clase
CompradorHolandesaIncrementoDinamicoBehaviour .........................................................84
Clase
BuscadorBehaviourInitiator ..............................................................................................................87
Clase
CompradorSuscribirBehaviourInitiator .......................................................................................90
Clase
SubastadorTransaccionesBehaviourInitiator ............................................................................91
Clase
BuscadorBehaviourResponder.........................................................................................................92
Clase
CasaSubastasBusquedasBehaviourResponder..........................................................................93
Clase
SubastadorSuscribirBehaviourResponder ..................................................................................94
Clase
CasaSubastasTransaccionesBehaviourResponder...................................................................96
Clase
ICfgApuesta ..............................................................................................................................................97
Clase
ICfgSubasta ................................................................................................................................................98
Clase
IncrementalCfgImpl ...............................................................................................................................98
Clase
ApuestaUnicaNRondasCfgImpl.........................................................................................................99
Clase
ApuestaUnicaIncrementoDinamicoCfgImpl............................................................................. 101
Clase
SubastaHolandesaImpl...................................................................................................................... 103
Clase
SubastaInglesaImpl............................................................................................................................. 103
Clase
Subasta ..................................................................................................................................................... 104
Clase
Transacción ............................................................................................................................................ 106
-4/106-
Índice de figuras
Figura 1. Remote Agent Management de JADE.................................................................... 9
Figura 2. Sniffer de JADE mostrando el flujo de mensajes entre 3 agentes.......................... 9
Figura 3. Instrospector de JADE mostrando los mensajes recibidos por un agente y el
comportamiento que está ejecutando ........................................................................... 10
Figura 4. Log Manager de JADE ........................................................................................ 10
Figura 5. Diagrama de Gantt de las tareas del proyecto...................................................... 16
Figura 6. Diagrama de casos de uso .................................................................................... 21
Figura 7. Diagrama de modelo de roles ............................... ¡Error!Marcador no definido.
Figura 8. Diagrama de actividad subasta inglesa ................................................................ 28
Figura 9. Diagrama de actividad subasta holandesa............................................................ 28
Figura 10. Diagrama de conceptos ...................................................................................... 29
Figura 11. Diagrama de secuencia del protocolo de interacción de la subasta inglesa ...... 30
Figura 12. Diagrama de secuencia del protocolo de interacción de la subasta holandesa .. 31
Figura 13. Diagrama de secuencia del protocolo de suscripción mantenido entre Comprador
y Subastador ................................................................................................................. 31
Figura 14. Diagrama de secuencia del protocolo FIPA-Brokering ..................................... 32
Figura 15. Diagrama de secuencia del protocolo FIPA-Query que actúa como subprotocolo
en el proceso de búsqueda de una subasta.................................................................... 33
Figura 16. Diagrama de clases del SMA............................................................................. 34
Figura 17. FIPA Contract Net Interaction Protocol ............................................................ 37
Figura 18. Estructura de paquetes utilizada en el desarrollo del SMA ............................... 39
Figura 19. Intercambio de mensajes en subasta inglesa...................................................... 44
Figura 20. Intercambio de mensajes en subasta holandesa ................................................. 46
-5/106-
Capítulo 1. - Introducción
1.1. Justificación del PFC y contexto en el que se desarrolla
El proyecto pertenece al ámbito de la Inteligencia Artificial y, más concretamente, al
ámbito de los Sistemas Multiagente o SMA. Entendiendo como SMA [1]:
"Un conjunto de agentes autónomos inteligentes que se comunican para resolver un
problema de manera conjunta. Cuando los componentes de este tipo de sistemas quieren
cooperar en la resolución del problema, se habla de un conjunto de agentes
colaborativos.".
En cuanto a los agentes que integran un SMA, hay muchas definiciones al respecto. La
FIPA [2] (Foundation for Intelligent Physical Agents) los define de la siguiente manera:
"Un agente es una entidad de software encapsulado con su propio estado, conducta, hilo
de control y la habilidad para interactuar y comunicarse con otras entidades (gente, otros
agentes o sistemas legados)”.
Los agentes se definen como [3]:
“...hardware o (más usualmente) sistema de computación que posea las siguientes
propiedades:
- autonomía: opera sin intervención directa de los humanos u otros programas, y tiene
algún tipo de control sobre sus acciones o estado interno;
- habilidad social: interactúan con otros agentes a través de un lenguaje de comunicación;
- reactividad: perciben su entorno (mundo físico, usuario a través de interfaz gráfica,
agentes, Internet) y responden a cambios que ocurren en él;
- pro-actividad: exhiben comportamiento dirigido por objetivos, tomando la iniciativa.”
El campo de actuación de los SMA comprende, entre otros [4]:
•
Flujos de trabajo y gestión de procesos de negocio. Como por ejemplo el SMA
utilizado por SCA Packaging para explorar diferentes estrategias encaminadas a
reducir los niveles de stocks sin comprometer los tiempos de reparto, que consigue
reducir los niveles de stock en almacén un 35%.
•
Reputación y confianza. Aportan nuevas técnicas para expresar el razonamiento
sobre la reputación y la confianza a nivel individual y social para posibilitar la
interacción en entornos abiertos y dinámicos.
•
Creación y gestión de Organizaciones Virtuales en Grid computing. En lo que
se refiere la gestión y desarrollo de procedimientos y métodos para la
automatización de creación de Organizaciones Virtuales (VOs), gestión y
disolución.
-6/106-
•
Coordinación y reubicación de recursos. En la gestión autónoma y coordinada de
recursos distribuidos.
•
Negociación. Aportando estrategias y protocolos que establecen reglas de
negociación así como los propios mecanismos de negociación. Determinando qué
algoritmo de negociación es el más adecuado bajo determinadas circunstancias.
•
Aprendizaje y optimización. Aplicado por ejemplo al campo de la logística en
sistemas de optimización de transporte basados en coste, como es el caso de
Adaptive Transportation Networks cuyos agentes negocian utilizando un protocolo
similar al utilizado en las subastas.
•
Trazabilidad. Aportando mecanismos para la conocer la traza de cómo se ha
logrado alcanzar determinado resultado identificando los servicios que lo han
producido.
El presente proyecto se centra en el ámbito del comercio electrónico en la modalidad de
agentes de subasta (auction bots) [5]: "Agents that can run, and participate in, online
auctions for goods." Lo que se pretende es lograr es llevar a cabo todo el proceso de
negociación de las subastas sin intervención humana, por medio de sus agentes
representantes. De tal manera que un vendedor parametrice la subasta a realizar (tipo de
subasta, precio mínimo, tiempo de subasta, etc.) y genere un agente vendedor que lo
representará en la subasta. Por otra parte, los compradores generarán sus agentes
parametrizados acorde al objeto de la subasta y a la estrategia a seguir en la misma. A partir
de ahí se produce la interacción "automática" entre agentes compradores y vendedores de la
subasta, según sus modelos de comportamiento y estrategias de negociación, hasta el
momento en que ésta concluya. Al finalizar, los agentes tanto compradores como
vendedores informarán de los resultados e iniciarán los procesos necesarios tras la
adjudicación del producto de la subasta, en caso de que esta adjudicación se produzca.
En cuanto a los modelos de subasta, los contemplados en el sistema corresponden a la
tipología de subastas abiertas y más concretamente a las subastas al alza (inglesa) y las
subastas a la baja (holandesa). En el Capítulo 2 se explican en que consisten cada una de
ellas.
En este campo de los sistemas multiagente de subastas existen bastantes estudios sobre todo
en el contexto de la subasta doble continua o CDA y se han utilizado algunos de ellos [6, 7,
8] como fuente para obtener información sobre las estrategias de negociación de los agentes
"tipo".
En cuanto a la justificación del proyecto, en gran parte se debe al interés del estudiante de
obtener una visión práctica del funcionamiento de los SMA y adquirir una experiencia
básica en la implementación de estos sistemas utilizando Java.
-7/106-
1.2. Objetivos del PFC
1.2.1.
Objetivos
generales
y
alcance
El objetivo general del proyecto es adquirir una experiencia en el modelado e
implementación de sistemas multiagente (SMA) de negociación. Más concretamente, la
negociación se realizará en un entorno de subastas electrónica.
En un principio, el modelado de la especificación se pensó realizarla con IDK [9]
(INGENIAS Development Kit) pero se descartó debido fundamentalmente a problemas de
tiempo para hacer una especificación tan detallada como exige el IDK, hecho ya previsto
por el consultor del proyecto. Motivo por el cual se buscó una metodología menos exigente
pero que a la vez reflejara claramente los requisitos y modelara el SMA a alto nivel. La
metodología que más se adapta a estas necesidades está definida en el artículo "Una
Aproximación Metodológica para la Construcción de Modelos de simulación Basados en el
Paradigma Multi-Agente" [10] y, en líneas generales, ha sido la que se ha seguido en este
proyecto.
El entorno de desarrollo del proyecto se realizará en Eclipse y la ejecución del SMA se
llevará a cabo con JADE [11,12] (Java Agent Development Framework) un entorno de
desarrollo y ejecución de agentes basado en Java, que cumple la especificación FIPA, y que
simplifica la implementación de aplicaciones distribuidas. JADE proporciona:
•
Un API Java para desarrollar los agentes.
•
Un contenedor o entorno de ejecución en el que "viven" los agentes (similar al
concepto de contenedor EJB en J2EE).
•
Un conjunto de herramientas gráficas gestión y depuración de agentes, entre los que
se encuentran:
o RMA o Remote Agent Management. Desde él se pueden iniciar el resto de
herramientas gráficas y gestionar los agentes.
-8/106-
Figura 1. Remote Agent Management de JADE
o Snnifer para capturar el flujo de mensajes entre los agentes.
Figura 2. Sniffer de JADE mostrando el flujo de mensajes entre 3 agentes
-9/106-
o Instrospector para acceder a la cola de mensajes enviados y recibidos por un
agente y a los comportamientos que está ejecutando.
Figura 3. Instrospector de JADE mostrando los mensajes recibidos por un agente y el comportamiento que
está ejecutando
o JADE Log Manager para ver los logs que se producen en la ejecución del
SMA.
Figura 4. Log Manager de JADE
-10/106-
El alcance del proyecto se centra en la capa de negocio y no incluye un entorno gráfico
para el interfaz del usuario ni persistencia de datos. Como futura mejora del proyecto se
podría realizar un interfaz del usuario Web y utilizar una solución de persistencia como por
ejemplo Hibernate [13] o iBatis [14]. De tal manera que combinara J2EE con el entorno de
ejecución de JADE.
1.2.2.
Objetivos
específicos
Los objetivos específicos del proyecto consisten en:
•
Modelar la especificación de un SMA utilizando la metodología definida en "Una
Aproximación Metodológica para la Construcción de Modelos de simulación
Basados en el Paradigma Multi-Agente" [15]
•
Utilizar JADE como entorno de ejecución y comunicación de un SMA.
•
Implementar las clases de test que comprueben el funcionamiento de los agentes y
del SMA.
•
Implementar las clases de los agentes y de sus comportamientos con el fin de lograr
un SMA de subastas virtuales con agentes compradores y vendedores capaces de
negociar en base a diferentes estrategias.
-11/106-
1.3. Planificación de trabajo
1.3.1.
División
del
trabajo
en
tareas
y
estimación
de
tiempos
Se ha optado por una división Top-Down de las tareas necesarias para satisfacer los
objetivos señalados anteriormente. En la Tabla 1.1 se recogen la división de estructuras del
trabajo y sus duraciones estimadas.
T01
Definición
del
plan
de
trabajo
5
días
Elaboración
del
plan
de
trabajo
del
proyecto
T01.1
Recogida
de
documentación
básica
Obtención
de
documentación
necesaria
para
2
días
iniciar
el
estudio
del
proyecto.
Fuente
principal
Internet
T01.2
Propósito
del
proyecto
1
día
Propósito
y
definición
del
proyecto
T01.3
Objetivos
Definición
de
los
objetivos
generales
y
1
día
específicos
T01.4
Planificación
Descomposición
del
trabajo
en
tareas
siguiendo
1
día
una
metodología
WBS
y
planificación
temporal
de
las
mismas.
T02
Documentación
de
requisitos
del
SMA
7
días
Especificar
los
requisitos
del
SMA
modelando
los
casos
de
uso
en
un
diagrama
general
y
obteniendo
una
descripción
textual
de
los
casos
de
uso,
con
el
propósito
de
identificar
qué
debe
hacer
el
sistema,
cómo
y
cuándo.
Así
como
una
introducción
de
los
conceptos
principales
del
sistema.
T02.1
Conceptos
principales
del
sistema
Protocolos
de
subastas,
agentes,
estrategias
de
2
días
negociación,
el
historial
de
transacciones
y
previsión
de
problemas
a
solventa
en
el
sistema.
T02.2
Diagrama
de
casos
de
uso
Diagrama
general
de
casos
de
uso
que
servirá
de
1
días
base
para
identificar
los
requisitos
funcionales
del
sistema.
T02.3
Descripción
textual
de
casos
de
uso
4
días
Descripción
textual
de
los
casos
de
uso
identificados
en
el
diagrama
de
casos
de
uso.
Servirán
para
identificar
los
agentes
del
sistema,
sus
tareas
y
la
interacción
entre
ellos.
27
T03
Especificación
del
SMA
días
Una
vez
conocidos
los
requisitos
del
sistema
realizará
una
especificación
del
SMA
basándose
en
la
Metodología
descrita
en
el
Apartado
1.2.1.
T03.1
Modelo
de
roles
Identifica
los
roles
o
papeles
de
los
agentes
5
días
tomando
como
base
el
diagrama
de
casos
de
uso.
T03.2
Modelo
de
entorno
Describe
aquellos
componentes
del
sistema
que
5
días
no
son
agentes
pero
que
intervienen
de
una
u
otra
forma
en
los
procesos
que
llevan
a
cabo
los
agentes.
-12/106-
T03.3
Modelo
de
tareas
T03.4
Modelo
de
razonamiento
y
aprendizaje
T03.5
Modelo
de
ontología
T03.6
Modelo
de
coordinación
T04
Detalla
el
funcionamiento
de
cada
rol
mediante
la
descomposición
de
las
tareas
en
secuencias
de
actividades
y
su
representación
en
un
diagrama
de
actividad.
Engloba
las
creencias,
objetivos,
capacidades
y
decisiones
de
cada
rol
y
las
relaciona
con
las
actividades
que
debe
efectuar.
Se
representa
gráficamente
mediante
diagramas
de
flujo.
Representar
los
conceptos
de
la
ontología
(estructura
y
significado
de
los
conceptos
principales
del
sistema)
y
sus
relaciones
mediante
un
diagrama
de
clases
UML.
Utiliza
los
diagramas
de
secuencias
UML
para
representar
las
interacciones
entre
los
roles
y
las
etapas
que
las
componen.
Implementación
SMA
4
días
9
días
2
días
2
días
34
días
Implementación
en
JADE
del
SMA
según
las
especificaciones
de
la
tarea
T03.
T04.1
Crear
despliegue
Definir
la
configuración
de
despliegue
que
será
utilizada
para
lanzar
los
agentes.
Crear
las
clases
necesarias
para
el
funcionamiento
del
SMA.
Integrar
el
código
IDK
con
las
clases
de
la
tarea
T04
y
refinar
el
código
para
que
funcione
correctamente.
T04.2
Implementar
clases
del
SMA
T04.3
Refinar
el
código.
T05
Redacción
memoria
del
proyecto
Redacción
de
la
memoria
del
proyecto
T05.1
Documentar
requisitos
SMA
Redactar
los
requisitos
del
SMA
en
base
al
trabajo
obtenido
en
la
tarea
T02.
T05.2
Documentar
especificación
SMA
Redactar
la
especificación
del
SMA
en
base
al
trabajo
obtenido
en
la
tarea
T03.
T05.3
Documentar
implementación
del
SMA
Redactar
la
implementación
del
SMA
en
base
al
trabajo
obtenido
en
la
tarea
T04.
T05.4
Conclusiones,
mejoras,
referencias
y
Completar
la
memoria
añadiendo
las
bibliografía
conclusiones,
las
mejoras
posibles,
las
referencias
y
la
bibliografía.
T05.5
Revisiones
Realizar
las
modificaciones
necesarias
en
la
memoria
en
base
a
las
indicaciones
del
consultor.
-13/106-
3
días
25
días
6
días
31
días
5
días
7
días
7
días
7
días
5
días
20
T06
Test
días
Elaboración
de
los
juegos
de
pruebas
necesarios
para
probar
el
correcto
funcionamientos
de
los
agentes
y
del
SMA
implementado.
T06.1
Test
de
agentes
10
Crear
un
juego
de
pruebas
que
verifique
el
días
funcionamiento
de
los
agentes
tipo
que
intervienen
en
el
SMA.
T06.2
Test
SMA
10
Crear
un
juego
de
pruebas
que
verifique
el
días
funcionamiento
del
SMA.
10
T07
Elaborar
presentación
virtual
días
Elaboración
de
una
presentación
PowerPoint
que
sintetice
y
exponga
el
trabajo
realizado
en
el
proyecto.
20
T08
Revisiones
días
Revisiones
finales
del
SMA
obtenido,
de
la
memoria
y
de
la
presentación.
Tabla 1.1. División del trabajo y duración estimada.
1.3.2.
Identificación
de
hitos
•
PEC 1: entrega Planificación en fecha 8/3/2009.
•
PEC 2: entrega Requisitos y Especificación del SMA en fecha 12/4/2009.
•
PEC 3: entrega Implementación del SMA en fecha 17/5/2009.
•
Entrega final: implementación del SMA, memoria y presentación en fecha
19/6/2009.
-14/106-
1.3.3.
Planificación
temporal
En la Tabla 1.2 se muestra la planificación temporal de las tareas con su duración, fechas de
comienzo y fechas de fin. En la Figura 1 se muestra el diagrama de Gantt correspondiente a
la planificación.
Tabla 1.2. Planificación temporal tareas.
-15/106-
Figura 5. Diagrama de Gantt de las tareas del proyecto.
-16/106-
Capítulo 2. - Especificación de requisitos
En este Capítulo se introducen los conceptos principales del núcleo central del SMA y se
especifican los requisitos del SMA modelando los casos de uso en un diagrama general y
realizando una descripción textual de los casos de uso más relevantes, con el propósito de
identificar las funcionalidades principales del sistema y sus actores.
Originalmente, el proyecto no consideraba más agentes que los que directamente
intervienen en los procesos de negociación de las subastas, es decir, Agente Subastador y
Agente Comprador. Tras la lectura de "A Trustworthy Agent Based Online Auction System"
[15] se vio la necesidad de incorporar un agente Casa de subastas y agente Buscador, más
adelante se detalla el rol de cada uno de ellos, además de adoptarse un diseño similar para
conseguir que el sistema sea abierto a la extensión en cuanto a estrategias de compra se
refiere.
2.1. Conceptos principales del sistema
2.1.1.
Tipos
de
subastas
Los tipos de subasta que podrá elegir el vendedor corresponden a la tipología de subastas
abiertas y más concretamente a las siguientes [16,17]:
•
Subasta al alza. Pretende fomentar la competencia de los posibles compradores de
tal modo que el vendedor establece un precio de salida bajo. Este precio se va
incrementando con las sucesivas pujas de modo que se adjudica el objeto de la
subasta al participante que haya realizado la puja más alta durante el tiempo de vida
de la subasta. El vendedor puede fijar un precio mínimo de tal modo que si al
finalizar la subasta la puja máxima no es mayor o igual que el precio mínimo
entonces no se producirá la venta o adjudicación. Es la subasta clásica, también
conocida como subasta inglesa.
•
Subasta a la baja. El vendedor fija un precio de salida alto y sucesivamente lo
baja hasta que aparece un comprador que acepta el precio momento en el cual se le
adjudica el objeto de la subasta. Normalmente el vendedor fija un precio de reserva
de tal modo que ese precio será el mínimo al que puede llegar el objeto subastado.
También se conoce como subasta holandesa.
Nota: en un principio se consideraron las subastas a segundo precio o Vickrey pero se
descartaron para no aumentar la complejidad del proyecto.
2.1.2.
Agentes
En la concepción inicial de este proyecto se consideraron dos agentes con los roles de
vendedor o subastador y de comprador. A medida que el proyecto evoluciona se ve la
necesidad de crear nuevos tipos de agentes como es el caso de un agente Casa de subastas
que registra las subastas activas y los movimientos del historial de transacciones, entre otras
cosas, así como de un agente Buscador que localice las subastas activas que subasten un
bien determinado de interés para el usuario.
-17/106-
El sistema trabajará con los tipos de agentes siguiente:
•
Agente casa de subastas. Puesto en funcionamiento por el sistema, tiene las
responsabilidades siguientes:
o Mantener la lista de subastas activas y de bienes subastados.
o Crear la subastas y el agente subastador cuando se da de alta una nueva en el
sistema.
o Obtener la lista de subastas activa.
o Obtener la lista de bienes que se subastan. Para acotar el problema se
considera que no puede haber dos subastas activas que subasten el mismo
bien.
o Cerrar la subasta cuando concluye.
o Responder al agente buscador sobre la búsqueda de una subasta concreta.
o Registrar en el historial las transacciones que se produzcan a consecuencia
de la interacción entre agentes compradores y vendedores.
o Realizar los test de funcionamiento del SMA de subastas.
•
Agente subastador. Son puestos en funcionamiento por el agente Casa de subastas
y configurados previamente con:
o El artículo a vender.
o El tipo de subasta a realizar: inglesa, holandesa.
o El precio de salida.
o El precio de reserva.
o La fecha de finalización de la subasta.
Una vez liberado en el sistema, el agente comprador hará las gestiones necesarias
para responder a los mensajes de los compradores, notificar los cambios de precios
a los agentes involucrados en la subasta, reducir los precios en caso de la subasta
holandesa, determinar el ganador, notificar el ganador y notificar la finalización de
la subasta al agente Casa de subastas.
•
Agente buscador. Actúa de intermediario entre el usuario el agente Casa de
subastas para localizar las subastas activas que subasten un bien por el que el
usuario está dispuesto a pujar.
•
Agente comprador. Puesto en funcionamiento por el agente Casa de subastas y
configurado con:
o El artículo que se pretende comprar.
o La puja a realizar.
o El precio de reserva (la puja máxima a la puede llegar el agente).
o La estrategia a seguir (se detallan en el apartado Estrategias de negociación)
-18/106-
El agente comprador está vinculado a la subasta establecida en su configuración
inicial y se mantendrá en la misma realizando las pujas que considere el agente en
base a sus estrategias de negociación y al tipo de subasta.
2.1.3.
Estrategias
de
negociación
Las estrategias de negociación [6] determinarán el comportamiento de los agentes en la
subasta y serán parametrizadas al crear el agente aunque podrían modificarse
dinámicamente según el conocimiento del entorno, lo que permitiría, por ejemplo, que en la
subasta inglesa no todos los compradores pujen de la misma forma. Las estrategias
seguidas por los agentes y los resultados a los que llevan éstas podrán contrastarse ya que el
sistema guardará un historial de transacciones de las subastas.
En general, la estrategia del pujador determinará cuánto debe pujar y cuándo hacerlo. Para
ello, el sistema contemplará las estrategias siguientes:
•
Incremental. Estrategia del comprador de la subasta inglesa en la que el agente
puja a intervalos regulares incrementando la puja en una cantidad preestablecida al
crear el agente. Se puede optar por una de estas dos formas de incrementar la puja:
o Nueva puja = puja anterior + incremento.
o Nueva puja = puja anterior * incremento.
•
Apuesta única n rondas. Estrategia del comprador de la subasta holandesa en la
que al principio el agente considera pujar en la subasta por el precio configurado en
su atributo Puja. Si en el transcurso de la subasta se supera el número de rondas
configurado en la estrategia entonces el valor de aceptación de la puja será el de su
precio de reserva.
•
Apuesta única n rondas incremento dinámico. Estrategia del comprador de la
subasta holandesa en la que en principio el agente considera pujar en la subasta por
el precio configurado en su atributo Puja. Si se supera el número de rondas
preestablecido en la estrategia entonces incrementará el valor de aceptación de la
puja en una cantidad fija siempre y cuando no llegue al precio de reserva.
Por otra parte, se pretende que el SMA a implementar pertenezca abierto a la extensión en
el sentido de que sea sencillo implementar nuevas estrategias y configurarlas para que sean
utilizadas por los agentes compradores. Por ejemplo, para que en lugar de ser estrategias
estáticas, como las comentadas anteriormente, sean dinámicas y reactivas al
comportamiento de otros pujadores o al historial de transacciones. Además, en la subasta
holandesa podría resultar interesante incluir adaptaciones de estrategias propias de agentes
de subastas dobles continuas [7, 8] como por ejemplo la de los Agentes Kaplan, Agentes
Zero-Intelligente Plus (ZIP) o Agentes GD.
-19/106-
2.1.4.
Historial
de
transacciones
El sistema guardará un registro de las transacciones que tienen lugar en las subastas,
almacenando información referente al identificador de la subasta, identificador del agente
que realizó la transacción, el tipo de transacción, el precio (de puja o de venta) y la fecha.
El propósito de este historial es doble, por una parte puede utilizarse como fuente de datos
para realizar un estudio sobre el comportamiento de los tipos de agentes en las subastas. Por
otra parte puede utilizarse como base de conocimiento para que los agentes compradores y
vendedores puedan adaptar su estrategia de negociación.
2.1.5.
Problemas
a
solventar
en
el
sistema
En una valoración previa de las cuestiones que deben resolverse en la implementación de
este SMA de subastas se pueden identificar los siguientes:
•
El sistema de suscripciones a las subastas y notificaciones de cambios de
precios. Puede solventarse empleando el patrón Observador, de modo que los
compradores se suscriben a las subastas de los vendedores y estos podrán notificar
eventos de la subasta a todos sus subscriptores.
•
Pujas simultáneas en la subasta inglesa. Se produce cuando más de un comprador
realiza una puja simultáneamente. Puede tomarse como un problema de
concurrencia de productor-consumidor, siendo el productor el vendedor y el
consumidor el comprador. Se solventa utilizando una cola thread safe para procesar
los mensajes de puja que reciba el vendedor, aunque esta funcionalidad ya está
incorporada en el propio JADE y por tanto no es necesario implementarla de el
sistema.
•
Colisiones en ofertas realizadas por los compradores en la subasta holandesa.
Se produce cuando más de un comprador oferta el mismo precio. Se puede resolver
con el mismo sistema que el caso de las pujas simultaneas en la subasta inglesa.
Otra solución que puede adoptarse es utilizar un contador de colisiones, establecer
un máximo de colisiones permitidas y repetir la subasta hasta que el contador llegue
al máximo en cuyo caso se daría como ganador aleatoriamente a una de las pujas
ganadoras.
-20/106-
2.2. Diagrama de casos de uso
En la Figura 6. Diagrama de casos de uso, se identifica el actor Agente CasaDesSubastas
que se encarga de poner en marcha los casos de uso Revistar subasta y Crear compra que
desencadenan todo el proceso de una subasta. También figuran los agentes Comprador y
Subastador y una especialización de este último, el Agente Subastador holandesa que pone
en marcha el caso de uso bajar precio (caso particular de este tipo de subastas). Así como el
agente Buscador encargado de localizar una subasta en base a un criterio.
Figura 6. Diagrama de casos de uso
2.3. Descripción textual de casos de uso
En la descripción textual siguiente solo se tendrán en cuenta los casos de uso que no están
incluidos en otros puesto que su descripción textual no aporta nada a la documentación de
requisitos aunque es importante que figuren en el diagrama de casos de uso para ofrecer
una visión de las implicaciones de los casos de uso "principales" (puestos en marcha
directamente por un actor).
-21/106-
2.3.1.
Registrar
subasta
Caso de uso
Actores
Precondición
Poscondición
Descripción
Registrar subasta
Agente CasaDeSubastas
La subasta no está registrada en el sistema
La subasta está registrada en el sistema y hay un agente subastador encargado de la
venta objeto de la subasta.
1. El Agente CasaDeSubastas crea un Agente Subastador encargado de la subasta.
2. Registra el bien subastado en la lista de bienes subastados.
3. Registra la subasta en la lista de subastas activas:
• El identificador de la subasta
• La fecha de inicio de la subasta
• El identificador del agente subastador
• El objeto a subastar
• El tipo de subasta a realizar: inglesa, holandesa.
• El precio de salida
• El precio de venta de reserva
Flujo alternativo
2.3.2.
Determinar
ganador
Caso de uso
Actores
Precondición
Poscondición
Descripción
Determinar ganador
Agente Subastador
Hay un Agente Subastador encargado de la subasta y, o bien, la subasta es inglesa y ha
finalizado, o bien, la subasta es holandesa y hay uno o más compradores que ofertan el
precio establecido por el Agente Subastador.
La subasta cierra
1. El Agente Subastador comprueba que la puja actual es la ganadora.
2. El Agente Subastador notifica al Agente CasaDeSubastas y a los agentes
compradores del resultado de la subasta.
3. El Agente Subastador da por cerrada la subasta y se lo notifica a al Agente
CasaDeSubastas.
Flujo alternativo
2.3.3.
Bajar
precio
Caso de uso
Actores
Precondición
Poscondición
Descripción
Bajar precio
Agente Subastador
El tipo de subasta es holandesa y no ha finalizado
El precio del bien subastado se ha reducido
1. El Agente Subastador determina en base a su estrategia que es necesario bajar el
precio.
2. Calcula el nuevo precio de la subasta.
3. Notifica el nuevo precio al Agente CasaDeSubastas y a los agentes vendedores
suscritos en la subasta.
Flujo alternativo
-22/106-
2.3.4.
Crear
compra
Caso de uso
Actores
Precondición
Poscondición
Descripción
Crear compra
Agente CasaDeSubastas
Hay una subasta en curso de interés para el comprador
Se crea un agente comprador suscrito a la subasta
1. Crea un agente Comprador asignándole una estrategia parametrizada de la forma
siguiente.
Para la subasta inglesa:
• La forma de incrementar la puja.
• El incremento.
• La puja inicial
• La puja máxima o reserva.
Para la subasta Holandesa:
• El incremento
• El precio aceptable inicial
• El precio aceptable máximo o reserva.
• El número de ronda máximo para incrementar el precio aceptable
2. Le asigna una subasta concreta.
Flujo alternativo
2.3.5.
Pujar
Caso de uso
Actores
Precondición
Poscondición
Descripción
Flujo alternativo
Pujar
Agente comprador
El agente Comprador está suscrito a una subasta.
Una nueva puja del agente comprador es notificada al Agente Subastador
1. El agente comprador determina realizar una puja y el importe de la misma según la
estrategia seguida por el agente Comprador.
2. El agente Comprador envía un mensaje al Agente Subastador notificando la puja.
3. El Agente Subastador procesa la puja.
4. El Agente Subastador verifica que la puja es correcta y la notifica al Agente
CasaDeSubastas y al resto de compradores.
4a. Si la subasta ha finalizado entonces caso de uso Determinar ganador.
2.3.6.
Localizar
subasta
Caso de uso
Actores
Precondición
Poscondición
Descripción
Localizar subasta
Agente Buscador
1. El usuario indica el objeto de subasta que le interesa localizar.
2. El agente Buscador envía un mensaje al Agente CasaDeSubastas con la búsqueda a
realizar.
3. El Agente CasaDeSubastas envía un mensaje al Agente Buscador con el resultado de
la búsqueda.
4. El Agente Buscador informa textualmente al usuario del resultado de la búsqueda.
Flujo alternativo
-23/106-
Capítulo 3. - Especificación del SMA
3.1. Modelo de roles
En este modelo se identificación los roles o papeles de los agentes tomando como base el
diagrama de casos de uso.
En la Figura 7, se pueden ver los roles de los agentes contemplados en el sistema. El agente
CasaDeSubastas está relacionado con 0 o más agentes Subastadores Cada agente
Comprador dispone de un agente Buscador el cual solicita al agente CasaDeSubastas la
lista de subastas actuales o aquellas en las que se subasta un bien determinado. La relación
de uso entre Agente Subastador y Agente Comprador representa la negociación entre
ambos que se produce en la subasta. También se puede ver la relación de especialización
del agente Subastador Holandesa respecto al agente Subastador.
Complementando al diagrama anterior, se describe a alto nivel y en formato tabular el papel
que desempeña cada tipo de agente en cuanto a sus objetivos, responsabilidades principales,
capacidades e información que requiere para cumplir sus objetivos.
Rol
Agente Buscador
Objetivos
Localizar las subastas activas según criterio de búsqueda
Responsabilidades
Capacidades
Enviar mensajes de búsqueda de subastas al Agente CasaDeSubastas
Notificar las subastas encontradas al usuario
Buscar subastas
Información requerida
•
El "objeto" o bien que quiere localizarse en subasta
-24/106-
Rol
Agente CasaDeSubastas
Objetivos
Llevar un control de todas las subastas del sistema
Responsabilidades
• Crear los agentes subastadores
• Crear los agentes compradores
• Registrar las subastas en el sistema
• Notificar la subasta activa de un bien determinado
• Eliminar al agente subastador cuando concluya una subasta
• Actualizar el Historial de transacciones
Creación de agentes y gestión de las subastas
Capacidades
Información requerida
•
•
•
•
Rol
Agente Subastador
Objetivos
Vender el objeto de la subasta con el mayor beneficio posible respetando el
precio de reserva.
• Determinar el ganador.
• Notificar ganador.
• Notificar nueva oferta a los suscriptores (subasta inglesa)
Vender un producto mediante subasta electrónica.
Responsabilidades
Capacidades
Los parámetros de configuración de la subasta.
Los parámetros de configuración de los agentes compradores
Los parámetros de configuración de los agentes subastadores
Las datos de la transacción a registrar.
Información requerida
•
•
Rol
Agente Subastador Holandesa
Objetivos
Vender el objeto de la subasta con el mayor beneficio posible respetando el
precio de reserva
Las mismas que las del Agente Subastador y además la estrategia a seguir a la
hora de determinar:
• Cuando ofertar el objeto de la subasta a un precio más reducido.
• La disminución de precio.
Vender un producto mediante subasta electrónica.
• Los parámetros de configuración de la subasta (igual que en Agente
Subastador)
• Las ofertas de compra (pujas) de los vendedores.
Responsabilidades
Capacidades
Información requerida
Los parámetros de configuración de la subasta.
Las ofertas de compra (pujas) de los vendedores.
Rol
Agente Comprador
Objetivos
Comprar el objeto de la subasta al menor precio posible sin superar el precio de
reserva.
Efectuar las pujas según el tipo de subasta y la estrategia elegida por el
comprador.
Comprar productos en una subasta electrónica.
Responsabilidades
Capacidades
Información requerida
•
•
•
•
Los parámetros de configuración del agente.
El tipo de subasta.
El precio de venta actual.
La estrategia a seguir
-25/106-
3.2. Modelo de entorno
El modelo del entorno describe aquellos componentes del sistema que no son agentes pero
que intervienen de una u otra forma en los procesos que llevan a cabo los agentes. Se puede
entender como la relación a nivel de flujo de información que se produce entre los agentes
y el entorno, identificando las entradas de datos, procesos que se llevan a cabo y las salidas
generadas.
Componente
Entradas
Dato
•
•
•
•
•
Precio de compra aceptable (subasta holandesa)
Emisor(es)
El número de rondas actuales de la subasta
El número de rondas máximo para el
comprador
El precio de compra aceptable actual
El precio de compra de reserva
El incremento de precio de compra por
ronda
•
•
Comprador
Subastador
Procesos
En las subastas holandesas el comprador recalculará el precio de compra aceptable según su estrategia.
Para la estrategia Apuesta única n rondas:
SI numero rondas actual >= número de rondas máximo para el comprador ENTONCES
Precio de compra aceptable=Precio de compra de reserva
FIN SI
Para la estrategia Apuesta única incremento dinámico:
SI numero rondas actual >= número de rondas máximo para el comprador ENTONCES
SI precio de compra aceptable + incremento > precio de compra de reserva ENTONCES
No se modifica el precio de compra aceptable
SI NO
Precio de compra aceptable=precio de compra aceptable anterior + incremento
FIN SI
FIN SI
Salidas
Dato
Receptor(es)
El precio de compra aceptable
Comprador
-26/106-
Componente
Entradas
Dato
•
•
•
•
Oferta de compra subasta inglesa
Emisor(es)
La puja actual
El precio de reserva
El incremento
La forma de incrementar la puja
•
•
Comprador
Subastador
Procesos
En la subasta inglesa el comprador determinará si puja o no en una ronda y el valor de la puja en base a su
estrategia.
Para la estrategia incremental:
MIENTRAS (puja<puja actual)
SI (tipo de incremento es sumar) ENTONCES
puja = puja + incremento
SI NO
puja = puja * incremento
FIN SI
FIN MIENTRAS
Salidas
Dato
Receptor(es)
La puja de un comprador en una ronda de una
subasta
Comprador
Subastador
Componente
Entradas
Dato
Emisor(es)
•
•
•
Oferta de venta subasta holandesa
El precio de venta actual
El precio de venta de reserva
El decremento
•
Subastador
Procesos
En la subasta holandesa el subastador determinará el nuevo precio de venta ofertado si no hay ofertas de
compra en una ronda.
nuevo precio de venta = precio de venta actual - decremento
SI (nuevo precio de venta>=precio de venta de reserva) ENTONCES
precio de venta actual = nuevo precio de venta
SI NO
terminar subasta
FIN SI
Salidas
Dato
Receptor(es)
La oferta de venta del subastador holandesa
Subastador
-27/106-
3.3. Modelo de tareas
Detalle del funcionamiento de cada rol mediante la descomposición de las tareas en
secuencias de actividades y su representación en un diagrama de actividad.
En este modelo se contemplan los diagramas siguientes:
Figura 7. Diagrama de actividad subasta inglesa
Figura 8. Diagrama de actividad subasta holandesa
-28/106-
3.4. Modelo de ontologías
El modelo emplea como representación gráfica un diagrama muy similar al diagrama de
clases de UML para representar los conceptos de la ontología (estructura y significado de
los conceptos principales del sistema) y sus relaciones.
Figura 9. Diagrama de conceptos
-29/106-
3.5. Modelo de coordinación
Este modelo utiliza los diagramas de secuencias UML para representar las interacciones
entre los roles y las etapas que las componen. En estos diagramas se muestra el flujo de
mensajes, y el tipo de los mismos, entre los roles.
3.5.1.
Negociación
subastador
inglesa
y
Comprador
El proceso de negociación de la subasta inglesa entre subastador y comprador se coordina
según protocolo de interacción FIPA English Auction Interaction Protocol [18] donde
Initiator corresponde al rol de Subastador y Participant al rol de Comprador.
Figura 10. Diagrama de secuencia del protocolo de interacción de la subasta inglesa
3.5.2.
Negociación
subastador
holandesa
y
Comprador
El proceso de negociación de la subasta holandesa entre subastador y comprador se
coordina según protocolo de interacción FIPA Dutch Auction Interaction Protocol [19]
donde Initiator corresponde al rol de Subastador y Participant al rol de Comprador.
-30/106-
Figura 11. Diagrama de secuencia del protocolo de interacción de la subasta holandesa
3.5.3.
Suscripción
comprador
y
subastador
El proceso de suscripción a una subasta por parte del comprador se coordina según
protocolo de interacción FIPA Subscribe Interaction Protocol [20] donde Initiator
corresponde al rol de Comprador y Participant al rol de Subastador.
Figura 12. Diagrama de secuencia del protocolo de suscripción mantenido entre Comprador y Subastador
-31/106-
3.5.4.
Búsqueda
de
subastas.
Comprador
‐
Buscador
‐
Casa
de
subastas
El proceso de búsqueda de una subasta por parte del comprador utilizando los servicios de
un agente buscador que consulta al agente Casa de subastas se coordina según protocolo de
interacción FIPA Brokering Interaction Protocol [21] donde Initiator corresponde al rol de
Comprador y Broker al rol de Buscador.
Figura 13. Diagrama de secuencia del protocolo FIPA-Brokering
El subprotocolo utilizado para interrogar al agente Casa de subastas es el FIPA Query
Interaction Protocol [22], donde Initiator es el agente Buscador y Participant es el agente
Casa de subastas.
-32/106-
Figura 14. Diagrama de secuencia del protocolo FIPA-Query que actúa como subprotocolo en el proceso de
búsqueda de una subasta
-33/106-
Capítulo 4. - Implementación
La implementación del SMA se ha realizado en un ordenador con sistema operativo Mac
OS X versión 10.5 y el entorno de desarrollo utilizado ha sido Eclipse 3.3.2.
4.1. Diagrama de clases
Las clases necesarias para implementar el SMA de subastas son las que se muestran en la
figura siguiente. Todas ellas incluyen comentarios tipo JavaDoc así como comentarios de
línea. En el Anexo 1 se muestra el código Java de todas las clases utilizadas.
Figura 15. Diagrama de clases del SMA
4.2. Implementación de los agentes
Los agentes del sistema extienden una clase base llamada AgenteBase que implementa
métodos de uso común para los agentes y que a su vez extiende la clase jade.core.Agent.
Concretamente un método para registrar al agente en las "páginas amarillas" (DF Services)
de modo que sea fácilmente localizable y otro método para quitarlo de dicho registro.
Los agentes que extienden AgenteBase son:
•
•
•
•
AgenteBuscador
AgenteCasaSubastas
AgenteComprador
AgenteSubastador
Los mencionados agentes implementan el rol especificado en el punto 3.1. Modelo de roles.
4.3. Comunicación entre agentes
La comunicación entre los agentes se realizará acorde al Lenguaje de Comunicación de
Agentes (ACL) recogido en el protocolo FIPA-ACL [23].
Un mensaje FIPA-ACL, además de los datos de emisor (sender), receptor (receiver),
protocolo (protocol) y otros datos de cabecera, adjunta el tipo de acción comunicativa
según se puede ver en la tabla adjunta [24].
Acción
comunicativa
(Performative)
Significado
accept‐proposal
Aceptar
una
propuesta
recibida
previamente
agree
Estar
de
acuerdo
en
realizar
alguna
acción
cancel
Cancelar
alguna
acción
pedida
previamente
cfp
Solicitar
propuestas
para
realizar
una
acción
dada
confirm
Informar
a
un
receptor
que
una
proposición
es
cierta
disconfirm
Informar
a
un
receptor
que
una
proposición
es
falsa
failure
Informar
a
otro
agente
que
se
intentó
una
acción
pero
falló
inform
Informar
a
un
receptor
que
una
proposición
es
cierta
inform‐if
Si
el
agente
que
recibe
la
acción
cree
que
la
sentencia
es
verdadera
informará
de
manera
afirmativa,
sino
indicará
que
es
falsa.
inform‐ref
Permite
que
el
emisor
informe
al
receptor
de
un
objeto
que
cree
que
corresponde
a
un
descriptor,
como
puede
ser
un
nombre
u
otra
descripción
que
lo
identifique.
not‐understood
Informar
a
un
receptor
que
el
emisor
no
entendió
el
mensaje
propagate
El
receptor
trata
el
mensaje
como
si
fuese
dirigido
directamente
a
él,
y
debe
identificar
-35/106-
los
agentes
en
este
descriptor
y
enviarles
el
mensaje
a
ellos
propose
Enviar
una
propuesta
para
realizar
una
cierta
acción
proxy
El
receptor
debe
seleccionar
agentes
objetivo
denotados
por
una
descripción
dada,
y
enviarles
un
mensaje
embebido
query‐if
Preguntarle
a
otro
agente
si
una
determinada
proposición
es
cierta
query‐ref
Preguntar
a
otro
agente
por
el
objeto
referenciado
en
una
expresión
refuse
Rechazar
realizar
una
acción
reject‐proposal
Rechazar
una
propuesta
durante
una
negociación
request
Solicitar
a
un
receptor
que
realice
alguna
acción
request‐when
Solicitar
al
receptor
que
realice
alguna
acción
cuando
una
proposición
dada
sea
cierta
request‐whenever
Solicitar
al
receptor
que
realice
alguna
acción
cada
vez
que
una
proposición
dada
sea
cierta
subscribe
Una
intención
persistente
de
notificar
al
emisor
de
un
determinado
valor,
y
volver
a
notificarle
cada
vez
que
dicho
valor
cambie
En el apartado siguiente, Implementación de los comportamientos (behaviours) se indica el
tipo de acciones comunicativas que utilizarán los agentes a implementar en el sistema.
4.4. Implementación de los comportamientos (behaviours)
4.4.1.
Comportamientos
de
subastadores
Los comportamientos de los subastadores se han realizado adaptando el FIPA Contract Net
Interaction Protocol [25] al protocolo de la subasta inglesa y holandesa. Encapsulan las
estrategias de cada tipo de subasta: inglesa y holandesa.
Las clases correspondientes a los subastadores: SubastadorHolandesaBehaviour y
SubastadorInglesaBehaviour extienden la clase base SubastadorBehaviour que a su vez
extiende la clase jade.proto.ContractNetInitiator. SubastadorBehaviour contiene los
métodos comunes a los comportamientos de los subastadores:
•
•
registrarTransacción. Envía un mensaje al agente CasaSubastas para que registre
la transacción.
getCasaSubastas. Obtiene el identificador del agente CasaSubastas registrado en
las páginas amarillas.
-36/106-
Figura 16. FIPA Contract Net Interaction Protocol
4.4.2.
Comportamientos
de
compradores
Los comportamientos de los compradores también obedecen a una adaptación del FIPA
Contract Net Interaction Protocol. Los comportamientos de los compradores encapsulan las
estrategias utilizadas por los compradores y ya comentadas en el apartado 2.1.3:
CompradorInglesaIncrementalBehaviour, CompradorHolandesaNRondasBehaviour
y CompradorHolandesaIncrementoDinamicoBehaviour; extienden la clase jade.proto.
SSIteratedContractNetResponder.
4.4.3.
Comportamientos
que
inician
una
petición
Estos comportamientos extienden la clase jade.proto.AchieveREInitiator que implementa
los protocolos de estilo FIPA Request:
•
•
•
BuscadorBehaviourInitiator. El agente Buscador realiza al agente CasaSubastas
una petición de búsqueda de una subasta en base al nombre del objeto subastado.
CompradorSuscribirBehaviourInitiator. El agente Comprador realiza una
petición de suscripción a un comprador para que le suscriba en una subasta.
SubastadorTransaccionesBehaviourInitiator. El agente Subastador realiza una
petición al agente CasaSubastas para que registre una transacción.
-37/106-
4.4.4.
Comportamientos
que
responden
a
una
petición
Estos comportamientos extienden la clase jade.proto.AchieveREResponder:
•
•
•
•
BuscadorBehaviourResponder. Devuelve al agente Comprador el resultado de la
búsqueda de la subasta.
CasaSubastasBusquedasBehaviourResponder. Devuelve al agente Buscador el
resultado de la búsqueda de la subasta.
SubastadorSuscribirBehaviourResponder. Suscribe al agente Comprador a la
subasta indicada en la petición correspondiente del comprador.
CasaSubastasTransaccionesBehaviourResponder. Registra la transacción
contenida en la petición realizada por el agente Subastador.
4.5. Implementación de las estrategias
4.5.1.
Interfaces
utilizados
en
las
estrategias
Se define el interface ICfgApuesta que deben implementar las estrategias de los
compradores e ICfgSubasta para las estrategias de los subastadores.
4.5.2.
Clases
que
implementan
el
interface
ICfgApuesta
Encapsulan los datos necesarios para la estrategia de los compradores. Son las siguientes,
ya comentadas en el apartado 2.1.3:
•
•
•
IncrementalCfgImpl
ApuestaUnicaNRondasCfgImpl
ApuestaUnicaIncrementoDinamicoCfgImpl
4.5.3.
Clases
que
implementan
el
interface
ICfgSubasta
Encapsulan los datos necesarios para la estrategia de los subastadores. Son las siguientes:
•
•
SubastaHolandesaImpl
SubastaInglesaImpl
4.6. Clases de información manejada en la subasta
Se utilizan las clases Subasta que contiene todos los datos necesarios para realizar la
subasta y la clase Transacción que se utilizará para el registro del historial de transacciones.
-38/106-
4.7. Estructura de paquetes
Las clases implementadas se estructuran dentro del paquete uoc.sma. En la figura siguiente
puede verse la estructura de paquetes utilizada con el fin de organizar todas las clases del
sistema según sean de tipo agente, comportamiento, etc..
Figura 17. Estructura de paquetes utilizada en el desarrollo del SMA
-39/106-
4.8. Librerías utilizadas
Las librería utilizadas en la implementación corresponden a:
•
•
El Java Runtime Environment 1.5.0
El entorno de ejecución JADE 3.6.1:
o http.jar
o iiop.jar
o jade.jar
o jadeTools.jar
o commons-codec-1.3.jar
4.9. Distribución final
La distribución de la aplicación está almacenada en una carpeta llamada SUBASTAS
dentro de la cual se encuentran las carpetas siguientes:
•
Carpeta src: contiene los paquetes y clases creadas en el proyecto.
•
Carpeta bin: contiene todas las clases del SMA en el archivo smasubastas.jar
(incluyendo archivos fuente) así como las librerías de JADE.
•
Carpeta doc: contiene el JAVADOC de la aplicación.
-40/106-
Capítulo 5. - Ejecución
5.1. Ejecución del SMA
La ejecución del SMA se realiza desde la clase IniciarSMA empaquetada en el archivo el
archivo smasubastas.jar junto con el resto de clases del sistema multiagente.
Esta clase realiza las acciones siguientes:
•
•
•
Obtiene una referencia al entorno de ejecución de JADE
Crea un contenedor JADE
Crea un agente de tipo AgenteCasaSubastas
Para ejecutar el SMA desde la línea de comandos hay que abrir la carpeta SUBASTAS\BIN
y poner el comando:
java -jar smasubastas.jar
Hay que tener en cuenta que las clases utilizadas se han compilado con la versión 1.5 de
Java.
5.2. Test de ejecución
Puesto que el sistema de subastas se ocupa de la capa de negocio y no dispone de interfaz
de usuario, en la clase AgenteCasaSubastas se han implementado métodos para probar el
funcionamiento del SMA. Estos métodos ya se ejecutan directamente al iniciar la
aplicación.
•
•
•
testSubastas. Se lanza al crearse el AgenteCasaSubastas (método setup). Crea 2
subastas (y por tanto 2 agentes compradores), las añade al sistema e invoca la
ejecución de los métodos que crean agentes compradores para la subasta inglesa y
para la subasta holandesa. La primera subasta comienza transcurrido 1 minuto desde
la ejecución de la clase IniciarSMA. La segunda subasta comienza 2 minutos
después.
testCrearCompradoresInglesa. Crea 3 agentes compradores y los suscribe a una
subasta inglesa.
testCrearCompradoresHolandesa. Crea 3 agentes compradores y los suscribe a
una subasta holandesa.
Por otra parte, para comprobar el comportamiento del agente Buscador, el agente
Comprador, al iniciarse (método setup), solicita la búsqueda de una subasta al agente
Buscador.
La realización de otros test podría realizarse solo con modificar la clase
AgenteCasaSubastas en lo que atañe a los tres métodos citados anterioemente.
-41/106-
El resultado de la ejecución del test es el siguiente:
imac‐de‐rodolfo‐de‐benito:bin
rodolfo$
java
‐jar
smasubastas.jar
16‐jun‐2009
16:27:42
jade.core.Runtime
beginContainer
INFO:
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
This
is
JADE
snapshot
‐
revision
$WCREV$
of
$WCDATE$
downloaded
in
Open
Source,
under
LGPL
restrictions,
at
http://jade.tilab.com/
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
16‐jun‐2009
16:27:43
jade.core.BaseService
init
INFO:
Service
jade.core.management.AgentManagement
initialized
16‐jun‐2009
16:27:43
jade.core.BaseService
init
INFO:
Service
jade.core.messaging.Messaging
initialized
16‐jun‐2009
16:27:43
jade.core.BaseService
init
INFO:
Service
jade.core.mobility.AgentMobility
initialized
16‐jun‐2009
16:27:43
jade.core.BaseService
init
INFO:
Service
jade.core.event.Notification
initialized
16‐jun‐2009
16:27:43
jade.core.messaging.MessagingService
clearCachedSlice
INFO:
Clearing
cache
16‐jun‐2009
16:27:43
jade.mtp.http.HTTPServer
<init>
INFO:
HTTP‐MTP
Using
XML
parser
com.sun.org.apache.xerces.internal.parsers.SAXParser
16‐jun‐2009
16:27:43
jade.core.messaging.MessagingService
boot
INFO:
MTP
addresses:
http://192.168.0.195:7778/acc
16‐jun‐2009
16:27:43
jade.core.AgentContainerImpl
joinPlatform
INFO:
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
Agent
container
Main‐Container@imac‐de‐rodolfo‐de‐benito.local
is
ready.
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteCasaSubastas
testSubastas
INFO:
El
agente
de
casa
de
subastas
crea
el
agente
Buscador
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:27:43
uoc.sma.agentes.AgenteComprador$1
action
INFO:
Agente
buscador:
subasta
localizada
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:28:43
uoc.sma.agentes.AgenteSubastador$1
onWake
INFO:
Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
‐
Se
inicia
la
subasta
Subasta
Id:1
iMac
25
Precio:2.25
Inicio:Tue
Jun
16
16:28:43
CEST
2009
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador2
:
ENVIA
:
PROPOSE
:
5.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador3
:
ENVIA
:
PROPOSE
:
30.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador1
:
ENVIA
:
PROPOSE
:
25.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
30.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador1
:
ENVIA
:
PROPOSE
:
35.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador2
:
ENVIA
:
PROPOSE
:
40.0
prepareResultNotification()
method
not
re‐defined
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
40.0
prepareResultNotification()
method
not
re‐defined
-42/106-
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador1
:
ENVIA
:
PROPOSE
:
45.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador3
:
ENVIA
:
PROPOSE
:
90.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
90.0
prepareResultNotification()
method
not
re‐defined
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador1
:
ENVIA
:
PROPOSE
:
95.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador2
:
ENVIA
:
PROPOSE
:
160.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
160.0
prepareResultNotification()
method
not
re‐defined
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour
handleCfp
INFO:
Comprador1
:
ENVIA
:
PROPOSE
:
165.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
165.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Puja
más
alta
en
esta
ronda:
0.0
16‐jun‐2009
16:28:43
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour
handleAllResponses
INFO:
Ganador
de
la
subasta:Subasta
Id:1
iMac
25
Precio:165.0
Inicio:Tue
Jun
16
16:28:43
CEST
2009
el
comprador
Comprador1
con
una
puja
de
165.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.agentes.AgenteSubastador$1
onWake
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
‐
Se
inicia
la
subasta
Subasta
Id:2
Mac
Book
pro
Precio:250.0
Inicio:Tue
Jun
16
16:29:43
CEST
2009
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
onEnd
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE:
Oferta
de
venta:235.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
onEnd
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE:
Oferta
de
venta:220.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
onEnd
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE:
Oferta
de
venta:205.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
onEnd
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE:
Oferta
de
venta:190.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
onEnd
INFO:
Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE:
Oferta
de
venta:175.0
prepareResultNotification()
method
not
re‐defined
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
handleAllResponses
INFO:
FIN
DE
SUBASTA
16‐jun‐2009
16:29:43
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour
handleAllResponses
INFO:
Ganador
de
la
subasta:Subasta
Id:2
Mac
Book
pro
Precio:175.0
Inicio:Tue
Jun
16
16:29:43
CEST
2009
el
comprador
Comprador6
con
una
puja
de
175.0
-43/106-
5.2.1.
Muestra
de
flujo
de
mensajes
en
el
test
de
la
subasta
inglesa
Figura 18. Intercambio de mensajes en subasta inglesa
-44/106-
5.2.2.
Muestra
de
intercambio
de
mensajes
de
negociación
entre
subastador
y
compradores
en
el
test
de
la
subasta
inglesa
Este extracto de los mensajes intercambiados entre el Subastador1 y los agentes
Comprador1, Comprador2 y Comprador 3 corresponde a la primera ronda de la subasta. Se
han marcado en negrita el tipo de mensaje e identificado el remitente y destinatario de los
mensajes.
Se puede ver que hay 3 mensajes de propuesta CFP (Call For Proposal) que el subastador
dirige a los compradores con el precio de salida del artículo, 2.25 euros. También se ven los
mensajes de respuesta a dichas propuestas (PROPOSE) con la puja propuesta por
Comprador1, Comprador2 y Comprador3: 25.0, 5.0 y 30.0, respectivamente.
(CFP
:sender
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"2.25"
:reply‐with
R1245001470219_0
:reply‐by
20090614T174440206Z
:conversation‐id
C8941849_1245001470219
)
(CFP
:sender
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"2.25"
:reply‐with
R1245001470220_1
:reply‐by
20090614T174440206Z
:conversation‐id
C8941849_1245001470219
)
(PROPOSE
:sender
(
agent‐identifier
:name
Comprador1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"25.0"
:reply‐with
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470230"
:in‐reply‐to
R1245001470220_1
:conversation‐id
C8941849_1245001470219
)
(CFP
:sender
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador3@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"2.25"
:reply‐with
R1245001470222_2
:reply‐by
20090614T174440206Z
:conversation‐id
C8941849_1245001470219
)
(PROPOSE
:sender
(
agent‐identifier
:name
Comprador2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"5.0"
:reply‐with
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470233"
:in‐reply‐to
R1245001470219_0
:conversation‐id
C8941849_1245001470219
)
(PROPOSE
-45/106-
:sender
(
agent‐identifier
:name
Comprador3@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"30.0"
:reply‐with
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470248"
:in‐reply‐to
R1245001470222_2
:conversation‐id
C8941849_1245001470219
)
5.2.3.
Muestra
de
flujo
de
mensajes
en
el
test
de
la
subasta
holandesa
Figura 19. Intercambio de mensajes en subasta holandesa
-46/106-
5.2.4.
Muestra
de
intercambio
de
mensajes
de
negociación
entre
subastador
y
compradores
en
el
test
de
la
subasta
holandesa
Este extracto de los mensajes intercambiados en la primera ronda de la subasta entre el
Subastador2 y los agentes Comprador4, Comprador5 y Comprador 6 corresponde a la
primera ronda de la subasta.
Se pueden ver los mensajes CFP que envía el subastador a los compradores proponiendo un
precio de venta de 250.0. Como contestación a este mensaje todos los compradores
rechazan
(CFP
:sender
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador4@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"250.0"
:reply‐with
R1245004074545_0
:reply‐by
20090614T182804535Z
:conversation‐id
C476737_1245004074545
)
(CFP
:sender
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador5@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"250.0"
:reply‐with
R1245004074546_1
:reply‐by
20090614T182804535Z
:conversation‐id
C476737_1245004074545
)
(REFUSE
:sender
(
agent‐identifier
:name
Comprador5@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:reply‐with
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245004074552"
:in‐reply‐to
R1245004074546_1
:conversation‐id
C476737_1245004074545
)
(CFP
:sender
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Comprador6@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"250.0"
:reply‐with
R1245004074548_2
:reply‐by
20090614T182804535Z
:conversation‐id
C476737_1245004074545
)
(REFUSE
:sender
(
agent‐identifier
:name
Comprador4@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:reply‐with
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245004074554"
:in‐reply‐to
R1245004074545_0
:conversation‐id
C476737_1245004074545
)
(REFUSE
:sender
(
agent‐identifier
:name
Comprador6@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:reply‐with
"Subastador
2@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245004074560"
:in‐reply‐to
R1245004074548_2
:conversation‐id
C476737_1245004074545
)
-47/106-
5.2.5.
Muestra
de
mensajes
entre
el
agente
Subastador,
el
agente
DF
y
el
agente
CasaSubastas
En este ejemplo el subastador pide con un mensaje REQUEST al agente DF que localice al
agente CasaSubastas. El agente DF le responde con un mensaje INFORM indicando el
identificador el agente CasaSubastas. El agente subastador le pide REQUEST al agente
CsaSubastas que registre una transacción y este le responde que lo ha realizado (AGREE).
(REQUEST
:sender
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
df@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"((action
(
agent‐identifier
:name
df@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
(search
(df‐agent‐description
:services
(set
(service‐description
:type
CasaDeSubastas)))
(search‐
constraints
:max‐results
‐1))))"
:reply‐with
"rw‐Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470264‐10"
:language
fipa‐sl0
:ontology
FIPA‐
Agent‐Management
:protocol
fipa‐request
:conversation‐id
"conv‐Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470264‐10"
)
(INFORM
:sender
(
agent‐identifier
:name
df@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
"((result
(action
(agent‐identifier
:name
df@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc))
(search
(df‐agent‐description
:services
(set
(service‐description
:type
CasaDeSubastas)))
(search‐
constraints
:max‐results
‐1)))
(sequence
(df‐agent‐description
:name
(agent‐identifier
:name
Casa‐Subastas@imac‐de‐rodolfo‐de‐
benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc))
:services
(set
(service‐description
:name
\"Casa‐
Subastas‐Casa
de
subastas\"
:type
CasaDeSubastas))))))"
:reply‐with
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470271"
:in‐reply‐to
"rw‐Subastador
1@imac‐de‐
rodolfo‐de‐benito.local:1099/JADE1245001470264‐10"
:language
fipa‐sl0
:ontology
FIPA‐Agent‐Management
:protocol
fipa‐request
:conversation‐id
"conv‐Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470264‐10"
)
(REQUEST
:sender
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
Casa‐Subastas@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:content
uoc.sma.datos.Transaccion
:reply‐with
R1245001470278_0
:protocol
fipa‐request
:conversation‐id
C6486835_1245001470278
)
(AGREE
:sender
(
agent‐identifier
:name
Casa‐Subastas@imac‐de‐rodolfo‐de‐benito.local:1099/JADE
:addresses
(sequence
http://192.168.0.196:7778/acc
))
:receiver
(set
(
agent‐identifier
:name
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE"
:addresses
(sequence
http://192.168.0.196:7778/acc
))
)
:reply‐with
"Subastador
1@imac‐de‐rodolfo‐de‐benito.local:1099/JADE1245001470290"
:in‐reply‐to
R1245001470278_0
:protocol
fipa‐request
:conversation‐id
C6486835_1245001470278
)
-48/106-
5.2.6.
Rondas
y
pujas
obtenidas
en
el
test
de
la
subasta
inglesa
La subasta inicial subastaba un artículo con un precio de salida de 2.25.
La configuración inicial de los compradores que participaron en ella es la siguiente:
Comprador
1
2
3
Puja
inicial
Incremento
25
5
30
10
2
3
Tipo
incremento
Reserva
puja+incremento
puja*incremento
puja*incremento
190
195
175
Las pujas en cada ronda han sido las siguientes:
Ronda
Comprador1
1
2
3
4
Comprador2
25
35
95
165
Comprador3
5
40
160
‐
30
90
‐
‐
Resulta ganador el Comprador 1 con una puja de 165.
5.2.7.
Rondas
y
pujas
obtenidas
en
el
test
de
la
subasta
holandesa
La subasta inicial subastaba un artículo con un precio de salida de 250.
La configuración inicial de los compradores que participaron en ella es la siguiente:
Comprador
4
5
6
Puja
inicial
Incremento
100
120
140
20
10
‐
Estrategia
Reserva
IncrementalDinamico
IncrementalDinamico
NRondas
Rondas
160
180
180
4
4
5
Las pujas en cada ronda han sido las siguientes:
Ronda
Subastador
2
Comprador4
Comprador5
Comprador6
1
2
3
4
5
235
220
205
190
175
‐
‐
‐
‐
‐
‐
‐
‐
‐
‐
‐
‐
‐
‐
175
-49/106-
5.3. Sistema de logging
En el proceso de desarrollo de la solución software se ha utilizado el sistema de log propio
de JADE, la clase jade.util.Logger.
Las clases inicializan el logger en nivel INFO para mostrar solo los mensajes de ese nivel:
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
logger.setLevel(Logger.INFO);
Los mensajes de log que se utilizan utilizan dos niveles de detalle: INFO y FINE:
logger.log(Logger.INFO,myAgent.getLocalName()
+
"
:
ENVIA
:
PROPOSE
:
"
+
puja);
logger.log(Logger.FINE,myAgent.getName()
+
"
:
Recibe
:
ACCEPT");
Si es necesario un mayor detalle en el log para ver el comportamiento del sistema entonces
puede establecerse el nivel FINE.
-50/106-
Capítulo 6. - Conclusiones y propuestas de mejora
Los Sistemas Multiagente de negociación constituyen una alternativa muy a tener en cuenta
en aquellos entornos en los que sea necesario elegir un algoritmo de negociación u
estrategia dependiendo de determinadas circunstancias. En este sentido el trabajo realizado
en este proyecto no solo se limita a las subastas electrónicas si no que puede servir de base
para la resolución de problemas de planificación y optimización de recursos basados en el
mejor "precio" o coste que puede ofrecer un agente en la resolución de una tarea concreta.
Es importante señalar que el estudiante ha tenido la oportunidad de aplicar los
conocimientos adquiridos en este proyecto en su ámbito profesional, proponiendo una
solución basada en multiagentes de negociación para resolver un problema de planificación
y optimización de recursos en un proyecto de I+D en el ámbito de bioenergía, en el que
actualmente trabaja como ingeniero de software.
En cuanto a las propuestas de mejora, son las siguientes:
•
Integrar el Sistema Multiagente en la capa de negocio de una aplicación J2EE,
posibilitando que la utilización del sistema se realice vía Web con un simple
navegador en lugar de hacerlo con una aplicación de escritorio o desde una solución
software de movilidad.
•
Interfaz del usuario: aunque el alcance de este proyecto no incluía el interfaz del
usuario, el interfaz del usuario facilitaría la interacción con el software.
•
Persistencia de datos: no contemplado en el alcance de este proyecto, utilizar una
base de datos relacional es necesario para registrar las subastas y transacciones
realizadas.
•
Cifrado de mensajes: puesto que los agentes pueden estar distribuidos y el
intercambio de mensajes realizarse por redes no seguras como Internet, el cifrado
del contenido de los mensajes puede aportar un nivel de seguridad básico al sistema.
La implementación del cifrado puede realizarse con las clases del paquete
javax.crypto utilizando, por ejemplo, el cifrado simétrico AES.
-51/106-
Bibliografía
Aranda Corral (2006). Construcción de un sistema multiagente mediante Jade. Curso:
Agentes Inteligentes. Universidad de Sevilla.
Bellifemine, Caire, Trucco, Rimassa (2007). JADE PROGRAMMER’S GUIDE
Bellifemine, Caire, Trucco, Rimassa (2007). JADE v3.6.1 API
Botia (2005). Construcción de Agentes Software con JAVA + JADE. Seminario de
Aplicación de los Agentes Software al Ocio y al turismo. Universidad Carlos III de
Madrid.
David Sánchez Ruenes. PROTOCOLS I ONTOLOGIES JADE 2.61. GUIA DE
PROGRAMACIÓ. Universitat Rovira i Virgili
Foundation for Intelligent Physical Agents (2003). FIPA ACL Message Structure
Specification, disponible en Internet
(http://www.fipa.org/specs/fipa00061/SC00061G.html)
Ganzha, Paprzycki, Pirvanescu, Badica y Abraham (2001). Jade Based Multi-Agent ECommerce Environment: Initial Implementation. 6th Int. Symposium SYNASC04,
Romania.
García Olaya (2007). Diseño Software de Agentes Inteligentes Autónomos: Tema IV –
Estándares para el desarrollo de SMA. Universidad Carlos III de Madrid.
Imbert Paredes (2005). Una Arquitectura Cognitiva Multinivel para Agentes con
Comportamiento
Influido por Características Individuales y Emociones, Propias y de Otros Agentes. Tesis
doctoral, Facultad de Informática. Universidad Politécnica De Madrid.
Ismail Khalil (2009). Cooperative Systems - UE, disponible en Internet (http://www.tk.unilinz.ac.at/teaching/)
Jennings, Sycara Y Wooldridge (1998). A Roadmap of Agent Research and Development.
Autonomous Agents and Multi-Agent Systems, 1, 7–38 (1998). Kluwer Academic
Publishers, Boston.
Llamas Bello (2002). Protocolos de interacción entre agentes (FIPA). Sistemas
Multiagente, Cursos de doctorado UVA.
Rinkesh Patel (2006). A Trustworthy Agent Based Online Auction System. CIS Master
Project. University of Massachusetts Dartmouth.
Stan Franklin y Art Graesser (1996). Is it an Agent, or just a Program?: A Taxonomy for
Autonomous Agents. Third International Workshop on Agent Theories, Architectures,
and Languages, Springer-Verlag.
Valladares Pernas (2004). Multi-Agent System for Online Auctions. CIS Master Project.
University of Massachusetts Dartmouth.
-52/106-
Referencias bibliográficas
[1] Moreno Ribas, Antonio. Agentes y sistemas multiagente. Módulo 2 P05/81007/00776.
UOC
[2] FIPA, disponible en Internet (http://www.fipa.org)
[3] Wooldridgey Jennings (1995)
[4] Luck M, McBurney P, Shehory O, Willmott S (2005) Agent Technology: Computing as
Interaction (A Roadmap for Agent Based Computing). AgentLink. Disponible en
Internet (http://www.agentlink.org/roadmap/al3rm.pdf)
[5] Wooldridge, Michael (2002). An Introduction to Multiagent systems. Wiley
[6] Posada, Marta y Lopez, Adolfo (2008). How to Choose the Bidding Strategy in
Continuous Double Auctions: Imitation Versus Take-The-Best Heuristics. Journal of
Artificial Societies and Social Simulation 11(1)6, disponible en Internet
(http://jasss.soc.surrey.ac.uk/11/1/6.html).
[7] Bagnall y Toft. Zero Intelligence Plus and Gjerstad-Dickhaut Agents for Sealed Bid
Auctions. Diponible en Internet en (http://citeseer.ist.psu.edu/708332.html)
[8] Posada, Lopez y Hernández (2004). Aprendizaje Evolutivo en la Subasta Doble
Continua. Un enfoque Multiagente, disponible en Internet en
(http://io.us.es/cio2004/comunicaciones/111-120.pdf)
[9] IDK, disponible en Internet (http://grasia.fdi.ucm.es/main/?q=en/node/127)
[10] Moreno, Velásquez, Ovalle. Una Aproximación Metodológica para la Construcción
de Modelos de Simulación Basados en el Paradigma Multi-Agente. Avances en
Sistemas e Informática, Vol.4 No. 2, Septiembre de 2007, disponible en Internet en
(http://pisis.unalmed.edu.co/avances/archivos/ediciones/Edicion%20Avances%202007
%202/16.pdf)
[11] JADE, disponible en Internet (http://jade.tilab.com)
[12] Bellifemine, Caire, Greenwood (2007). Developing Multi Agent Systems with JADE.
Wiley
[13] Hibernate, disponible en Internet en (https://www.hibernate.org)
[14] iBatis, disponible en Internet en (http://ibatis.apache.org)
[15] Patel, Rinkesh (2006). A Trustworthy Agent Based Online Auction System, disponible
en Internet
(http://www.cis.umassd.edu/~hxu/Projects/UMD/TrustworthyAuction/TrustworthyAuction-System.ppt)
[16] Fabra, Natalia (2003). Mecanismos de Subastas, disponible en Internet
(http://www.eco.uc3m.es/nfabra/Docencia/Seminarios/Subastas_UMTS.pdf)
[17] Juan Momparler, Mario Hidalgo. Modelos de subastas y su aplicación a los concursos,
disponible en Internet (http://www.uv.es/asepuma/XIII/comunica/comunica_58.pdf)
-53/106-
[18] Foundation for Intelligent Physical Agents (2002). FIPA English Auction Interaction
Protocol Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00031/index.html)
[19] Foundation for Intelligent Physical Agents (2002). FIPA Dutch Auction Interaction
Protocol Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00032/index.html)
[20] Foundation for Intelligent Physical Agents (2002). FIPA Subscribe Interaction
Protocol Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00035/SC00035H.html)
[21] Foundation for Intelligent Physical Agents (2002). FIPA Brokering Interaction
Protocol Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00033/SC00033H.pdf)
[22] Foundation for Intelligent Physical Agents (2002). FIPA Query Interaction Protocol
Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00027/SC00027H.pdf)
[23] Foundation for Intelligent Physical Agents (2002). FIPA ACL Message Structure
Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00061/SC00061G.pdf)
[24] Escuela Superior de Ingeniería Informática de la Universidad de Vigo. Programación
en JADE - Comunicación, disponible en Internet en
(http://programacionjade.wikispaces.com/Comunicación)
[25] Foundation for Intelligent Physical Agents (2002). FIPA ContractNet Interaction
Protocol Specification, disponible en Internet en
(http://www.fipa.org/specs/fipa00029/SC00029H.pdf)
-54/106-
Anexo A. Clases Java implementadas
Clase
AgenteBase
package
uoc.sma.agentes;
import
jade.core.Agent;
import
jade.domain.DFService;
import
jade.domain.FIPAException;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.domain.FIPAAgentManagement.ServiceDescription;
import
jade.util.Logger;
/**
*
Clase
base
para
loa
agentes
que
contiene
servicios
comunes
a
todos
ellos
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
@SuppressWarnings("serial")
public
class
AgenteBase
extends
Agent
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
@Override
/*
*
Procedimiento
que
se
ejecuta
en
la
creación
del
agente
*/
protected
void
setup()
{
//Establece
el
nivel
de
mensajes
del
logger
logger.setLevel(Logger.INFO);
}
/**
*
Registra
a
un
agente
en
las
páginas
amarillas
*
para
facilitar
su
localización
*
*
@param
tipoAgente
El
tipo
de
agente
a
registrar
*
@param
nombre
El
nombre
del
agente
*
*/
protected
void
registrarDFAgente(String
tipoAgente,
String
nombre)
{
logger.log(Logger.FINE,this.getLocalName()
+"
registrando
agente
"
+
nombre
+"
en
páginas
amarillas");
//Crea
la
descripción
del
agente
y
le
asigna
el
nombre
de
agente
DFAgentDescription
descripcionAgente
=
new
DFAgentDescription();
descripcionAgente.setName(getAID());
//Crea
la
descripción
del
servicio
y
le
asigna
el
nombre
del
agente
y
tipo
ServiceDescription
sd
=
new
ServiceDescription();
sd.setType(tipoAgente);
sd.setName(nombre);
descripcionAgente.addServices(sd);
try
{
//Registra
el
agente
en
las
páginas
amarillas
DFService.register(this,
descripcionAgente);
}
catch
(FIPAException
e)
{
e.printStackTrace();
}
}
-55/106-
}
/**
*
Localiza
a
un
agente
en
las
páginas
amarillas
*
*
@param
tipo
El
tipo
de
agente
a
localizar
*
@return
El
array
de
agentes
que
responden
al
tpo
de
agente
a
localizar
*/
protected
DFAgentDescription[]
getAgentePaginasAmarillas(String
tipo)
{
logger.log(Logger.FINE,this.getLocalName()
+"
localizando
agente
"+tipo+"
en
páginas
amarillas");
//Crea
la
plantilla
tipo
del
agente
a
localizar
DFAgentDescription
plantilla
=
new
DFAgentDescription();
DFAgentDescription[]
resultado
=
null;
ServiceDescription
sd
=
new
ServiceDescription();
sd.setType(tipo);
plantilla.addServices(sd);
try
{
//Busca
al
agente
en
las
páginas
amarillas
resultado
=
DFService.search(this,
plantilla);
}
catch
(FIPAException
fe)
{
fe.printStackTrace();
}
return
resultado;
}
-56/106-
Clase
AgenteCasaSubastas
package
uoc.sma.agentes;
import
java.io.IOException;
import
java.util.ArrayList;
import
java.util.GregorianCalendar;
import
java.util.Iterator;
import
java.util.logging.FileHandler;
import
uoc.sma.behaviours.CasaSubastasBusquedasBehaviourResponder;
import
uoc.sma.behaviours.CasaSubastasTransaccionesBehaviourResponder;
import
uoc.sma.datos.Subasta;
import
uoc.sma.datos.Transaccion;
import
uoc.sma.estrategias.ApuestaUnicaIncrementoDinamicoCfgImpl;
import
uoc.sma.estrategias.ApuestaUnicaNRondasCfgImpl;
import
uoc.sma.estrategias.ICfgSubasta;
import
uoc.sma.estrategias.IncrementalCfgImpl;
import
uoc.sma.estrategias.SubastaHolandesaImpl;
import
uoc.sma.estrategias.SubastaInglesaImpl;
import
jade.core.AID;
import
jade.domain.DFService;
import
jade.domain.FIPAException;
import
jade.domain.FIPANames;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.util.Logger;
import
jade.util.leap.HashMap;
import
jade.wrapper.ControllerException;
import
jade.wrapper.PlatformController;
import
jade.wrapper.StaleProxyException;
/**
*
Agente
con
las
responsabilidades
siguientes:
*
‐Crear
un
agente
subastador
cuando
se
crea
una
nueva
subasta
*
‐Crear
la
subasta
*
‐Obtener
la
lista
de
bienes
que
se
subastan.
Para
acotar
el
problema
se
considera
*
que
no
puede
haber
2
subastas
activas
que
subasten
el
mismo
bien.
*
‐Buscar
el
ID
de
la
subasta
según
el
bien
subastado
*
‐Eliminar
al
agente
subastador
cuando
concluye
la
subasta
*
*
Comportamientos:
*
‐Atender
las
peticiones
de
escritura
en
el
historial
de
transacciones
*
‐Atender
las
peticiones
de
búsqueda
de
subastas
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
@SuppressWarnings("serial")
public
class
AgenteCasaSubastas
extends
AgenteBase
{
private
HashMap
subastas;
//La
lista
de
subastas
activas
(id,
subasta)
private
ArrayList<Transaccion>
historialTransacciones;
//El
historial
de
transacciones
private
HashMap
bienesSubastados;
//
La
lista
de
bienes
subastados
(bienSubastado,
idSubasta)
private
PlatformController
contenedor;
//Una
referencia
al
contenedor
de
agentes
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
@Override
/**
*
Al
inicializar
el
agente
realiza
las
operaciones
siguientes:
-57/106-
*
‐Inicializar
las
listas
de
historial
de
transacciones
*
‐Inicializar
la
lista
de
subastas
activas
*
‐Inicializar
la
lista
de
bienes
subastados
*
‐Añadir
los
comportamientos
al
agente
*
‐Registrarse
en
las
páginas
amarillas
*
*/
protected
void
setup()
{
super.setup();
//Habilita
el
logger
para
escribir
en
el
fichero
Historial.log
try
{
FileHandler
handler;
handler
=
new
FileHandler("Historial.log");
logger.addHandler(handler);
}
catch
(SecurityException
e)
{
e.printStackTrace();
}
catch
(IOException
e)
{
e.printStackTrace();
}
logger.setLevel(Logger.INFO);
this.contenedor=getContainerController();
//Obtiene
una
referencia
al
contenedor
//Inicialización
de
estructuras
de
datos
inicializarEstructurasDatos();
//Registro
en
páginas
amarillas
registrarDFAgente("CasaDeSubastas",getLocalName()
+
"‐Casa
de
subastas");
addHistorialTransaccionesBehaviour();
addBusquedaSubastasBehaviour();
}
//A
modo
de
prueba
añade
subastas
al
sistema
testSubastas();
/**
*
Añade
el
comportamiento
que
atiende
a
las
peticiones
de
búsquedas
*
de
subastas
*
*
Sigue
el
protocolo
FIPA_QUERY
*/
private
void
addBusquedaSubastasBehaviour()
{
logger.log(Logger.FINE,"Agente
"+getLocalName()+"
esperando
peticiones
de
búsqueda
de
subastas...");
MessageTemplate
template
=
MessageTemplate.and(
MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_QUERY),
MessageTemplate.MatchPerformative(ACLMessage.QUERY_REF)
);
addBehaviour(new
CasaSubastasBusquedasBehaviourResponder(this,template));
}
/**
*
Añade
el
comportamiento
que
se
encarga
de
atender
las
peticiones
*
de
añadir
información
de
la
subasta
al
historial
*
*
Sigue
el
protocolo
FIPA‐REQUEST
*/
private
void
addHistorialTransaccionesBehaviour()
{
logger.log(Logger.FINE,"Agente
"+getLocalName()+"
esperando
peticiones
para
el
historial
de
transacciones...");
MessageTemplate
protocolo
=
MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
MessageTemplate
performativa
=
MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
MessageTemplate
plantilla
=
MessageTemplate.and(protocolo,
performativa);
-58/106-
}
addBehaviour(new
CasaSubastasTransaccionesBehaviourResponder(this,plantilla));
/**
*
Inicializa
las
estructuras
de
datos
necesarias
para
el
agente
*/
private
void
inicializarEstructurasDatos()
{
historialTransacciones
=
new
ArrayList<Transaccion>();
subastas
=
new
HashMap();
bienesSubastados
=
new
HashMap();
}
/**
*
Agrega
una
transacción
al
historial
*
*
@param
t
La
transacción
a
agregar
*/
public
void
addTransaccion(Transaccion
t){
historialTransacciones.add(t);
logger.log(Logger.FINE,"Se
ha
añadido
la
transacción
"+t);
if
(t.getOperación().equalsIgnoreCase(Transaccion.FIN))
{
logger.log(Logger.FINE,"Se
cierra
la
subasta
"+t.getIdSubasta());
this.cerrarSubasta(t.getIdSubasta());
}
}
/**
*
Obtiene
el
historial
de
transacciones
*
*
@return
La
lista
de
transacciones
*/
public
ArrayList<Transaccion>
getTransacciones(){
return
historialTransacciones;
}
/**
*
Añade
una
nueva
subasta
al
sistema
*
‐Crea
el
Agente
vendedor
y
lo
asocia
a
la
subasta
*
‐Añade
la
subasta
a
la
lista
de
subastas
activas
*
‐Añade
el
bien
subastado
a
la
lista
de
bienes
*
‐Crea
una
nueva
transacción
de
inicio
de
subasta
y
la
añade
al
historial
*
*
@param
s
‐
La
subasta
a
añadir
*
@param
estrategiaSubasta
La
estrategia
de
subasta
del
vendedor
(subasta
inglesa,
holandesa,
etc.)
*/
private
void
addSubasta(Subasta
s,
ICfgSubasta
estrategiaSubasta){
crearAgenteSubastador(s,
estrategiaSubasta);
subastas.put(s.getIdSubasta(),
s);
addBienSubastado(s.getObjetoSubastado(),
s.getIdSubasta());
addTransaccion(new
Transaccion(s.getFechaInicio(),s.getIdSubasta(),s.getAgenteSubastador().getLocalName(),"INICIO",s.getPrecio()));
logger.log(Logger.FINE,"Se
ha
creado
en
el
sistema
la
subasta
"+s);
}
/**
*
Elimina
la
subasta
de
la
lista
de
subastas
activas
*
*
@param
id
‐
El
identificador
de
la
subasta
a
eliminar
*/
public
void
removeSubasta(int
id){
subastas.remove(id);
}
-59/106-
/**
*
Obtiene
la
subasta
indicada
por
el
identificador
*
*
@param
id
El
identidficador
de
la
subasta
*
@return
La
subasta
*/
public
Subasta
getSubasta(int
id){
return
(Subasta)
subastas.get(id);
}
/**
*
Añade
un
nuevo
bien
subastado
a
la
lista
*
*
Cada
bien
diferente
se
identifica
en
un
HashMap
cuyas
*
claves
referencian
a
un
ArrayList
de
subastas
para
permitir
*
colisiones
en
el
HashMap
*
*
@param
b
‐
El
bien
que
se
subasta
*
@param
l
*/
public
void
addBienSubastado(String
b,
int
l){
bienesSubastados.put(b.toUpperCase(),new
Integer(l));
logger.log(Logger.FINE,"Hay
un
nuevo
bien
subastado
"+b+"
en
la
subasta
"+l);
}
/**
*
Elimina
un
bien
de
la
lista
de
bienes
subastados
*
*
@param
b
El
bien
a
eliminar
*/
public
void
removeBienSubastado(String
b){
bienesSubastados.remove(b.toUpperCase());
}
/**
*
Localiza
la
subasta
que
contiene
el
bien
a
buscar
*
Si
no
lo
encuentra
devuelve
0
*
*
@param
bienSubastado
El
bien
a
localizar
en
la
subasta
*
@return
La
subasta
*/
public
Subasta
getSubasta(String
bienSubastado){
if
(bienesSubastados!=null){
if
(bienesSubastados.get(bienSubastado.toUpperCase())!=null){
return
(Subasta)
subastas.get((Integer)
bienesSubastados.get(bienSubastado.toUpperCase()));
}
}
return
null;
}
/**
*
Devuelve
toda
la
lista
de
subastas
*
@return
*/
public
Iterator
getAllSubastas(){
return
(Iterator)
this.subastas.values();
}
-60/106-
/**
*
Crea
un
nuevo
agente
subastador
encargado
de
una
subasta
*
*
@param
s
La
subasta
que
atiende
el
agente
vendedor
*
@param
estrategiaSubasta
La
estrategia
que
seguirá
la
subasta
(Inglesa,
Holandesa,
etc)
*/
private
void
crearAgenteSubastador(Subasta
s,
ICfgSubasta
estrategiaSubasta){
Object[]
args
=
new
Object[2];
args[0]=s;
args[1]=estrategiaSubasta;
try
{
contenedor.createNewAgent("Subastador
"+s.getIdSubasta(),
"uoc.sma.agentes.AgenteSubastador",args
).start();
}
catch
(StaleProxyException
e)
{
e.printStackTrace();
}
catch
(ControllerException
e)
{
e.printStackTrace();
}
s.setAgenteSubastador(new
AID("Subastador
"+s.getIdSubasta(),AID.ISLOCALNAME));
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Subastador
para
la
subasta
"+s.getIdSubasta());
}
/**
*
Elimina
de
la
memoria
el
agente
subastador
*
*
@param
localname
El
agente
a
eliminar
*/
private
void
eliminarAgenteSubastador(String
localname){
try
{
contenedor.getAgent(localname).kill();
}
catch
(StaleProxyException
e)
{
e.printStackTrace();
}
catch
(ControllerException
e)
{
e.printStackTrace();
}
}
/**
*
Realiza
las
operaciones
necesarias
para
eliminar
la
subasta
*
una
vez
ésta
haya
concluido:
*
‐Quitar
la
subasta
de
la
lista
*
‐Quitar
el
bien
subastado
de
la
lista
*
‐Eliminar
al
agente
subastador
responsable
de
la
subasta
*
*
@param
idSubasta
El
identificador
de
la
subasta
a
cerrar
*/
public
void
cerrarSubasta(int
idSubasta){
removeBienSubastado(getSubasta(idSubasta).getObjetoSubastado());
eliminarAgenteSubastador(getSubasta(idSubasta).getAgenteSubastador().getLocalName());
removeSubasta(idSubasta);
}
@Override
/**
*
Al
finalizar
el
agente:
*
‐
Quitar
el
registro
de
las
páginas
amarillas
*/
protected
void
takeDown()
{
super.takeDown();
try
{
DFService.deregister(this);
}
catch
(FIPAException
fe)
{
-61/106-
fe.printStackTrace();
}
logger.log(Logger.INFO,"Historial
de
transacciones:"
+
this.historialTransacciones);
}
/**
*
Método
que
comprueba
el
funcionamiento
de
las
subastas
inglesa
y
holandesa
*
Crea
una
subasta
inglesa
y
una
subasta
holandesa
*
*
Crea
3
agentes
compradores
para
una
subasta
inglesa
y
3
compradores
para
*
una
subasta
holandesa.
*
*
Crea
un
agente
buscador.
*
*/
private
void
testSubastas()
{
GregorianCalendar
fInicioS1=
new
GregorianCalendar();
fInicioS1.add(GregorianCalendar.MINUTE,
1);
Subasta
s1
=
new
Subasta(1,fInicioS1.getTime(),"iMac
25",2.25,50,true,Subasta.SUBASTA_INGLESA);
//ICfgSubasta
e1
=
new
SubastaInglesaImpl();
GregorianCalendar
fInicioS2=
new
GregorianCalendar();
fInicioS2.add(GregorianCalendar.MINUTE,
2);
Subasta
s2
=
new
Subasta(2,fInicioS2.getTime(),"Mac
Book
pro",250,0,true,Subasta.SUBASTA_HOLANDESA);
//Crea
2
subasta
de
ejemplo
addSubasta(s1,new
SubastaInglesaImpl());
addSubasta(s2,new
SubastaHolandesaImpl());
try
{
//
Crea
agente
buscador
de
subastas
contenedor.createNewAgent("Buscador",
"uoc.sma.agentes.AgenteBuscador",null
).start();
logger.log(Logger.INFO,"El
agente
de
casa
de
subastas
crea
el
agente
Buscador");
testCrearCompradoresInglesa(s1);
testCrearCompradoresHolandesa(s2);
}
catch
(StaleProxyException
e)
{
e.printStackTrace();
}
catch
(ControllerException
e)
{
e.printStackTrace();
}
}
/**
*
Crea
3
compradores
de
prueba
para
la
subasta
Holandesa
*
*
@param
s2
*
@throws
StaleProxyException
*
@throws
ControllerException
*/
private
void
testCrearCompradoresHolandesa(Subasta
s2)
throws
StaleProxyException,
ControllerException
{
Object[]
args4
=
new
Object[2];
args4[0]=
s2;
args4[1]
=new
ApuestaUnicaIncrementoDinamicoCfgImpl(20,100,160,4);
Object[]
args5
=
new
Object[2];
args5[0]=
s2;
args5[1]
=new
ApuestaUnicaIncrementoDinamicoCfgImpl(10,120,180,4);
Object[]
args6
=
new
Object[2];
args6[0]=
s2;
-62/106-
}
args6[1]
=new
ApuestaUnicaNRondasCfgImpl(0,140,180,5);
contenedor.createNewAgent("Comprador4",
"uoc.sma.agentes.AgenteComprador",args4
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador4
para
la
subasta
"+s2.getIdSubasta());
contenedor.createNewAgent("Comprador5",
"uoc.sma.agentes.AgenteComprador",args5
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador5
para
la
subasta
"+s2.getIdSubasta());
contenedor.createNewAgent("Comprador6",
"uoc.sma.agentes.AgenteComprador",args6
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador6
para
la
subasta
"+s2.getIdSubasta());
}
/**
*
Crea
compradores
de
prueba
para
la
subasta
Inglesa
*
*
@param
s1
*
@throws
StaleProxyException
*
@throws
ControllerException
*/
private
void
testCrearCompradoresInglesa(Subasta
s1)
throws
StaleProxyException,
ControllerException
{
Object[]
args1
=
new
Object[2];
args1[0]=
s1;
args1[1]
=new
IncrementalCfgImpl(0,10,25,190);
Object[]
args2
=
new
Object[2];
args2[0]=
s1;
args2[1]
=new
IncrementalCfgImpl(1,2,5,195);
Object[]
args3
=
new
Object[2];
args3[0]=
s1;
args3[1]
=new
IncrementalCfgImpl(1,15,30,175);
contenedor.createNewAgent("Comprador1",
"uoc.sma.agentes.AgenteComprador",args1
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador1
para
la
subasta
"+s1.getIdSubasta());
contenedor.createNewAgent("Comprador2",
"uoc.sma.agentes.AgenteComprador",args2
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador2
para
la
subasta
"+s1.getIdSubasta());
contenedor.createNewAgent("Comprador3",
"uoc.sma.agentes.AgenteComprador",args3
).start();
logger.log(Logger.FINE,"El
agente
de
casa
de
subastas
crea
el
agente
Comprador3
para
la
subasta
"+s1.getIdSubasta());
}
-63/106-
Clase
AgenteSubastador
package
uoc.sma.agentes;
import
java.util.Date;
import
java.util.HashSet;
import
java.util.Iterator;
import
java.util.Set;
import
uoc.sma.behaviours.SubastadorSuscribirBehaviourResponder;
import
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour;
import
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour;
import
uoc.sma.datos.Subasta;
import
uoc.sma.estrategias.ICfgSubasta;
import
jade.core.AID;
import
jade.core.behaviours.WakerBehaviour;
import
jade.domain.FIPAAgentManagement.FailureException;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.proto.SubscriptionResponder;
import
jade.proto.SubscriptionResponder.Subscription;
import
jade.proto.SubscriptionResponder.SubscriptionManager;
import
jade.util.Logger;
/**
*
Agente
que
se
encarga
de
una
subasta
determinada
puesta
en
marcha
por
un
*
usuario
Tiene
las
responsabilidades
siguientes:
*
‐Aceptar
las
pujas
de
los
compradores
y
efectuar
las
postcondiones
a
la
recepción
de
una
puja
*
‐Notificar
a
los
agentes
compradores
participantes
los
cambios
de
precio
en
*
la
subasta
*
‐Notificar
el
ganador
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
@SuppressWarnings("serial")
public
class
AgenteSubastador
extends
AgenteBase
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
Subasta
subasta;
private
ICfgSubasta
estrategiaSubasta;
private
Set<Subscription>
suscripciones
=
new
HashSet<Subscription>();
public
Subasta
getSubasta()
{
return
subasta;
}
public
void
setSubasta(Subasta
subasta)
{
this.subasta
=
subasta;
}
public
Set<Subscription>
getSuscripciones()
{
return
suscripciones;
}
public
void
setSuscripciones(Set<Subscription>
suscripciones)
{
this.suscripciones
=
suscripciones;
}
public
ICfgSubasta
getEstrategiaSubasta()
{
return
estrategiaSubasta;
}
-64/106-
/**
*
Añade
el
comportamiento
con
la
estrategia
que
utilizará
el
comprador
*
*
@param
estrategiaSubasta
La
estrategia
a
seguir
en
la
compra
*/
public
void
setEstrategiaSubasta(ICfgSubasta
estrategiaSubasta)
{
this.estrategiaSubasta
=
estrategiaSubasta;
}
@Override
protected
void
setup()
{
super.setup();
//
Comprueba
los
argumentos
del
agente
subastador
y
obtiene
la
estrategia
del
vendedor
subasta
=
(Subasta)
this.getArguments()[0];
if
((getArguments()!=null)
&&
(getArguments().length>=2)){
setEstrategiaSubasta((ICfgSubasta)getArguments()[1]);
}else{
logger.log(Logger.INFO,"El
agente
"+this.getLocalName()+"
no
dispone
de
ninguna
estrategia
de
venta");
//Termina
la
ejecución
del
agente
cuando
el
número
de
argumentos
es
incorrecto
this.doDelete();
}
logger.log(Logger.FINE,"Agente
subastador
"
+
this.getLocalName()
+
"
creado.");
logger.log(Logger.FINE,this.getLocalName()+
":
Esperando
suscripciones
a
la
subasta...");
//
Se
crea
una
plantilla
para
que
sólo
se
admitan
mensajes
del
protocolo
FIPA‐Subscribe
MessageTemplate
template
=
SubscriptionResponder.createMessageTemplate(ACLMessage.SUBSCRIBE);
//
Se
crea
un
SubscriptionManager
que
registrará
y
eliminará
las
suscripciones.
SubscriptionManager
gestor
=
crearGestorSubscripciones();
//
Se
añade
un
comportamiento
que
maneja
los
mensajes
recibidos
para
suscribirse.
this.addBehaviour(new
SubastadorSuscribirBehaviourResponder(this,
template,
gestor));
this.addBehaviour(new
WakerBehaviour(this,subasta.getFechaInicio())
{
}
}
);
@Override
protected
void
onWake()
{
super.onWake();
logger.log(Logger.INFO,myAgent.getName()
+
"
‐
Se
inicia
la
subasta
"+subasta);
ACLMessage
cfpMsg
=
new
ACLMessage(ACLMessage.CFP);
cfpMsg.setContent(String.valueOf(subasta.getPrecio()));
cfpMsg.setReplyByDate(new
Date(System.currentTimeMillis()
+
10000));
if
(subasta.getTipoSubasta()==Subasta.SUBASTA_INGLESA)
myAgent.addBehaviour(new
SubastadorInglesaBehaviour(myAgent,
cfpMsg));
else
if
(subasta.getTipoSubasta()==Subasta.SUBASTA_HOLANDESA)
myAgent.addBehaviour(new
SubastadorHolandesaBehaviour(myAgent,
cfpMsg));
}
/**
*
Crea
el
gestor
de
suscripciones
y
define
los
métodos
para
*
suscribir
y
desuscribir
agentes
a
las
subastas
*
*
@return
*/
private
SubscriptionManager
crearGestorSubscripciones()
{
SubscriptionManager
gestor
=
new
SubscriptionManager()
{
-65/106-
public
boolean
deregister(Subscription
suscripcion)
throws
FailureException
{
if
(suscripcion.getMessage().getContent()
!=
null)
{
int
idSubasta
=
obtenerIdSubasta(suscripcion.getMessage()
.getContent());
suscripciones.remove(suscripcion);
return
removeSuscriptor(suscripcion.getMessage()
.getSender(),
idSubasta);
}
return
false;
}
public
boolean
register(Subscription
suscripcion)
throws
RefuseException,
NotUnderstoodException
{
if
(suscripcion.getMessage().getContent()
!=
null)
{
int
idSubasta
=
obtenerIdSubasta(suscripcion.getMessage()
.getContent());
suscripciones.add(suscripcion);
return
addSuscriptor(suscripcion.getMessage().getSender(),
idSubasta);
}
return
false;
}
}
private
int
obtenerIdSubasta(String
content)
{
return
Integer.parseInt(content);
}
};
return
gestor;
@Override
protected
void
takeDown()
{
super.takeDown();
}
/**
*
Añade
un
suscriptor
a
la
lista
de
suscriptores
*
*
@param
suscriptor
*/
public
boolean
addSuscriptor(AID
suscriptor,
int
idSubasta){
subasta.getSuscriptores().add(suscriptor);
logger.log(Logger.FINE,"Se
ha
añadido
el
suscriptor
"+
suscriptor.getLocalName()+
"
a
la
subasta
"+subasta);
return
true;
}
/**
*
Elimina
un
suscriptor
de
la
lista
de
suscriptores
*
*
@param
suscriptor
*/
public
boolean
removeSuscriptor(AID
suscriptor,
int
idSubasta){
subasta.getSuscriptores().remove(suscriptor);
logger.log(Logger.FINE,"Se
ha
eliminado
el
suscriptor
"+
suscriptor.getLocalName()+
"
de
la
subasta
"+subasta);
return
true;
}
//Comprueba
la
propuesta.
En
este
caso
si
el
contenido
del
mensaje
tiene
una
longitud
mayor
que
2,
devuelve
true
public
boolean
compruebaMensaje(String
propuesta)
{
return
true;
}
-66/106-
}
/**
*
Añade
al
mensaje
CFP
a
los
suscriptores
de
la
subasta
*
*
@param
m
El
mensaje
que
se
enviará
*
@return
*/
public
ACLMessage
addAgentsToMessage(ACLMessage
m)
{
Iterator<AID>
it
=
subasta.getSuscriptores().iterator();
while
(it.hasNext()){
m.addReceiver(it.next());
}
return
m;
}
Clase
AgenteBuscador
package
uoc.sma.agentes;
import
uoc.sma.behaviours.BuscadorBehaviourInitiator;
import
uoc.sma.behaviours.BuscadorBehaviourResponder;
import
jade.domain.DFService;
import
jade.domain.FIPAException;
import
jade.domain.FIPANames;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.util.Logger;
/**
*
Agente
que
tiene
como
responsabilidad
principal
localizar
*
las
subastas
activas
de
interés
para
el
comprador
*
a
partir
del
bien
a
comprar
y
comunicarselas
al
usuario.
*
*
Se
basa
en
FIPA‐BROKERING
de
tal
manera
que
este
agente
buscador
actua
de
*
intermediario
entre
el
agente
CasaSubastas
y
el
agente
comprador.
*
El
agente
comprador
le
pide
realizar
una
búsqueda
y
el
agente
buscador
*
se
la
remite
al
agente
CasaSubastas.
*
Cuando
el
agente
CasaSubastas
devuelve
el
resultado
de
la
búsqueda,
*
este
agente
retorna
el
resultado
al
comprador
*
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
AgenteBuscador
extends
AgenteBase
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
@Override
/*
*
Procedimiento
que
se
ejecuta
en
la
creación
del
agente
*/
protected
void
setup()
{
logger.log(Logger.FINE,"Agente
"
+
getLocalName()
+
"
esperando
peticiones...");
registrarDFAgente("BUSCADOR",
this.getLocalName());
//Crea
una
plantilla
de
mensajes
con
el
protocolo
FIPA_REQUEST
-67/106-
}
//con
mensajes
de
tipo
REQUEST
MessageTemplate
template
=
MessageTemplate.and(MessageTemplate
.MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST),
MessageTemplate.MatchPerformative(ACLMessage.REQUEST));
}
//
Registra
un
AchieveREInitiator
para
el
estado
PREPARE_RESULT_NOTIFICATION
//
Que
se
utilizará
para
iniciar
la
conversación
con
el
agente
CasaSubastas
//
solicitando
que
realice
una
búsqueda
y
para
devolver
el
resultado
de
la
búsqueda
//
al
agente
comprador
responder.registerPrepareResultNotification(new
BuscadorBehaviourInitiator(this,
null));
addBehaviour(responder);
//Añade
al
agente
el
comportamiento
que
responderá
a
las
peticiones
del
agente
Comprador
BuscadorBehaviourResponder
responder
=
new
BuscadorBehaviourResponder(this,template);
@Override
/*
*
Se
ejecuta
al
finalizar
el
agente
*/
protected
void
takeDown()
{
super.takeDown();
//Elimina
la
entrada
de
las
páginas
amarillas
try
{
DFService.deregister(this);
}
catch
(FIPAException
fe)
{
fe.printStackTrace();
}
}
Clase
AgenteComprador
package
uoc.sma.agentes;
import
uoc.sma.behaviours.CompradorSuscribirBehaviourInitiator;
import
uoc.sma.behaviours.estrategias.CompradorHolandesaIncrementoDinamicoBehaviour;
import
uoc.sma.behaviours.estrategias.CompradorHolandesaNRondasBehaviour;
import
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour;
import
uoc.sma.datos.Subasta;
import
uoc.sma.estrategias.ApuestaUnicaIncrementoDinamicoCfgImpl;
import
uoc.sma.estrategias.ApuestaUnicaNRondasCfgImpl;
import
uoc.sma.estrategias.ICfgApuesta;
import
uoc.sma.estrategias.IncrementalCfgImpl;
import
jade.core.AID;
import
jade.core.behaviours.Behaviour;
import
jade.domain.FIPANames;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.lang.acl.UnreadableException;
import
jade.util.Logger;
/**
*
Agente
responsable
de:
*
‐Pujar
en
una
subasta
acorde
a
unos
parámetros
fijados
por
el
usuario
*
‐Admite
varias
estrategias:
*
Incremental:
partiendo
de
un
precio
mínimo
y
uno
máximo,
el
agente
realiza
pujas
-68/106-
*
a
un
intervalo
de
tiempos
fijado
por
el
usuario
incrementando
la
puja
en
*
una
cantidad
fija
estipulada
por
el
usuario.
*
Francotirador:
parte
de
un
precio
máximo
al
que
está
dispuesto
a
llegar
el
comprador
*
(precio
de
reserva)
y
realiza
un
puja
en
el
último
minuto
de
la
subasta
*
por
una
importe
comprendido
entre
la
puja
máxima
en
ese
momento
y
el
*
precio
de
reserva
del
comprador.
*
Primerapuja:
el
agente
hace
una
puja
instantanea
por
el
importe
señalado
por
el
comprador.
*
*
El
sistema
está
abierto
a
implementar
cualquier
otra
estrategia
sin
que
esto
implique
*
cambio
alguno
en
la
arquitectura
del
SMA.
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
AgenteComprador
extends
AgenteBase
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
Subasta
subasta;
//
Contiene
una
referencia
a
la
subasta
a
la
que
se
suscribirá
el
comprador
private
ICfgApuesta
estrategia;
private
AID
idBuscador=null;
public
ICfgApuesta
getEstrategia()
{
return
estrategia;
}
public
void
setEstrategia(ICfgApuesta
estrategiaComprador)
{
this.estrategia
=
estrategiaComprador;
}
public
Subasta
getSubasta()
{
return
subasta;
}
public
void
setSubasta(Subasta
subasta)
{
this.subasta
=
subasta;
}
@Override
protected
void
setup()
{
logger.setLevel(Logger.INFO);
//Comprueba
que
el
número
de
argumentos
pasados
en
la
creación
del
agente
sean
correctos
if
((getArguments()!=null)
&&
(getArguments().length>=2)){
setEstrategia((ICfgApuesta)getArguments()[1]);
}else{
logger.log(Logger.FINE,"El
agente
"+this.getLocalName()+"
no
dispone
de
ninguna
estrategia");
this.doDelete();
}
//
Localiza
al
Agente
Buscador
en
las
páginas
amarillas
DFAgentDescription[]
aBuscador
=
getAgentePaginasAmarillas("BUSCADOR");
if
(aBuscador
!=
null)
this.idBuscador
=
aBuscador[0].getName();
addSuscripcionBehaviour();
addEstrategiaBehaviour();
addBusquedaBehaviour();
testAgenteBuscador("iMac
25");
}
-69/106-
/**
*
Método
de
prueba
que
utiliza
al
aagente
buscador
para
localizar
subastas
*
activas
que
contenga
el
texto
pasado
como
parámetro
*
*
@param
cadenaBusqueda
*/
private
void
testAgenteBuscador(String
cadenaBusqueda)
{
if
(idBuscador!=null){
logger.log(Logger.FINE,this.getLocalName()
+"
verificando
el
funcionamiento
del
agente
buscador");
ACLMessage
mensaje
=
new
ACLMessage(ACLMessage.REQUEST);
mensaje.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
mensaje.setContent(cadenaBusqueda);
mensaje.addReceiver(idBuscador);
this.send(mensaje);
}else
logger.log(Logger.INFO,this.getLocalName()
+"
no
se
pudo
localizar
al
agente
buscador
en
páginas
amarillas");
}
/**
*
Añade
como
comportamiento
una
clase
interna
que,
a
su
vez,
añadirá
como
comportamiento
*
la
recepción
de
un
mensaje
de
tipo
INFORM
procedente
del
agente
buscador
*/
private
void
addBusquedaBehaviour()
{
addBehaviour(new
Behaviour(){
//Plantilla
para
responder
a
los
mensajes
tipo
INFORM
procedentes
del
agente
buscador
MessageTemplate
template
=
MessageTemplate.and(MessageTemplate
.MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST),
MessageTemplate.MatchPerformative(ACLMessage.INFORM));
public
void
action()
{
//Espera
un
mensaje
tipo
INFORM
ACLMessage
mensaje
=
receive(template);
if
(mensaje
!=
null)
{
try
{
if
(mensaje.getContentObject()!=null){
//Muestra
la
subasta
buscada
logger.log(Logger.INFO,"Agente
buscador:
subasta
localizada
"+(Subasta)
mensaje.getContentObject());
}else
logger.log(Logger.INFO,"
El
agente
buscador
no
ha
localizado
ninguna
subasta");
}
catch
(UnreadableException
e)
{
e.printStackTrace();
}
}else
{
block();
}
}
@Override
public
boolean
done()
{
return
false;
}
});
}
-70/106-
/**
*
Añade
como
comportamiento
una
clase
interna
que,
a
su
vez,
añadirá
como
comportamiento
*
la
estrategia
que
corresponda
al
recibir
un
mensaje
de
tipo
CFP
(simboliza
el
inicio
de
la
subasta)
*/
private
void
addEstrategiaBehaviour()
{
addBehaviour(new
Behaviour(){
//Plantilla
para
responder
a
los
mensajes
tipo
CFP
private
MessageTemplate
mt
=
MessageTemplate.MatchPerformative(ACLMessage.CFP);
public
void
action()
{
//Espera
un
mensaje
tipo
CFP
ACLMessage
cfp
=
receive(mt);
if
(cfp
!=
null)
{
//Cuando
recibe
el
mensaje
añade
el
comportamiento
que
coresponde
a
la
estrategia
de
compra
logger.log(Logger.FINE,myAgent.getLocalName()
+
"
:
RECIBE
:
CFP");
if
(estrategia
instanceof
ApuestaUnicaIncrementoDinamicoCfgImpl)
{
myAgent.addBehaviour(new
CompradorHolandesaIncrementoDinamicoBehaviour(myAgent,cfp));
}
if
(estrategia
instanceof
ApuestaUnicaNRondasCfgImpl)
{
myAgent.addBehaviour(new
CompradorHolandesaNRondasBehaviour(myAgent,cfp));
}
if
(estrategia
instanceof
IncrementalCfgImpl)
{
myAgent.addBehaviour(new
CompradorInglesaIncrementalBehaviour(myAgent,cfp));
}
}else
{
block();
}
}
@Override
public
boolean
done()
{
return
false;
}
});
}
/**
*
Añade
el
comportamiento
para
que
el
comprador
pueda
suscribirse
a
una
subasta
*
cuyo
ID
se
pasa
como
parámetro
en
la
creación
del
agente
*
*
Sigue
el
protocolo
FIPA‐Subscribe
*/
private
void
addSuscripcionBehaviour(){
//Se
crea
un
mensaje
de
tipo
SUBSCRIBE
y
se
asocia
al
protocolo
FIPA‐Subscribe.
ACLMessage
mensaje
=
new
ACLMessage(ACLMessage.SUBSCRIBE);
mensaje.setProtocol(FIPANames.InteractionProtocol.FIPA_SUBSCRIBE);
//Trabaja
con
el
primero
de
los
argumentos
de
creación
del
agente
//para
obtener
el
identificador
de
la
subasta
al
que
va
a
suscribirse
//el
agente
comprador
if
(getArguments()!=null){
setSubasta((Subasta)getArguments()[0]);
int
idSubasta
=
subasta.getIdSubasta();
//Pasa
en
el
mensaje
el
identificador
de
la
subasta
a
la
que
debe
suscribirse
mensaje.setContent(String.valueOf(idSubasta));
//La
subasta
a
la
que
se
suscribe
//Añade
el
comportamiento
this.addBehaviour(new
CompradorSuscribirBehaviourInitiator(this,
mensaje));
}else{
logger.log(Logger.FINE,"El
agente
"+this.getLocalName()+"
no
dispone
de
ninguna
subasta
a
la
que
suscribirse");
}
}
}
-71/106-
Clase
SubastadorBehaviour
package
uoc.sma.behaviours.estrategias;
import
java.io.IOException;
import
uoc.sma.behaviours.SubastadorTransaccionesBehaviourInitiator;
import
uoc.sma.datos.Transaccion;
import
jade.core.AID;
import
jade.core.Agent;
import
jade.domain.DFService;
import
jade.domain.FIPAException;
import
jade.domain.FIPANames;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.domain.FIPAAgentManagement.ServiceDescription;
import
jade.lang.acl.ACLMessage;
import
jade.proto.ContractNetInitiator;
@SuppressWarnings("serial")
public
class
SubastadorBehaviour
extends
ContractNetInitiator
{
public
SubastadorBehaviour(Agent
a,
ACLMessage
cfp)
{
super(a,
cfp);
}
/**
*
Envía
un
mensaje
al
agente
CasaSubastas
para
que
registre
la
transacción
*
*
@param
t
*
La
transacción
*
@param
idCasaSubastas
*
El
identificador
del
agente
CasaSubastas
*/
protected
void
registrarTransaccion(Transaccion
t,
AID
idCasaSubastas)
{
ACLMessage
msg
=
new
ACLMessage(ACLMessage.REQUEST);
msg.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
msg.addReceiver(idCasaSubastas);
try
{
msg.setContentObject(t);
}
catch
(IOException
e)
{
e.printStackTrace();
}
myAgent.addBehaviour(new
SubastadorTransaccionesBehaviourInitiator(myAgent,
msg));
}
/**
*
Obtiene
el
identificador
del
agente
CasaSubastas
de
las
páginas
amarillas
*
@return
*/
protected
DFAgentDescription[]
getCasaSubastas()
{
DFAgentDescription
template
=
new
DFAgentDescription();
DFAgentDescription[]
result
=
null;
ServiceDescription
sd
=
new
ServiceDescription();
sd.setType("CasaDeSubastas");
template.addServices(sd);
try
{
result
=
DFService.search(myAgent,
template);
}
catch
(FIPAException
fe)
{
fe.printStackTrace();
}
return
result;
}
}
-72/106-
Clase
SubastadorHolandesaBehaviour
package
uoc.sma.behaviours.estrategias;
import
java.util.Date;
import
java.util.Vector;
import
uoc.sma.agentes.AgenteSubastador;
import
uoc.sma.datos.Subasta;
import
uoc.sma.datos.Transaccion;
import
uoc.sma.estrategias.SubastaHolandesaImpl;
import
jade.core.AID;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.lang.acl.ACLMessage;
import
jade.util.Logger;
/**
*
Encapsula
el
comportamiento
de
un
agente
subastador
de
subasta
Holandesa
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
SubastadorHolandesaBehaviour
extends
SubastadorBehaviour
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AgenteSubastador
agente;
private
Subasta
s;
private
SubastaHolandesaImpl
estrategiaVendedor;
private
AID
idCasaSubastas;
private
double
decremento
=
15;
//
El
decremento
de
precio
que
se
aplicará
//
en
cada
ronda
private
int
contadorPujas
=
0;
private
boolean
finalSubasta
=
false;
private
boolean
inferiorReserva
=
false;
public
SubastadorHolandesaBehaviour(Agent
a,
ACLMessage
msg)
{
super(a,
msg);
logger.setLevel(Logger.INFO);
agente
=
(AgenteSubastador)
myAgent;
s
=
agente.getSubasta();
estrategiaVendedor
=
(SubastaHolandesaImpl)
agente
.getEstrategiaSubasta();
//
Localizar
al
Agente
de
Subastas
en
las
páginas
amarillas
DFAgentDescription[]
aCasaSubastas
=
getCasaSubastas();
if
(aCasaSubastas
!=
null)
this.idCasaSubastas
=
aCasaSubastas[0].getName();
}
@Override
/**
*
Prepara
el
mensaje
CFP
siguiente
*/
protected
Vector
prepareCfps(ACLMessage
cfp)
{
cfp
=
agente.addAgentsToMessage(cfp);
Vector
mensajes
=
new
Vector();
mensajes.add(cfp);
-73/106-
}
return
mensajes;
@Override
/**
*
Comprueba
si
es
necesaria
otra
ronda
y
la
inicia
si
es
preciso
*/
public
int
onEnd()
{
if
(finalSubasta
==
false)
{
ACLMessage
nextMsg
=
new
ACLMessage(ACLMessage.CFP);
nextMsg.setContent(String.valueOf(s.getPrecio()));
logger.log(Logger.INFO,
myAgent.getName()
+
":
Oferta
de
venta:"
+
s.getPrecio());
myAgent.addBehaviour(new
SubastadorHolandesaBehaviour(myAgent,
nextMsg));
}
}
return
super.onEnd();
/**
*
Gestiona
las
respuestas
de
todos
los
participantes
en
la
subasta
*/
protected
void
handleAllResponses(Vector
respuestas,
Vector
acceptances)
{
contadorPujas
=
0;
for
(ACLMessage
respuesta
:
(Vector<ACLMessage>)
respuestas)
{
//
Controlar
los
mensajes
de
tipo
REFUSE
(el
agente
no
puja)
if
(respuesta.getPerformative()
==
ACLMessage.REFUSE)
{
logger.log(Logger.FINE,
respuesta.getSender().getLocalName()
+
"
NO
PUJA");
}
//
Hay
una
puja
if
(contadorPujas
>
0)
{
finalSubasta
=
true;
logger.log(Logger.INFO,
"FIN
DE
SUBASTA");
//
Controla
los
mensajes
de
tipo
PROPOSE
(las
pujas)
}
else
if
(respuesta.getPerformative()
==
ACLMessage.PROPOSE)
{
++contadorPujas;
double
puja
=
Double.parseDouble(respuesta.getContent());
logger.log(Logger.FINE,
"Agente:"
+
respuesta.getSender().getLocalName()
+
"
Puja="
+
String.valueOf(puja));
registrarTransaccion(new
Transaccion(new
Date(),
s
.getIdSubasta(),
respuesta.getSender().getLocalName(),
Transaccion.PUJA,
puja),
idCasaSubastas);
//
Puja
ganadora
s.setPrecio(puja);
s.setMsgMejorOferta(respuesta);
break;
}
//
Enviar
ACCEPT
si
hay
un
ganador
if
(s.getMsgMejorOferta()
!=
null)
{
//
Establece
el
ganador
de
la
subasta
s.setGanador(s.getMsgMejorOferta().getSender());
logger.log(Logger.INFO,
"Ganador
de
la
subasta:"
+
s
+
"
el
comprador
"
+
s.getMsgMejorOferta().getSender().getLocalName()
+
"
con
una
puja
de
"
+
s.getPrecio());
registrarTransaccion(new
Transaccion(new
Date(),
s
.getIdSubasta(),
s.getMsgMejorOferta().getSender()
.getLocalName(),
Transaccion.FIN,
s.getPrecio()),
idCasaSubastas);
-74/106-
ACLMessage
accept
=
s.getMsgMejorOferta().createReply();
accept.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
accept.setContent(String.valueOf(s.getPrecio()));
acceptances.add(accept);
}
else
{
}
for
(ACLMessage
response
:
(Vector<ACLMessage>)
respuestas)
{
if
(s.getMsgMejorOferta()
!=
response)
{
ACLMessage
reject
=
response.createReply();
reject.setPerformative(ACLMessage.REJECT_PROPOSAL);
reject.setContent(String.valueOf(s.getPrecio()));
acceptances.add(reject);
}
}
}
}
//
En
caso
que
no
se
reciba
ninguna
respuesta
o
el
nuevo
precio
sea
//
inferior
al
de
reserva
//
se
da
por
finalizada
la
subasta
sin
ganador
if
(respuestas.size()
==
0
||
inferiorReserva)
{
logger.log(
Logger.INFO,"No
hay
ganador
de
la
subasta.
Se
ha
agotado
el
tiempo
máximo
de
espera
de
nuevas
pujas
o
el
vendedor
no
bajará
mas
el
precio");
for
(ACLMessage
response
:
(Vector<ACLMessage>)
respuestas)
{
ACLMessage
reject
=
response.createReply();
reject.setPerformative(ACLMessage.REJECT_PROPOSAL);
reject.setContent(String.valueOf(s.getPrecioReserva()));
acceptances.add(reject);
finalSubasta
=
true;
}
}
//
Recalcular
la
nueva
oferta
de
precio
por
parte
del
vendedor
double
nuevoPrecio
=
s.getPrecio()
‐
decremento;
if
(nuevoPrecio
>=
s.getPrecioReserva())
{
s.setPrecio(nuevoPrecio);
registrarTransaccion(new
Transaccion(new
Date(),
s
.getIdSubasta(),
myAgent.getLocalName(),
Transaccion.OFERTA,
s.getPrecio()),
idCasaSubastas);
}
else
inferiorReserva
=
true;
-75/106-
Clase
SubastadorInglesaBehaviour
package
uoc.sma.behaviours.estrategias;
import
java.util.Date;
import
java.util.Vector;
import
uoc.sma.agentes.AgenteSubastador;
import
uoc.sma.datos.Subasta;
import
uoc.sma.datos.Transaccion;
import
uoc.sma.estrategias.SubastaInglesaImpl;
import
jade.core.AID;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.lang.acl.ACLMessage;
import
jade.util.Logger;
/**
*
Encapsula
el
comportamiento
de
un
agente
subastador
de
subasta
inglesa
*
*
@author
Rodolfo
de
Benito
*
*/
public
class
SubastadorInglesaBehaviour
extends
SubastadorBehaviour
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AgenteSubastador
agente;
private
Subasta
s;
private
SubastaInglesaImpl
estrategiaVendedor;
private
AID
idCasaSubastas;
private
int
contadorPujas
=
0;
private
boolean
finalSubasta
=
false;
public
SubastadorInglesaBehaviour(Agent
a,
ACLMessage
msg)
{
super(a,
msg);
agente
=
(AgenteSubastador)
myAgent;
s
=
agente.getSubasta();
estrategiaVendedor
=
(SubastaInglesaImpl)
agente.getEstrategiaSubasta();
//
Localizar
al
Agente
de
Subastas
en
las
páginas
amarillas
DFAgentDescription[]
aCasaSubastas
=
getCasaSubastas();
if
(aCasaSubastas
!=
null)
this.idCasaSubastas
=
aCasaSubastas[0].getName();
}
@Override
/**
*
Prepara
el
mensaje
CFP
siguiente
*/
protected
Vector
prepareCfps(ACLMessage
cfp)
{
cfp
=
agente.addAgentsToMessage(cfp);
Vector
mensajes
=
new
Vector();
mensajes.add(cfp);
return
mensajes;
}
-76/106-
@Override
/**
*
Comprueba
si
es
necesaria
otra
ronda
y
la
inicia
si
es
preciso
*/
public
int
onEnd()
{
if
(finalSubasta
==
false)
{
ACLMessage
nextMsg
=
new
ACLMessage(ACLMessage.CFP);
nextMsg.setContent(String.valueOf(s.getPrecio()));
myAgent.addBehaviour(new
SubastadorInglesaBehaviour(myAgent,
nextMsg));
}
return
super.onEnd();
}
/**
*
Gestiona
las
respuestas
de
todos
los
participantes
en
la
subasta
*/
protected
void
handleAllResponses(Vector
respuestas,
Vector
acceptances)
{
ACLMessage
mejorOfertaMsg
=
null;
double
mejorPuja
=
0;
contadorPujas
=
0;
for
(ACLMessage
respuesta
:
(Vector<ACLMessage>)
respuestas)
{
//
Controlar
los
mensajes
de
tipo
REFUSE
(el
agente
no
puja)
if
(respuesta.getPerformative()
==
ACLMessage.REFUSE)
{
logger.log(Logger.FINE,
respuesta.getSender().getLocalName()
+
"
NO
PUJA");
//
Controla
los
mensajes
de
tipo
PROPOSE
(las
pujas)
}
else
if
(respuesta.getPerformative()
==
ACLMessage.PROPOSE)
{
++contadorPujas;
double
puja
=
Double.parseDouble(respuesta.getContent());
logger.log(Logger.FINE,
"Agente:"
+
respuesta.getSender().getLocalName()
+
"
Puja="
+
String.valueOf(puja));
registrarTransaccion(new
Transaccion(new
Date(),
s
.getIdSubasta(),
respuesta.getSender().getLocalName(),
Transaccion.PUJA,
puja),
idCasaSubastas);
}
}
logger.log(Logger.INFO,
"Puja
más
alta
en
esta
ronda:
"
+
String.valueOf(mejorPuja));
if
(contadorPujas
==
0)
{
finalSubasta
=
true;
logger.log(Logger.FINE,
"No
hay
más
pujas");
//
Comprueba
si
es
la
mejor
puja
if
(puja
>
mejorPuja)
{
mejorPuja
=
puja;
s.setPrecio(mejorPuja);
mejorOfertaMsg
=
respuesta;
s.setMsgMejorOferta(mejorOfertaMsg);
}
//
Enviar
ACCEPT
si
hay
un
ganador
if
((s.getMsgMejorOferta())
!=
null
&&
(s.getPrecio()
>
s.getPrecioReserva()))
{
//
Establece
el
ganador
de
la
subasta
s.setGanador(s.getMsgMejorOferta().getSender());
logger.log(Logger.INFO,
"Ganador
de
la
subasta:"
+
s
+
"
el
comprador
"
+
s.getMsgMejorOferta().getSender().getLocalName()
+
"
con
una
puja
de
"
+
s.getPrecio());
-77/106-
}
registrarTransaccion(new
Transaccion(new
Date(),
s
.getIdSubasta(),
s.getMsgMejorOferta().getSender()
.getLocalName(),
Transaccion.FIN,
s.getPrecio()),
idCasaSubastas);
ACLMessage
accept
=
s.getMsgMejorOferta().createReply();
accept.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
accept.setContent(String.valueOf(s.getPrecio()));
acceptances.add(accept);
}
else
{
for
(ACLMessage
response
:
(Vector<ACLMessage>)
respuestas)
{
if
(s.getMsgMejorOferta()
!=
response)
{
ACLMessage
reject
=
response.createReply();
reject.setPerformative(ACLMessage.REJECT_PROPOSAL);
reject.setContent(String.valueOf(s.getPrecio()));
acceptances.add(reject);
}
}
}
}
}
}
logger.log(Logger.INFO,
"No
hay
ganador
de
la
subasta.
Las
pujas
no
superan
el
precio
de
reserva:
"
+
s.getPrecioReserva());
for
(ACLMessage
response
:
(Vector<ACLMessage>)
respuestas)
{
ACLMessage
reject
=
response.createReply();
reject.setPerformative(ACLMessage.REJECT_PROPOSAL);
reject.setContent(String.valueOf(s.getPrecioReserva()));
acceptances.add(reject);
-78/106-
Clase
CompradorInglesaIncrementalBehaviour
package
uoc.sma.behaviours.estrategias;
import
uoc.sma.agentes.AgenteComprador;
import
uoc.sma.estrategias.IncrementalCfgImpl;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.FailureException;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.proto.SSIteratedContractNetResponder;
import
jade.util.Logger;
/**
*
Estrategia
del
comprador
de
la
subasta
inglesa
en
la
que
el
agente
puja
a
*
intervalos
regulares
incrementando
la
puja
en
una
cantidad
preestablecida
al
*
crear
el
agente.
Se
puede
optar
por
una
de
estas
dos
formas
de
incrementar
la
*
puja:
*
*
Nueva
puja
=
puja
anterior
+
incremento.
Nueva
puja
=
puja
anterior
*
*
incremento.
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
CompradorInglesaIncrementalBehaviour
extends
SSIteratedContractNetResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AgenteComprador
agente;
private
IncrementalCfgImpl
estrategia;
private
double
puja
=
0;
private
int
contadorPujas
=
0;
public
CompradorInglesaIncrementalBehaviour(Agent
a,
ACLMessage
cfp)
{
super(a,
cfp);
logger.setLevel(Logger.INFO);
agente
=
(AgenteComprador)
a;
estrategia
=
(IncrementalCfgImpl)
agente.getEstrategia();
}
@Override
/**
*
Trata
los
mensajes
Call
For
Proposal
procedentes
del
comprador
con
la
*
puja
actual
de
la
subasta
*
*
En
este
método
decide
si
pujar
o
no
y
el
importe
de
la
puja,
enviando
un
*
mensaje
de
propuesta
(si
puja)
o
de
rechazo
(si
no
puja)
*
*/
protected
ACLMessage
handleCfp(ACLMessage
cfp)
throws
RefuseException,
FailureException,
NotUnderstoodException
{
ACLMessage
firstPropose
=
cfp.createReply();
puja
=
obtenerPuja(Double.parseDouble(cfp.getContent()));
if
((pujaAceptable(puja))
&&
(puja
>
Double.parseDouble(cfp.getContent())))
{
//
La
puja
no
sobrepasa
el
precio
de
reserva
del
comprador
-79/106-
}
//
y
además
es
mayor
que
la
puja
actual.
Se
propone
una
puja
firstPropose.setPerformative(ACLMessage.PROPOSE);
logger.log(Logger.INFO,
myAgent.getLocalName()
+
"
:
ENVIA
:
PROPOSE
:
"
+
puja);
firstPropose.setContent(String.valueOf(puja));
estrategia.setPuja(puja);
++contadorPujas;
}
else
{
//
No
puja
firstPropose.setPerformative(ACLMessage.REFUSE);
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
ENVIA
:
REFUSE
:
"
+
cfp.getContent());
}
return
firstPropose;
@Override
protected
void
handleRejectProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
reject)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Recibe
:
REJECT");
}
if
(reject
==
null)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Responder
:
TIMEOUT");
}
@Override
/**
*
Trata
los
mensajes
de
aceptación
de
propuesta
de
puja
procedentes
del
*
subastador
En
caso
de
recibir
un
mensaje
de
aceptación
indica
que
la
puja
*
del
agente
es
la
ganadora
de
la
subasta
y
se
envía
un
mensaje
INFORM
al
*
agente
subastador
confirmando
en
importe
de
la
puja
ganadora
*/
protected
ACLMessage
handleAcceptProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
accept)
throws
FailureException
{
logger.log(Logger.FINE,
myAgent.getName()
+
"
:
Recibe
:
ACCEPT");
if
(accept
!=
null)
{
ACLMessage
inform
=
accept.createReply();
inform.setPerformative(ACLMessage.INFORM);
inform.setContent(String.valueOf(estrategia.getPuja()));
}
else
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Envía
:
INFORM
:
"
+
puja);
return
inform;
}
}
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Envía
:
REFUSE");
return
refuse;
ACLMessage
refuse
=
cfp.createReply();
refuse.setPerformative(ACLMessage.REFUSE);
refuse.setContent(String.valueOf(estrategia.getPuja()));
-80/106-
}
/**
*
Calcula
la
puja
que
ofertará
el
comprador
*
*
@return
El
valor
de
la
puja
*/
private
double
obtenerPuja(Double
pujaActual)
{
double
incremento
=
estrategia.getIncremento();
int
tipoIncremento
=
estrategia.getTipoIncemento();
double
puja
=
estrategia.getPuja();
while
(puja
<
pujaActual)
{
if
(tipoIncremento
==
0)
{
puja
=
puja
+
incremento;
}
else
{
puja
=
Math.round(puja
*
incremento);
}
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
Calculando
nueva
puja:"
+
puja);
}
return
puja;
}
/**
*
Comprueba
si
la
puja
es
aceptable
en
base
a
la
estrategia
del
comprador
y
*
su
precio
de
reserva
*
*
@param
puja
*
El
importe
de
la
puja
*
@return
true
si
la
puja
es
aceptable
y
fase
en
caso
contrario
*/
private
boolean
pujaAceptable(double
puja)
{
return
((puja
<
estrategia.getReserva())
&&
((puja
>
estrategia
.getPuja())
||
(contadorPujas
==
0)));
}
-81/106-
Clase
CompradorHolandesaNRondasBehaviour
package
uoc.sma.behaviours.estrategias;
import
uoc.sma.agentes.AgenteComprador;
import
uoc.sma.estrategias.ApuestaUnicaNRondasCfgImpl;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.FailureException;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.proto.SSIteratedContractNetResponder;
import
jade.util.Logger;
/**
*
Estrategia
del
comprador
de
la
subasta
holandesa
en
la
que
al
principio
el
*
agente
considera
pujar
en
la
subasta
por
el
precio
configurado
en
su
atributo
*
Puja.
Si
en
el
transcurso
de
la
subasta
se
supera
el
número
de
rondas
*
configurado
en
la
estrategia
entonces
el
valor
de
aceptación
de
la
puja
será
*
el
de
su
precio
de
reserva.
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
CompradorHolandesaNRondasBehaviour
extends
SSIteratedContractNetResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AgenteComprador
agente;
private
ApuestaUnicaNRondasCfgImpl
estrategia;
private
double
puja
=
0;
public
CompradorHolandesaNRondasBehaviour(Agent
a,
ACLMessage
cfp)
{
super(a,
cfp);
logger.setLevel(Logger.INFO);
agente
=
(AgenteComprador)
a;
estrategia
=
(ApuestaUnicaNRondasCfgImpl)
agente.getEstrategia();
}
@Override
/**
*
Trata
las
propuestas
de
compra
del
subastastador
y
envía
un
mensaje
*
PROPOSE
en
caso
que
acepte
la
oferta
de
venta
o
un
mensaje
REFUSE
si
*
rechaza
la
oferta
*/
protected
ACLMessage
handleCfp(ACLMessage
cfp)
throws
RefuseException,
FailureException,
NotUnderstoodException
{
ACLMessage
firstPropose
=
cfp.createReply();
estrategia.setContadorRondas(estrategia.getContadorRondas()
+
1);
puja
=
Double.parseDouble(cfp.getContent());
if
(pujaAceptable(puja))
{
//
Se
acepta
la
puja
firstPropose.setPerformative(ACLMessage.PROPOSE);
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
ENVIA
:
PROPOSE
:
"
+
puja);
firstPropose.setContent(String.valueOf(puja));
-82/106-
}
}
else
{
//
No
puja
firstPropose.setPerformative(ACLMessage.REFUSE);
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
ENVIA
:
REFUSE
:
"
+
cfp.getContent());
}
return
firstPropose;
@Override
/**
*
Trata
los
mensajes
de
rechazo
sobre
una
propuesta
enviada
al
comprador
*/
protected
void
handleRejectProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
reject)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Recibe
:
REJECT");
if
(reject
==
null)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Responder
:
TIMEOUT");
}
}
@Override
/**
*
Trata
los
mensajes
de
aceptación
de
una
propuesta
de
compra
por
parte
del
*
comprador.
*
*
Envía
un
mensaje
INFORM
cuando
el
subastador
acepta
la
propuesta
de
*
compra.
*
*/
protected
ACLMessage
handleAcceptProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
accept)
throws
FailureException
{
logger.log(Logger.FINE,
myAgent.getName()
+
"
:
Recibe
:
ACCEPT");
if
(accept
!=
null)
{
ACLMessage
inform
=
accept.createReply();
inform.setPerformative(ACLMessage.INFORM);
inform.setContent(String.valueOf(estrategia.getPuja()));
}
else
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Envía
:
INFORM
:
"
+
puja);
return
inform;
}
}
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Envía
:
REFUSE");
return
refuse;
ACLMessage
refuse
=
cfp.createReply();
refuse.setPerformative(ACLMessage.REFUSE);
refuse.setContent(String.valueOf(estrategia.getPuja()));
/**
*
Comprueba
si
la
puja
propuesta
por
el
agente
comprador
es
aceptable
y
si
*
el
número
de
rondas
es
mayor
o
igual
que
el
establecido
entonces
*
incrementa
el
valor
de
la
puja
aceptable
*
*
@param
puja
*
El
precio
propuesto
por
el
agente
vendedor
*
@return
*/
private
boolean
pujaAceptable(double
puja)
{
if
(puja
<=
estrategia.getPuja())
-83/106-
}
}
return
true;
if
(estrategia.getContadorRondas()
>=
estrategia.getRondas()
&&
estrategia.getReserva()
!=
estrategia.getPuja())
{
//
Transcurridas
n
rodas
se
iguala
la
puja
al
precio
de
reserva
estrategia.setPuja(estrategia.getReserva());
logger.log(
Logger.FINE,
myAgent.getLocalName()
+
":
se
iguala
el
valor
de
la
nueva
puja
aceptable
al
de
la
reserva:"
+
estrategia.getReserva());
return
false;
}
else
return
false;
//No
interesa
pujar
Clase
CompradorHolandesaIncrementoDinamicoBehaviour
package
uoc.sma.behaviours.estrategias;
import
uoc.sma.agentes.AgenteComprador;
import
uoc.sma.estrategias.ApuestaUnicaIncrementoDinamicoCfgImpl;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.FailureException;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.proto.SSIteratedContractNetResponder;
import
jade.util.Logger;
/**
*
Estrategia
del
comprador
de
la
subasta
holandesa
en
la
que
en
principio
el
*
agente
considera
pujar
en
la
subasta
por
el
precio
configurado
en
su
atributo
*
Puja.
Si
se
supera
el
número
de
rondas
preestablecido
en
la
estrategia
*
entonces
incrementará
el
valor
de
aceptación
de
la
puja
en
una
cantidad
fija
*
siempre
y
cuando
no
llegue
al
precio
de
reserva.
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
CompradorHolandesaIncrementoDinamicoBehaviour
extends
SSIteratedContractNetResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AgenteComprador
agente;
private
ApuestaUnicaIncrementoDinamicoCfgImpl
estrategia;
private
double
puja
=
0;
public
CompradorHolandesaIncrementoDinamicoBehaviour(Agent
a,
ACLMessage
cfp)
{
super(a,
cfp);
logger.setLevel(Logger.INFO);
agente
=
(AgenteComprador)
a;
estrategia
=
(ApuestaUnicaIncrementoDinamicoCfgImpl)
agente
.getEstrategia();
}
-84/106-
@Override
/**
*
Trata
las
propuestas
de
compra
del
subastastador
y
envía
un
mensaje
*
PROPOSE
en
caso
que
acepte
la
oferta
de
venta
o
un
mensaje
REFUSE
si
*
rechaza
la
oferta
*/
protected
ACLMessage
handleCfp(ACLMessage
cfp)
throws
RefuseException,
FailureException,
NotUnderstoodException
{
ACLMessage
firstPropose
=
cfp.createReply();
estrategia.setContadorRondas(estrategia.getContadorRondas()
+
1);
puja
=
Double.parseDouble(cfp.getContent());
if
(pujaAceptable(puja))
{
//
Se
acepta
la
puja
firstPropose.setPerformative(ACLMessage.PROPOSE);
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
ENVIA
:
PROPOSE
:
"
+
puja);
firstPropose.setContent(String.valueOf(puja));
}
}
else
{
//
No
puja
firstPropose.setPerformative(ACLMessage.REFUSE);
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
ENVIA
:
REFUSE
:
"
+
cfp.getContent());
}
return
firstPropose;
@Override
/**
*
Trata
los
mensajes
de
rechazo
sobre
una
propuesta
enviada
al
comprador
*/
protected
void
handleRejectProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
reject)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Recibe
:
REJECT");
if
(reject
==
null)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Responder
:
TIMEOUT");
}
}
@Override
/**
*
Trata
los
mensajes
de
aceptación
de
una
propuesta
de
compra
por
parte
del
*
comprador.
*
*
Envía
un
mensaje
INFORM
cuando
el
subastador
acepta
la
propuesta
de
*
compra.
*
*/
protected
ACLMessage
handleAcceptProposal(ACLMessage
cfp,
ACLMessage
propose,
ACLMessage
accept)
throws
FailureException
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Recibe
:
ACCEPT");
if
(accept
!=
null)
{
ACLMessage
inform
=
accept.createReply();
inform.setPerformative(ACLMessage.INFORM);
inform.setContent(String.valueOf(estrategia.getPuja()));
}
else
{
logger.log(Logger.FINE,
myAgent.getName()
+
"
:
Envía
:
INFORM
:
"
+
puja);
return
inform;
-85/106-
}
ACLMessage
refuse
=
cfp.createReply();
refuse.setPerformative(ACLMessage.REFUSE);
refuse.setContent(String.valueOf(estrategia.getPuja()));
}
}
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
:
Envía
:
REFUSE");
return
refuse;
/**
*
Comprueba
si
la
puja
propuesta
por
el
agente
comprador
es
aceptable
y
si
*
el
número
de
rondas
es
mayor
o
igual
que
el
establecido
entonces
*
incrementa
el
valor
de
la
puja
aceptable
*
*
@param
puja
*
El
precio
propuesto
por
el
agente
vendedor
*
@return
*/
private
boolean
pujaAceptable(double
puja)
{
if
(puja
<=
estrategia.getPuja())
return
true;
if
(estrategia.getContadorRondas()
>=
estrategia.getRondas())
{
if
((estrategia.getPuja()
+
estrategia.getIncremento())
>
estrategia
.getReserva())
{
//
La
nueva
puja
aceptable
supera
el
precio
de
reserva
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
el
valor
de
la
nueva
puja
aceptable
"
+
(estrategia.getPuja()
+
estrategia.getIncremento())
+
"
supera
la
reserva
"
+
estrategia.getReserva());
return
false;
}
else
{
//
Calcula
la
puja
aceptable
para
la
nueva
ronda
estrategia.setPuja(estrategia.getPuja()
+
estrategia.getIncremento());
logger.log(
Logger.FINE,
myAgent.getLocalName()
+
":
recalculando
el
valor
de
la
nueva
puja
aceptable
a:"
+
estrategia.getPuja()
+
estrategia.getIncremento());
return
false;
}
}
else
return
false;
//No
interesa
pujar
}
-86/106-
Clase
BuscadorBehaviourInitiator
package
uoc.sma.behaviours;
import
java.io.IOException;
import
java.util.Vector;
import
uoc.sma.datos.Subasta;
import
jade.core.AID;
import
jade.core.Agent;
import
jade.domain.DFService;
import
jade.domain.FIPAException;
import
jade.domain.FIPANames;
import
jade.domain.FIPAAgentManagement.DFAgentDescription;
import
jade.domain.FIPAAgentManagement.ServiceDescription;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.UnreadableException;
import
jade.proto.AchieveREInitiator;
import
jade.proto.AchieveREResponder;
import
jade.util.Logger;
/**
*
Comportamiento
del
Agente
buscador.
Forma
parte
del
protocolo
FIPA‐Brokering
*
*
Recibe:
*
‐Mensajes
del
Agente
CasaSubastas
*
que
contienen
el
resultado
de
la
búsqueda
*
*
Envía:
*
‐Mensajes
de
petición
al
Agente
CasaSubastas
*
solicitando
una
búsqueda
de
subastas
*
*
‐Mensajes
de
respuesta
al
Agente
Comprador
*
con
el
resultado
de
la
búsqueda
*
*
@author
Rodofo
de
Benito
*
*/
public
class
BuscadorBehaviourInitiator
extends
AchieveREInitiator
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
private
AID
idCasaSubastas;
public
BuscadorBehaviourInitiator(Agent
a,
ACLMessage
mt)
{
super(a,
mt);
logger.setLevel(Logger.INFO);
//
Localizar
al
Agente
de
Subastas
en
las
páginas
amarillas
DFAgentDescription[]
aCasaSubastas
=
getCasaSubastas();
if
(aCasaSubastas
!=
null)
this.idCasaSubastas
=
aCasaSubastas[0].getName();
}
/**
*
Construye
la
pregunta
al
Agente
CasaSubastas
en
base
a
la
*
pregunta
del
Agente
Comprador
*/
protected
Vector
prepareRequests(ACLMessage
request)
{
//
Recupera
la
petición
entrante
del
DataStore
String
clavePeticionEntrada
=
(String)
((AchieveREResponder)
parent).REQUEST_KEY;
ACLMessage
peticionEntrada
=
(ACLMessage)
getDataStore().get(clavePeticionEntrada);
-87/106-
}
//
Prepara
la
petición
para
enviarsela
al
Agente
CasaSubastas
logger.log(Logger.FINE,"Agente
"
+
myAgent.getLocalName()
+
":
Redirigiendo
the
petición
a
"
+
idCasaSubastas.getName());
ACLMessage
peticionSalida
=
new
ACLMessage(ACLMessage.QUERY_REF);
peticionSalida.setProtocol(FIPANames.InteractionProtocol.FIPA_QUERY);
peticionSalida.addReceiver(idCasaSubastas);
peticionSalida.setContent(peticionEntrada.getContent());
peticionSalida.setReplyByDate(peticionEntrada.getReplyByDate());
Vector
v
=
new
Vector(1);
v.addElement(peticionSalida);
return
v;
protected
void
handleInform(ACLMessage
inform)
{
guardarMensaje(ACLMessage.INFORM);
}
protected
void
handleRefuse(ACLMessage
refuse)
{
guardarMensaje(ACLMessage.FAILURE);
}
protected
void
handleNotUnderstood(ACLMessage
notUnderstood)
{
guardarMensaje(ACLMessage.FAILURE);
}
protected
void
handleFailure(ACLMessage
failure)
{
guardarMensaje(ACLMessage.FAILURE);
}
protected
void
handleAllResultNotifications(Vector
notificaciones)
{
if
(notificaciones.size()
==
0)
{
//
Timeout
guardarMensaje(ACLMessage.FAILURE);
}
}
/**
*
Trata
los
mensajes
recibidos
y
gestiona
el
Datastore
*
para
recuperar
los
mensajes
recibidos
y
almacenar
*
mensajes
de
respuesta
*
*
@param
performative
*/
private
void
guardarMensaje(int
performative)
{
Subasta
subasta=null;
if
(performative
==
ACLMessage.INFORM)
{
logger.log(Logger.INFO,"Agente
"
+
myAgent.getLocalName()
+
":
Redirección
conseguida");
}
else
{
logger.log(Logger.INFO,"Agente
"
+
myAgent.getLocalName()
+
":
Fallo
en
la
redirección
");
}
//
Recupera
la
petición
entrante
del
DataStore.
El
mensaje
del
agente
comprador
String
clavePeticionEntrada
=
(String)
((AchieveREResponder)
parent).REQUEST_KEY;
ACLMessage
peticionEntrada
=
(ACLMessage)
getDataStore().get(clavePeticionEntrada);
//Recupera
del
DataStore
la
respuesta
del
agente
CasaDeSubastas
ACLMessage
respuestaCasaSubastas
=
(ACLMessage)
getDataStore().get(REPLY_KEY);
//
Prepara
el
mensaje
para
el
Agente
Comprador
y
la
almacena
en
el
DataStore
ACLMessage
mensaje
=
peticionEntrada.createReply();
mensaje.setPerformative(performative);
try
{
if
(respuestaCasaSubastas.getContentObject()!=null)
{
-88/106-
}
}
subasta
=
(Subasta)
respuestaCasaSubastas.getContentObject();
mensaje.setContentObject(subasta);
}
}
catch
(IOException
e)
{
e.printStackTrace();
}
catch
(UnreadableException
e)
{
e.printStackTrace();
}
String
notificationkey
=
(String)
((AchieveREResponder)
parent).RESULT_NOTIFICATION_KEY;
getDataStore().put(notificationkey,
mensaje);
/**
*
Localiza
al
agente
CasaSubastas
en
las
páginas
amarillas
*
@return
*/
private
DFAgentDescription[]
getCasaSubastas()
{
DFAgentDescription
template
=
new
DFAgentDescription();
DFAgentDescription[]
result
=
null;
ServiceDescription
sd
=
new
ServiceDescription();
sd.setType("CasaDeSubastas");
template.addServices(sd);
try
{
result
=
DFService.search(myAgent,
template);
}
catch
(FIPAException
fe)
{
fe.printStackTrace();
}
return
result;
}
-89/106-
Clase
CompradorSuscribirBehaviourInitiator
package
uoc.sma.behaviours;
import
java.util.Vector;
import
uoc.sma.agentes.AgenteComprador;
import
jade.core.AID;
import
jade.core.Agent;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.proto.SubscriptionInitiator;
import
jade.util.Logger;
@SuppressWarnings("serial")
/**
*
Clase
que
modela
el
comportamiento
del
comprador
como
suscriptor
*
de
una
subasta.
*
*
Sigue
el
protocolo
FIPA‐Subscription
con
el
rol
de
Initiator
*
*/
public
class
CompradorSuscribirBehaviourInitiator
extends
SubscriptionInitiator
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
public
CompradorSuscribirBehaviourInitiator(Agent
agente,
ACLMessage
mensaje)
{
super(agente,
mensaje);
logger.setLevel(Logger.INFO);
}
@Override
/*
*
Se
encarga
de
crear
el
mensaje
de
suscripción
para
un
subastador
*
determinado
y
una
subasta
concreta
*/
protected
Vector
prepareSubscriptions(ACLMessage
subscription)
{
subscription.addReceiver(((AgenteComprador)
myAgent).getSubasta()
.getAgenteSubastador());
//
El
identificador
del
subastador
subscription.setContent(String.valueOf(((AgenteComprador)
myAgent)
.getSubasta().getIdSubasta()));
//El
id
de
la
subasta
a
la
que
se
suscribe
logger.log(Logger.FINE,
"Agente
"
+
myAgent.getLocalName()
+
":
Creando
mensaje
de
suscripcion
"
+
subscription);
return
super.prepareSubscriptions(subscription);
}
protected
void
handleAgree(ACLMessage
inform)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
Solicitud
aceptada.");
}
protected
void
handleRefuse(ACLMessage
inform)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
Solicitud
rechazada.");
}
protected
void
handleInform(ACLMessage
inform)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
Informe
recibido:
"
+
inform.getContent()
+
"\n");
}
-90/106-
}
protected
void
handleFailure(ACLMessage
failure)
{
//Se
comprueba
si
el
fallo
viene
del
AMS
o
de
otro
agente.
if
(failure.getSender().equals(myAgent.getAMS()))
{
logger.log(Logger.INFO,
myAgent.getLocalName()
+
":
El
agente
no
existe.");
}
else
{
logger.log(Logger.INFO,
myAgent.getLocalName()
+
":
El
agente
"
+
failure.getSender().getName()
+
"
falló
al
intentar
realizar
la
acción
solicitada.\n");
}
}
public
void
cancellationCompleted(AID
agente)
{
//Se
crea
una
plantilla
para
solo
recibir
los
mensajes
del
agente
que
va
a
cancelar
la
suscripción
MessageTemplate
template
=
MessageTemplate.MatchSender(agente);
ACLMessage
msg
=
myAgent.blockingReceive(template);
}
//Se
comprueba
que
tipo
de
mensaje
llega:
INFORM
o
FAILURE
if
(msg.getPerformative()
==
ACLMessage.INFORM)
logger.log(Logger.INFO,
myAgent.getLocalName()
+
":
Suscripcion
cancelada
con
el
agente
"
+
agente.getLocalName()
+
"\n");
else
logger.log(
Logger.INFO,
myAgent.getLocalName()
+
":
Se
ha
producido
un
fallo
en
la
cancelación
con
el
agente
"
+
agente.getLocalName()
+
"\n");
Clase
SubastadorTransaccionesBehaviourInitiator
package
uoc.sma.behaviours;
import
jade.core.Agent;
import
jade.lang.acl.ACLMessage;
import
jade.proto.AchieveREInitiator;
/**
*
Comportamiento
del
Agente
buscador
*
implementa
FIPA‐Query
*
*
Se
utiliza
para
enviar
la
transacción
que
debe
registrar
el
agente
CasSubastas
*
*
*
@author
Rodofo
de
Benito
*/
public
class
SubastadorTransaccionesBehaviourInitiator
extends
AchieveREInitiator
{
public
SubastadorTransaccionesBehaviourInitiator(Agent
a,
ACLMessage
mt)
{
super(a,
mt);
}
}
-91/106-
Clase
BuscadorBehaviourResponder
package
uoc.sma.behaviours;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.proto.AchieveREResponder;
import
jade.util.Logger;
/**
*
Comportamiento
del
Agente
buscador
que
forma
parte
del
protocolo
FIPA‐Brokering
*
*
Envía:
*
‐Mensajes
de
respuesta
AGREE
al
Agente
Comprador
cuando
recibe
una
*
petición
de
búsqueda
*
*
*
@author
Rodofo
de
Benito
*
*/
public
class
BuscadorBehaviourResponder
extends
AchieveREResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
public
BuscadorBehaviourResponder(Agent
a,
MessageTemplate
mt)
{
super(a,
mt);
logger.setLevel(Logger.INFO);
}
protected
ACLMessage
prepareResponse(ACLMessage
request)
throws
NotUnderstoodException,
RefuseException
{
logger.log(Logger.FINE,"Agente
"
+
myAgent.getLocalName()
+
":
Petición
recibida
de
"
+
request.getSender().getName()
+
".
La
acción
es
"
+
request.getContent());
ACLMessage
agree
=
request.createReply();
agree.setPerformative(ACLMessage.AGREE);
return
agree;
}
}
-92/106-
Clase
CasaSubastasBusquedasBehaviourResponder
package
uoc.sma.behaviours;
import
java.io.IOException;
import
uoc.sma.agentes.AgenteCasaSubastas;
import
uoc.sma.datos.Subasta;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.FailureException;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.proto.AchieveREResponder;
import
jade.util.Logger;
/**
*
Comportamiento
del
Agente
CasaSubastas
que
se
encarga
de
responder
a
la
*
petición
de
búsquedas
de
subastas
del
Agente
Buscador
*
*
Implementa
FIPa‐Query
con
el
rol
de
Participant
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
CasaSubastasBusquedasBehaviourResponder
extends
AchieveREResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
public
CasaSubastasBusquedasBehaviourResponder(Agent
a,
MessageTemplate
mt)
{
super(a,
mt);
logger.setLevel(Logger.FINE);
}
/**
*
Prepara
el
mensaje
de
respuesta
al
agente
buscador
confirmando
que
ha
*
recibido
la
petición
de
búsqueda
*/
protected
ACLMessage
prepareResponse(ACLMessage
request)
throws
NotUnderstoodException,
RefuseException
{
logger.log(Logger.FINE,
"Agente
"
+
myAgent.getLocalName()
+
":
Petición
recibida
de
"
+
request.getSender().getName()
+
".
Acción
es
"
+
request.getContent());
logger.log(Logger.FINE,
"Agente
"
+
myAgent.getLocalName()
+
":
Agree");
ACLMessage
agree
=
request.createReply();
agree.setPerformative(ACLMessage.AGREE);
return
agree;
}
/**
*
Prepara
el
mensage
de
respuesta
al
agente
buscador
con
el
resultado
de
la
*
búsqueda
*/
protected
ACLMessage
prepareResultNotification(ACLMessage
request,
ACLMessage
response)
throws
FailureException
{
logger.log(Logger.FINE,
"Agente
"
+
myAgent.getLocalName()
+
":
Búsqueda
realizada
satisfactoriamente");
Subasta
s
=
((AgenteCasaSubastas)
myAgent).getSubasta(request
.getContent().toUpperCase());
-93/106-
}
}
ACLMessage
inform
=
request.createReply();
inform.setPerformative(ACLMessage.INFORM);
try
{
inform.setContentObject(s);
}
catch
(IOException
e)
{
e.printStackTrace();
}
return
inform;
Clase
SubastadorSuscribirBehaviourResponder
package
uoc.sma.behaviours;
import
uoc.sma.agentes.AgenteSubastador;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.proto.SubscriptionResponder;
import
jade.util.Logger;
/**
*
Procesa
los
mensajes
relacionados
con
la
suscripción
de
Agentes
Compradores
a
una
subasta
*
*
Implementa
el
protocolo
FIPA‐Subscribe
con
el
rol
de
Participant
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
SubastadorSuscribirBehaviourResponder
extends
SubscriptionResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
public
SubastadorSuscribirBehaviourResponder(Agent
a,
MessageTemplate
mt,
SubscriptionManager
sm)
{
super(a,
mt,
sm);
logger.setLevel(Logger.INFO);
}
private
Subscription
suscripcion;
/**
*
Método
que
gestiona
la
suscripcion
aceptando/rechazando
las
*
propuestas
de
suscripción
a
la
subasta
*/
protected
ACLMessage
handleSubscription(ACLMessage
propuesta)
throws
NotUnderstoodException
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
SUSCRIBE
recibido
de
"
+
propuesta.getSender().getLocalName()
+
"\n");
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"
La
propuesta
es
suscribirse
a
la
subastas
Id:"
+
myAgent.getLocalName(),
propuesta.getContent()
+
"\n");
//Comprueba
los
datos
de
la
propuesta
if
(((AgenteSubastador)
myAgent).compruebaMensaje(propuesta
.getContent()))
{
//Crea
la
suscripcion
this.suscripcion
=
this.createSubscription(propuesta);
-94/106-
}
try
{
//El
SubscriptionManager
registra
la
suscripcion
this.mySubscriptionManager.register(suscripcion);
}
catch
(Exception
e)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
Error
en
el
registro
de
la
suscripción.");
}
}
}
else
{
}
//Acepta
la
propuesta
y
la
envía
ACLMessage
agree
=
propuesta.createReply();
agree.setPerformative(ACLMessage.AGREE);
return
agree;
//Rechaza
la
propuesta
y
la
envía
logger.log(Logger.FINE,
myAgent.getLocalName()
+
":
Rechaza
la
propuesta
de
suscripción.");
ACLMessage
refuse
=
propuesta.createReply();
refuse.setPerformative(ACLMessage.REFUSE);
return
refuse;
/**
*
Gestiona
la
cancelación
de
la
subasta
*/
protected
ACLMessage
handleCancel(ACLMessage
cancelacion)
{
logger.log(Logger.FINE,
myAgent.getLocalName()
+
"%s:
CANCEL
recibido
de
"
+
cancelacion.getSender().getLocalName()
+
"\n");
try
{
//El
SubscriptionManager
elimina
del
registro
la
suscripcion
this.mySubscriptionManager.deregister(this.suscripcion);
}
catch
(Exception
e)
{
logger.log(
Logger.FINE,
myAgent.getLocalName()
+
":
Error
en
la
operación
de
anluar
la
suscripción
de
la
suscripción.");
}
}
//Acepta
la
cancelación
y
responde
ACLMessage
cancela
=
cancelacion.createReply();
cancela.setPerformative(ACLMessage.INFORM);
return
cancela;
-95/106-
Clase
CasaSubastasTransaccionesBehaviourResponder
package
uoc.sma.behaviours;
import
uoc.sma.agentes.AgenteCasaSubastas;
import
uoc.sma.datos.Transaccion;
import
jade.core.Agent;
import
jade.domain.FIPAAgentManagement.NotUnderstoodException;
import
jade.domain.FIPAAgentManagement.RefuseException;
import
jade.lang.acl.ACLMessage;
import
jade.lang.acl.MessageTemplate;
import
jade.lang.acl.UnreadableException;
import
jade.proto.AchieveREResponder;
import
jade.util.Logger;
/**
*
Comportamiento
del
Agente
CasaSubastas
que
se
encarga
de
atender
las
*
peticiones
de
insercción
de
una
transacción
en
el
historial
de
transacciones
*
*
Implementa
FIPA‐Query
con
el
rol
de
Participant
*
*
@author
Rodolfo
de
Benito
*
*/
@SuppressWarnings("serial")
public
class
CasaSubastasTransaccionesBehaviourResponder
extends
AchieveREResponder
{
private
final
Logger
logger
=
Logger.getMyLogger(this.getClass().getName());
public
CasaSubastasTransaccionesBehaviourResponder(Agent
a,
MessageTemplate
mt)
{
super(a,
mt);
logger.setLevel(Logger.INFO);
}
/**
*
Atiende
los
mensajes
de
petición
de
registro
de
una
trnasacción
*
procedentes
de
un
agente
subastador
*/
protected
ACLMessage
handleRequest(ACLMessage
request)
throws
NotUnderstoodException,
RefuseException
{
Transaccion
t
=
null;
try
{
t
=
(Transaccion)
request.getContentObject();
logger.log(Logger.FINE,"Agente
"
+
myAgent.getLocalName()
+
":
Petición
recibida
de
"
+
request.getSender().getName()
+
".
Transacción
"
+
t);
}
catch
(UnreadableException
e)
{
e.printStackTrace();
}
//
Registra
la
transacción
((AgenteCasaSubastas)
myAgent).addTransaccion(t);
logger.log(Logger.FINE,"Agente
"
+
myAgent.getLocalName()
+
":
Agree");
ACLMessage
agree
=
request.createReply();
agree.setPerformative(ACLMessage.AGREE);
return
agree;
}
}
-96/106-
Interface
ICfgApuesta
package
uoc.sma.estrategias;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
estrategia
que
seguirá
el
agente
comprador
*
*
La
finalidad
de
este
interface
es
ser
implementado
por
las
*
clases
que
representan
las
diferentes
estrategias
que
seguirá
*
el
agente
comprador.
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
public
interface
ICfgApuesta
{
/**
*
Establece
el
comportamiento
en
el
agente
comprador
*
que
se
le
pasa
como
referencia
*
*
@param
agente
*/
public
void
setComportamiento(Behaviour
comportamiento);
/**
*
Retorna
una
referencia
al
comportamiento
o
estrategia
que
*
seguirá
el
comprador
*
*
@return
*/
public
Behaviour
getComportamiento();
}
-97/106-
Interface
ICfgSubasta
package
uoc.sma.estrategias;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
estrategia
que
seguirá
el
agente
subastador
*
*
La
finalidad
de
este
interface
es
ser
implementado
por
las
*
clases
que
representan
los
tipos
de
subastas.
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
public
interface
ICfgSubasta
{
/**
*
Establece
el
comportamiento
en
el
agente
subastador
*
que
se
le
pasa
como
referencia
*
*
@param
agente
*/
public
void
setComportamiento(Behaviour
comportamiento);
/**
*
Retorna
una
referencia
al
comportamiento
o
estrategia
que
*
seguirá
el
subastador
*
*
@return
*/
public
Behaviour
getComportamiento();
}
Clase
IncrementalCfgImpl
package
uoc.sma.estrategias;
import
uoc.sma.behaviours.estrategias.CompradorInglesaIncrementalBehaviour;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
estrategia
de
una
puja
inicial
que
cada
cierto
tiempo
*
se
va
incrementando
en
una
cantidad
fija
sin
que
la
puja
llegue
a
*
superar
el
precio
de
reserva
marcado
por
el
comprador
*
*
@author
Rodolfo
de
Benito
*
*/
public
class
IncrementalCfgImpl
implements
ICfgApuesta{
public
final
int
INCREMENTOARITMETICO
=
0;
public
final
int
INCREMENTOGEOMETRICO
=
1;
private
int
tipoIncremento;
private
double
incremento;
//Incremento
de
la
puja
private
double
puja;
private
double
reserva;
//La
puja
máxima
a
la
que
llegará
el
agente
private
CompradorInglesaIncrementalBehaviour
comportamiento;
public
IncrementalCfgImpl(int
tipoIncemento,
double
incremento,
double
puja,
double
reserva)
{
-98/106-
}
super();
this.tipoIncremento
=
tipoIncemento;
this.incremento
=
incremento;
this.puja
=
puja;
this.reserva
=
reserva;
public
Behaviour
getComportamiento()
{
return
comportamiento;
}
public
void
setComportamiento(Behaviour
comportamiento)
{
this.comportamiento=(CompradorInglesaIncrementalBehaviour)comportamiento;
}
public
int
getTipoIncemento()
{
return
tipoIncremento;
}
public
void
setTipoIncemento(int
tipoIncemento)
{
this.tipoIncremento
=
tipoIncemento;
}
public
double
getIncremento()
{
return
incremento;
}
public
void
setIncremento(double
incremento)
{
this.incremento
=
incremento;
}
public
double
getPuja()
{
return
puja;
}
public
void
setPuja(double
puja)
{
this.puja
=
puja;
}
public
double
getReserva()
{
return
reserva;
}
public
void
setReserva(double
reserva)
{
this.reserva
=
reserva;
}
}
Clase
ApuestaUnicaNRondasCfgImpl
package
uoc.sma.estrategias;
import
uoc.sma.behaviours.estrategias.CompradorHolandesaNRondasBehaviour;
import
jade.core.behaviours.Behaviour;
-99/106-
/**
*
Encapsula
la
estrategia
de
una
única
puja
*
*
En
principio
el
agente
considera
pujar
en
la
subasta
por
el
precio
configurado
en
su
atributo
Puja
*
Si
se
supera
el
número
de
rondas
"Rondas"
entonces
el
valor
de
aceptación
de
la
puja
será
el
*
de
su
precio
de
reserva
*
*
@author
Rodolfo
de
Benito
*
*/
public
class
ApuestaUnicaNRondasCfgImpl
implements
ICfgApuesta
{
private
double
incremento;
//Incremento
del
valor
de
aceptación
de
la
puja
private
double
puja;
//Valor
de
aceptación
por
el
que
está
dispuesto
a
pujar
si
no
se
alcanza
el
número
de
rondas
estipulado
private
double
reserva;
//La
puja
máxima
a
la
que
llegará
el
agente
private
int
rondas;
//Número
de
rondas
que
esperará
para
subir
el
valor
de
aceptación
de
la
puja
private
int
contadorRondas;
//Contabiliza
el
número
de
rondas
que
lleva
un
comprador
en
una
subasta
private
CompradorHolandesaNRondasBehaviour
comportamiento;
public
ApuestaUnicaNRondasCfgImpl(double
incremento,
double
puja,
double
reserva,
int
rondas)
{
super();
this.incremento
=
incremento;
this.puja
=
puja;
this.reserva
=
reserva;
this.rondas=rondas;
this.contadorRondas=0;
}
public
Behaviour
getComportamiento()
{
return
comportamiento;
}
public
void
setComportamiento(Behaviour
comportamiento)
{
this.comportamiento=(CompradorHolandesaNRondasBehaviour)comportamiento;
}
public
int
getRondas()
{
return
rondas;
}
public
void
setRondas(int
rondas)
{
this.rondas
=
rondas;
}
public
double
getIncremento()
{
return
incremento;
}
public
void
setIncremento(double
incremento)
{
this.incremento
=
incremento;
}
public
double
getPuja()
{
return
puja;
}
public
void
setPuja(double
puja)
{
-100/106-
}
}
this.puja
=
puja;
public
double
getReserva()
{
return
reserva;
}
public
void
setReserva(double
reserva)
{
this.reserva
=
reserva;
}
public
int
getContadorRondas()
{
return
contadorRondas;
}
public
void
setContadorRondas(int
contadorRondas)
{
this.contadorRondas
=
contadorRondas;
}
Clase
ApuestaUnicaIncrementoDinamicoCfgImpl
package
uoc.sma.estrategias;
import
uoc.sma.behaviours.estrategias.CompradorHolandesaIncrementoDinamicoBehaviour;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
estrategia
de
una
única
puja
*
*
En
principio
el
agente
considera
pujar
en
la
subasta
por
el
precio
configurado
en
su
atributo
Puja
*
Si
se
supera
el
número
de
rondas
"Rondas"
entonces
incrementará
el
valor
de
aceptación
de
la
puja
*
siempre
y
cuando
no
llegue
al
precio
de
reserva
*
*
@author
Rodolfo
de
Benito
*
*/
public
class
ApuestaUnicaIncrementoDinamicoCfgImpl
implements
ICfgApuesta
{
private
double
incremento;
//Incremento
del
valor
de
aceptación
de
la
puja
private
double
puja;
//Valor
de
aceptación
por
el
que
está
dispuesto
a
pujar
si
no
se
alcanza
el
número
de
rondas
estipulado
private
double
reserva;
//La
puja
máxima
a
la
que
llegará
el
agente
private
int
rondas;
//Número
de
rondas
que
esperará
para
subir
el
valor
de
aceptación
de
la
puja
private
int
contadorRondas;
//Contabiliza
el
número
de
rondas
que
lleva
un
comprador
en
una
subasta
private
CompradorHolandesaIncrementoDinamicoBehaviour
comportamiento;
public
ApuestaUnicaIncrementoDinamicoCfgImpl(double
incremento,
double
puja,
double
reserva,
int
rondas)
{
super();
this.incremento
=
incremento;
this.puja
=
puja;
this.reserva
=
reserva;
this.rondas=rondas;
this.contadorRondas=0;
}
public
Behaviour
getComportamiento()
{
return
comportamiento;
}
-101/106-
}
public
void
setComportamiento(Behaviour
comportamiento)
{
this.comportamiento=(CompradorHolandesaIncrementoDinamicoBehaviour)comportamiento;
}
public
int
getRondas()
{
return
rondas;
}
public
void
setRondas(int
rondas)
{
this.rondas
=
rondas;
}
public
double
getIncremento()
{
return
incremento;
}
public
void
setIncremento(double
incremento)
{
this.incremento
=
incremento;
}
public
double
getPuja()
{
return
puja;
}
public
void
setPuja(double
puja)
{
this.puja
=
puja;
}
public
double
getReserva()
{
return
reserva;
}
public
void
setReserva(double
reserva)
{
this.reserva
=
reserva;
}
public
int
getContadorRondas()
{
return
contadorRondas;
}
public
void
setContadorRondas(int
contadorRondas)
{
this.contadorRondas
=
contadorRondas;
}
-102/106-
Clase
SubastaHolandesaImpl
package
uoc.sma.estrategias;
import
uoc.sma.behaviours.estrategias.SubastadorHolandesaBehaviour;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
configuración
de
la
subasta
Holandesa
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
public
class
SubastaHolandesaImpl
implements
ICfgSubasta
{
private
SubastadorHolandesaBehaviour
comportamiento;
public
Behaviour
getComportamiento()
{
return
comportamiento;
}
public
void
setComportamiento(Behaviour
comportamiento)
{
this.comportamiento=
(SubastadorHolandesaBehaviour)
comportamiento;
}
}
Clase
SubastaInglesaImpl
package
uoc.sma.estrategias;
import
uoc.sma.behaviours.estrategias.SubastadorInglesaBehaviour;
import
jade.core.behaviours.Behaviour;
/**
*
Encapsula
la
configuración
de
la
subasta
Inglesa
*
*
@author
Rodolfo
de
Benito
Arango
*
*/
public
class
SubastaInglesaImpl
implements
ICfgSubasta
{
private
SubastadorInglesaBehaviour
comportamiento;
public
Behaviour
getComportamiento()
{
return
comportamiento;
}
public
void
setComportamiento(Behaviour
comportamiento)
{
this.comportamiento=
(SubastadorInglesaBehaviour)
comportamiento;
}
}
-103/106-
Clase
Subasta
package
uoc.sma.datos;
import
jade.core.AID;
import
jade.lang.acl.ACLMessage;
import
jade.util.leap.Serializable;
import
java.util.ArrayList;
import
java.util.Date;
/**
*
Clase
que
encapsula
los
datos
propios
de
la
subasta
*
*
@author
Rodolfo
de
Benito
*/
public
class
Subasta
implements
Serializable{
public
static
final
int
SUBASTA_INGLESA=1;
public
static
final
int
SUBASTA_HOLANDESA=2;
private
static
final
long
serialVersionUID
=
1L;
private
int
idSubasta;
private
Date
fechaInicio;
private
AID
agenteSubastador;
private
String
objetoSubastado;
private
double
precio;
private
double
precioReserva;
private
boolean
activa;
private
int
tipoSubasta;
private
AID
ganador;
private
ACLMessage
msgMejorOferta;
private
ArrayList<AID>
suscriptores;
public
Subasta(int
idSubasta,
Date
fechaInicio,
String
objetoSubastado,
double
precio,
double
precioReserva,
boolean
activa,
int
tipoSubasta)
{
super();
this.idSubasta
=
idSubasta;
this.fechaInicio
=
fechaInicio;
this.objetoSubastado
=
objetoSubastado;
this.precio
=
precio;
this.precioReserva
=
precioReserva;
this.activa
=
activa;
this.tipoSubasta
=
tipoSubasta;
suscriptores
=
new
ArrayList<AID>();
}
public
ACLMessage
getMsgMejorOferta()
{
return
msgMejorOferta;
}
public
void
setMsgMejorOferta(ACLMessage
msgMejorOferta)
{
this.msgMejorOferta
=
msgMejorOferta;
}
public
double
getPrecio()
{
return
precio;
}
public
void
setPrecio(double
precio)
{
this.precio
=
precio;
}
-104/106-
}
public
int
getIdSubasta()
{
return
idSubasta;
}
public
void
setIdSubasta(int
idSubasta)
{
this.idSubasta
=
idSubasta;
}
public
Date
getFechaInicio()
{
return
fechaInicio;
}
public
void
setFechaInicio(Date
fechaInicio)
{
this.fechaInicio
=
fechaInicio;
}
public
String
getObjetoSubastado()
{
return
objetoSubastado;
}
public
void
setObjetoSubastado(String
objetoSubastado)
{
this.objetoSubastado
=
objetoSubastado;
}
public
double
getPrecioReserva()
{
return
precioReserva;
}
public
void
setPrecioReserva(double
precioReserva)
{
this.precioReserva
=
precioReserva;
}
public
boolean
isActiva()
{
return
activa;
}
public
void
setActiva(boolean
activa)
{
this.activa
=
activa;
}
public
int
getTipoSubasta()
{
return
tipoSubasta;
}
public
void
setTipoSubasta(int
tipoSubasta)
{
this.tipoSubasta
=
tipoSubasta;
}
public
AID
getAgenteSubastador()
{
return
agenteSubastador;
}
public
void
setAgenteSubastador(AID
agenteSubastador)
{
this.agenteSubastador
=
agenteSubastador;
}
public
AID
getGanador()
{
return
ganador;
}
public
void
setGanador(AID
ganador)
{
this.ganador
=
ganador;
}
public
ArrayList<AID>
getSuscriptores()
{
return
suscriptores;
}
public
void
setSuscriptores(ArrayList<AID>
suscriptores)
{
this.suscriptores
=
suscriptores;
}
@Override
public
String
toString()
{
String
cadena;
cadena="Subasta
Id:"+getIdSubasta()+
"
"+getObjetoSubastado()+"
Precio:"+getPrecio()+"
Inicio:"+getFechaInicio();
return
cadena;
}
-105/106-
Clase
Transacción
package
uoc.sma.datos;
import
java.io.Serializable;
import
java.util.Date;
/**
*
Encapsula
los
datos
de
una
transacción
u
operación
realizada
en
una
subasta
*
@author
Rodolfo
de
Benito
*/
public
class
Transaccion
implements
Serializable{
private
Date
fecha;
private
int
idSubasta;
private
String
agente;
private
String
operación;
private
double
valor;
public
static
final
String
PUJA="PUJA";
public
static
final
String
OFERTA
=
"OFERTA";
public
static
final
String
INICIO
=
"INICIO";
public
static
final
String
FIN
=
"FIN";
public
Transaccion(Date
fecha,
int
idSubasta,
String
agente,
String
operación,
double
valor)
{
super();
this.fecha
=
fecha;
this.idSubasta
=
idSubasta;
this.agente
=
agente;
this.operación
=
operación;
this.valor
=
valor;
}
public
Date
getFecha()
{
return
fecha;
}
public
void
setFecha(Date
fecha)
{
this.fecha
=
fecha;
}
public
int
getIdSubasta()
{
return
idSubasta;
}
public
void
setIdSubasta(int
idSubasta)
{
this.idSubasta
=
idSubasta;
}
public
String
getAgente()
{
return
agente;
}
public
void
setAgente(String
agente)
{
this.agente
=
agente;
}
public
String
getOperación()
{
return
operación;
}
public
void
setOperación(String
operación)
{
this.operación
=
operación;
}
public
double
getValor()
{
return
valor;
}
public
void
setValor(double
valor)
{
this.valor
=
valor;
}
public
String
toString()
{
String
cadena="Transacción
Fecha:"+getFecha()+"
Id.
subasta:"+getIdSubasta()+"
Agente:"
+getAgente()+"
Operación:"+getOperación()+"
Valor:"+getValor();
return
cadena;
}
}
-106/106-
Descargar