jueves, 3 de diciembre de 2009

Cooperación a través de la programación

código

Un valor que debe desarrollar nuestro alumnos es que la cooperación, el trabajo en equipo, es fundamental en el desempeño de su actividad laboral. En esta entrada te propongo una actividad para trabajar en clase la cooperación a través de la programación.

La actividad se basa en el clásico de la teoría de juegos "el dilema del prisionero". En este caso, el dilema se replantea en el siguiente escenario: son dos programadores que trabajan en un mismo proyecto y tienen la posibilidad de cooperar o no para realizar su trabajo. La recompensa/castigo por su actitud se mide en horas de trabajo que debe realizar.

Para la realización de la actividad cada alumno debe programar un "prisionero" utilizando Python en donde debe decidir si quiere colaborar o no. .A continuación se realiza un torneo en donde se cruzarán todos los prisioneros programados, generándose la puntación para cada uno de ellos. Realmente en nuestro caso no es un "prisionero" sino un "programador", pero he preferido utilizar la nomenclatura más acorde al planteamiento clásico del dilema del prisionero aunque el nombre lo puedes cambiar (consultar parámetro "-c").

La idea es realizar varias iteraciones en donde los alumnos programan su prisionero, se realiza el torneo y se valora los resultados de las diferentes estrategias. En cada iteración se puede realizar diferentes tipos de cruces atendiendo a la información que tiene disponible un prisionero para decidir:
  1. No posee ninguna información.
  2. Conoce la respuesta anterior de su oponente. La función "cooperar" de cada prisionero recibe como parámetro un valor lógico (True o False) indicando la respuesta dada anteriormente por su oponente.
  3. Conoce todas las respuestas anteriores dada en el torneo, tanto en los cruces en los que ha participado como en los que no.
Se podría modificar el programa para contemplar la posibilidad de que los prisioneros puedan elegir al oponente con que se quiere enfrentar. Seguramente, cada prisionero/programador prefiera enfrentarse/trabajar con los prisioneros/programadores que más colaboran.

Puedes jugar online al dileman del prisionero en la siguiente página.

Programar los prisioneros

Programar un "prisionero" es muy sencillo. En un fichero de texto con extensión ".py" (módulo en Python) cada alumno debe crear una clase que tenga los atributos "nombre" y "version", y la función "cooperar" en la que se debe devolver True si colabora o False en caso contrario. Por ejemplo, este es el código de un prisionero que siempre colabora.

class Prisionero(object):
nombre = "prisionero colaborador"
version = "1.0"

def cooperar(self, informacion):
return True

El parámetro "información" tiene que ver con la opción "-a". Consulta el apartado de posibles parámetros por línea de comandos.

Los estudiantes pueden programar una gran diversidad de prisioneros. Por ejemplo:
  1. Un prisionero que siempre coopera o al contrario, que nunca coopera.
  2. Un prisionero rencoroso que siempre coopera hasta que el contrario deja de cooperar, a partir de este momento nunca más coopera. Para realizar este tipo de torneo y el siguiente, se debe indicar al programa como parámetro "-a 1", así se le pasará a cada prisionero la última respuesta de su openente como parámetro de la función "cooperar"
  3. Un prisionero con la filosofía "donde las dan, las toman". En este caso, el prisionero coopera la primera vez y a partir de este momento siempre repetirá la última jugada realizada por su oponente.
Se ha realizado competiciones anteriores del dilema del prisionero en donde parece que el algoritmo óptimo es el prisionero con la filosofía "donde las dan, las toman".

Ejecutar el programa

Aunque se puede indicar diferentes parámetros, el programa es tan fácil, como copiar todos los archivos en donde los alumnos han programado un prisionero en la carpeta "prisioneros" y a continuación ejecutar el comando:

python ./dilemaprisionero.py

Se genera un directorio con el nombre "partida..." y dentro los siguientes tres archivos:
  • El archivo con nombre "interrogatorios.txt" contiene todos los cruces llevados a cabos y la respuesta de cada jugador.
  • El archivo nombrado "sentencias.txt" contiene el ranking de todos los prisioneros.
  • El archivo nombrado "logging.txt" en donde puedes consultar la traza seguida. Este archivo te puede ser útil si se produce algún error durante la ejecución y quieres averiguar el motivo.

Parámetros por línea de comandos

Parámetros que puedes indicar por línea de comandos:
  • "-o [directorio]" Nombre del directorio en donde se guardarán todos los ficheros generados por el programa. Por defecto se generará un directorio con el formato de nombre "partida_AñoMesDiaHoraMinutoSegundos".
  • "-d [directorio]" Nombre de la carpeta en la que se encuentra los ficheros Python con el código de cada prisionero. Por defecto, esta carpeta se llama "prisioneros".
  • "-t [nombre tabla]" Nombre de la tabla de recompensa que se empleará para definir las recompensas/castigo a cada prisionero. Estas tablas están definidas en el fichero "tabla_pagos.py".
  • "-i [numero de iteraciones]" Indica el número de veces que se va a enfrentar los dos programadores en un mismo interrogatorio. Valor 100 por defecto.
  • "-x [número de cruces]" Número de veces (interrogatorios) que se realizarán entre dos prisioneros. Valor 1 por defecto.
  • "-a [0|1|2]". Indica la información que recibe cada prisionero: "0" no recibe ninguna información, "1" recibe la última respuesta dada por su oponente, "2" recibe todas las respuestas dada hasta el momento por su oponente.
  • "-c [clase prisionero]" Nombre de la clase de los prisioneros. Por defecto es "Prisionero".
Tabla de recompensa

Esta es una posible tabla de recompensa:




prisionero A/prisionero BSiNo
Si816
No120

De este modo, si los dos prisioneros colaboran "Si", tendrán que trabajar 8 horas. Si el prisionero A colabora y el prisionero B no lo hace, el prisionero A tendrá que trabajar 16 horas y el prisionero B tan sólo 1 hora. Si ninguno de los dos colaboran, tendrán que trabajar 20 horas.

3 comentarios:

Unknown dijo...

Muy buenas,

He encontrado el artículo muy interesante.

He estado haciendo pruebas con el código y siempre obtengo el mismo error:

Traceback (most recent call last):
File "", line 1, in
__import__("C:/prisionero2.pyc")
ImportError: Import by filename is not supported.

¿Podría ud. echarme una mano? (trabajo sobre Win 7 / MAC OS X)

Unknown dijo...

Lo miro y te digo. A ver si es un problema de versiones de Python o de sistema operativo.

Unknown dijo...

Pues realmente le estaría agradecido.