Simulando sistemas complejos con WebSphere eXtreme Scale

Tomando como ejemplo el tráfico de vehículos en las calles de una ciudad, en este documento se describe la manera en que puede construirse y simularse un modelo que involucra grandes cantidades de agentes aprovechando la capacidad de Websphere eXtreme Scale para almacenar en memoria un número prácticamente ilimitado de objetos y realizar operaciones distribuidas sobre ellos usando recursos en diferentes servidores.

Mauricio García, Software IT Architect, IBM México, ISV's & Developer Relations

Mauricio García cuenta con más de 12 años de experiencia en diseño de aplicaciones empresariales. Como arquitecto de soluciones colabora con el ecosistema de IBM para aplicar la tecnología de la información en la solución de problemas de industria.

Mauricio es ingeniero en sistemas computacionales, cuenta con una maestría en ciencias de la computación, un máster en administración de empresas y estudios de doctorado en gestión estratégica y políticas de desarrollo.



05-09-2011

¿Qué es el Modelado Basado en Agentes?

La simulación de sistemas complejos, como aquellos que involucran el comportamiento de personas, puede ser abordada como la simulación de agentes con objetivos individuales interactuando entre sí. En el Modelado Basado en Agentes (ABM), un sistema es modelado como una colección de entidades autónomas que pueden tomar decisiones y tienen un objetivo establecido. Estos agentes se encuentran en un ambiente que define el espacio en el que pueden operar. Cada agente tiene la capacidad de evaluar su situación y tomar decisiones con base en un conjunto de reglas. Las interacciones continuas entre los agentes determinarán el comportamiento del sistema completo.

El ambiente y las características de los agentes serán definidos por el dominio del sistema que se quiera modelar. De esta manera, los agentes pueden representar células en un organismo, empresas en una economía, personas desplazándose durante una evacuación, o cualquier elemento requerido para simular el escenario que se va a estudiar.
. Incluso los modelos más simples pueden mostrar patrones de comportamiento complejos y proveer información valiosa sobre la dinámica del sistema que representa. Adicionalmente, si se añade a los agentes la capacidad de evolucionar, cambiando sus reglas de comportamiento para mejorar su capacidad de lograr sus objetivos, eventualmente emergerán patrones de comportamiento no anticipados.

Los beneficios de ABM sobre otras técnicas de modelado pueden ser resumidos en tres: a) el ABM permite el surgimiento de comportamientos emergentes no identificados al momento del modelado, potencialmente contraintuitivos y por lo tanto difícilmente predecibles, b) ABM provee una descripción natural de un sistema, pues se enfoca en el modelado de un agente no en la visión de un planeador central que coordina el comportamiento de todos los agentes en su conjunto, y c) ABM es suficientemente flexible para permitir la definición de diferentes tipos de agentes y el nivel de detalle en su descripción para analizar el surgimiento de diferentes características en el sistema.

Implementación del modelo

Desde el punto de vista funcional un modelo basado en agentes es relativamente simple. Se requiere implementar para cada tipo de agente la capacidad de recibir eventos de su entorno, evaluar su contexto y actuar de manera individual de acuerdo a la situación. No se necesita implementar un control central que coordine el comportamiento agregado del sistema.

Para simular el comportamiento del sistema, se crean instancias de los diferentes tipos de agentes y de manera iterativa se solicita a estos objetos que actúen, modificando su estado y el de su entorno, afectando de esta manera a otros agentes.

Una simulación efectiva requiere que la capacidad de almacenamiento y procesamiento de la plataforma utilizada pueda escalar de acuerdo con la cantidad de agentes a ser instanciados. Hay dos formas en que puede lograrse el crecimiento de estas capacidades, escalando verticalmente mediante la utilización de servidores con más memoria y procesadores, o escalando horizontalmente integrando de manera coordinada un conjunto de servidores formando una red de recursos.

Como en cada iteración potencialmente todos los agentes tendrán una acción, se debe procurar un acceso rápido a los objetos, idealmente manteniéndolos en memoria. También es importante considerar que la posibilidad de realizar operaciones en paralelo en el conjunto de objetos permitirá procesar las iteraciones más rápidamente, disminuyendo el tiempo necesario para llevar a cabo la simulación.

Finalmente, para que la simulación sea útil, la plataforma debe permitir que los datos generados puedan ser analizados. Idealmente se espera poder visualizar los datos mientras se desarrolla la simulación para identificar el surgimiento de comportamientos emergentes. La visualización del modelo debe ayudar a entender las implicaciones del comportamiento de los agentes en el sistema real que representa.


WebSphere eXtreme Scale

WebSphere eXtreme Scale es un almacén de objetos en memoria, elástico y escalable. Funciona coordinando recursos de un conjunto de máquinas virtuales Java (JVM) como si fueran una unidad, permitiendo almacenar una gran cantidad de objetos en memoria de manera distribuida. WebSphere eXtreme Scale puede ser utilizado como un caché de objetos o como una capa de acceso a datos que permite tiempos de respuesta muy cortos para una cantidad enorme de objetos.

Como su nombre sugiere, WebSphere eXtreme Scale permite escalar de manera substancial la capacidad de almacenamiento de objetos en memoria, esto se logra mediante la adición de más recursos provenientes de JVM's ejecutadas en servidores distribuidos. WebSphere eXtreme Scale está diseñado para poder integrar cientos de contenedores, aumentando su capacidad de almacenamiento y procesamiento sin formar un cuello de botella.

Como el almacén de objetos está formado por recursos en diferentes contenedores, los objetos están almacenados de manera distribuida. Para organizar los objetos en los contenedores, se crean particiones que definen qué tipo de objetos serán almacenados en cada contenedor, así como políticas de replicación para lograr alta disponibilidad del almacén en su conjunto.

Una introducción a las características de WebSphere eXtreme Scale puede ser consultada en el artículo Introducción a WebSphere eXtreme Scale (Parte 1).

La capacidad de escalar de WebSphere eXtreme Scale lo convierte en un elemento ideal de una plataforma de ABM, pues hará posible el almacenamiento de agentes en memoria aún cuando se trate de millones de ellos.

Agentes

WebSphere eXtreme Scale cuenta con una API para realizar consultas al almacén de objetos. Para procesar una consulta que involucra objetos en diferentes particiones es posible implementar agentes que coordinen la consulta distribuida. Cuando se realiza una consulta mediante un agente, una copia del agente es enviada para su ejecución en cada una de las particiones. Cada partición ejecuta la consulta de menera local, distribuyendo el procesamiento y evitando la comunicación entre particiones. Finalmente se agregan los resultados de todas las particiones como un resultado global.

Figura 1 – Ejecución de agentes en WebSphere eXtreme Scale
Figura 1 – Ejecución de agentes en WebSphere eXtreme Scale

Como los agentes tienen la capacidad de ejecutar lógica de forma paralela en todas las particiones, pueden ser utilizados para actualizar los objetos que se encuentran en éstas. Para la implementación de una plataforma ABM se puede tomar ventaja de esta característica para distribuir la carga de trabajo que implica actualizar el estado de todos los agentes durante una iteración de la simulación aprovechando los recursos de procesamiento de los contenedores.


Implementación de un modelo basado en agentes

En este ejemplo se construirá una aplicación que realiza la simulación de un modelo basado en agentes utilizando WebSphere eXtreme Scale para almacenar los agentes como objetos y agentes para realizar operaciones sobre ellos de manera distribuida.

Escenario

La simulación del movimiento de vehículos en las calles de una ciudad puede ser concebida como un modelo en el que cada vehículo es un agente con un objetivo definido: viajar de un punto a otro. Estos vehículos pueden moverse en las calles de acuerdo a las siguientes restricciones:

  • El vehículo tiene una hora de inicio en la que comenzará a moverse definido por el horario de una persona.
  • Cada vehículo tiene un punto de origen y un punto de destino y calculará la ruta más corta con base en la distancia a recorrer.
  • El vehículo se moverá a la velocidad menor entre su velocidad por defecto y la velocidad máxima de la calle que transita.
  • Cada calle esta compuesta por tramos. Cada tramo tiene un sentido y una capacidad máxima de vehículos.
  • Un vehículo puede entrar a un tramo si el número de vehículos que contiene es menor que su capacidad máxima. Si no, debe esperar su turno en una cola de entrada. Mientras espera, consinua utilizando espacio en la calle en que se encuentra.

Para actuar de acuerdo a estas restricciones, cada vehículo debe tomar en cuenta solamente información propia y de su entorno inmediato.

Entidades

WebSphere eXtreme Scale almacena los objetos de acuerdo a una estructura jerárquica. La entidad raíz define la partición en la que serán almacenados todos los objetos asociados. De esta forma, si las calles contienen tramos, todos los tramos serán almacenados en la misma partición que la calle a la que pertenecen. Es importante tomar en cuenta esta forma de organización al momento de iterar sobre los objetos ya una transacción no puede modificar objetos en más de una partición.

Las entidades representan objetos únicos. En este caso, los vehículos no son implementados como entidades porque son objetos temporales que serán creados y destruidos durante la simulación.

Figura 2 – Entidades del modelo de simulación
Figura 2 – Entidades del modelo de simulación

Para definir esta estructura, se anotan las clases con annotations definidos en el paquete com.ibm.websphere.projector.annotations. Como ejemplo, la entidad Street está definida por la clase Street, cuenta con un identificador único streetId y mantiene una relación de uno a muchos con la clase Track.

@Entity
public class Street {
  @Id long streetId;
  @OneToMany(cascade=CascadeType.ALL, mappedBy="street") List<Track> tracks;
  String name;
}

Ciclo

Para realizar la simulación se realizan los siguientes pasos:

  1. Inicialización
    1. Crear los objetos correspondientes a calles
    2. Crear los objetos correspondientes a personas
  2. Iteración – cada ciclo representa un segundo de la simulación
    1. Crear los vehículos de las personas que inician su recorrido en este segundo
    2. Calcular la nueva posición de los vehículos en las calles
    3. Mover los vehículos entre calles
    4. Remover los vehículos que han llegado a su destino

Inicialización

La información de las calles puede obtenerse de OpenStreetMap en forma de documento XML. La clase LoadOSM implementa la interface org.xml.sax.DefaultHandler para iterar el contenido y crear una calle con sus tramos por cada elemento <way> en el documento.

El primer paso es conectarse al almacen de objetos para obtener una sesión y su objeto EntityManager asociado. El EntityManager será utilizado para acceder las entidades.

protected final static String objectGridName = "CityObjectGrid";
protected final static String connectionEndPoint = "xabmserver:2809";
protected final static String objectgridDefinition = "ObjectGrid_Definition.xml";

ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();
ClientClusterContext clusterContext = ogManager.connect(connectionEndPoint,null, null);
ObjectGrid og = ogManager.getObjectGrid(clusterContext, objectGridName);
Session ses = og.getSession();
EntityManager em = ses.getEntityManager();

Para cada calle en el documento se creará un objeto Street y para cada tramo un objeto Track que será añadido a la lista de la calle. Cada calle es almacenada y como se ha definido una relación de cascada entre estas entidades, al almacenar el objeto Street se almacenan todos los objetos Track relacionados.

Street currentStreet=new Street();
currentStreet.tracks=new Vector<Track>();
.
.
.
Track track=new Track();
currentStreet.tracks.add(track);
.
.
.
em.getTransaction().begin();
em.persist(currentStreet);
em.getTransaction().commit();

Al terminar con las calles, se crean los objetos correspondientes a las personas, eligiendo el origen y destino de manera aleatoria. La ruta a seguir es calculada usando la clase DijkstraShortestPath de la librería JGraphT.

Iteración

Para la ejecución de la simulación se realiza una iteración en la que cada ciclo representa el paso de un segundo en el mundo real.

La clase RunModel se conecta al almacén de objetos y obtiene una referencia al AgentManager. El AgentManager coordina las llamadas de los agentes hacia las particiones y consolida el resultado de cada una para formar el resultado global. En cada ciclo se llamará a los agentes que ejecutarán las acciones sobre los vehículos en cada partición

El primer agente llamado es QueryPeopleMapAgent, que busca las personas que tienen programado iniciar su viaje en el segundo actual, para crear los vehículos correspondientes. La ejecución del agente mediante el método AgentManager.callMapAgent devuelve el mapa de vehículos que deben ser creados.

ObjectGrid ogManager = ObjectGridManagerFactory.getObjectGridManager();
ObjectMap map = ses.getMap("Street");
AgentManager amgr = map.getAgentManager();
QueryPeopleMapAgent qpma = new QueryPeopleMapAgent();
.
.
.
Map<Long, Vehicle> resultMap=(Map<Long, Vehicle>)amgr.callMapAgent(qpma);

Un agente que devuelve resultados debe implementar las interfaces EntityAgentMixin y MapGridAgent. EntityAgentMixin define la clase a la que pertenecen los resultados para que el resultado de cada partición pueda ser agregado al resultado global.

@Override
public Class getClassForEntity() {
    return Vehicle.class;
}

La interface MapGridAgent define la lógica que se ejecutará en la partición. El método processAllEntries recibe una sesión local en la partición en que está siendo ejecutada y devuelve un mapa de resultados parciales que serán agregados por el AgentManager a los resultados de las otras particiones.

Dentro del método processAllEntries pueden realizarse consultas utilizando la clase com.ibm.websphere.objectgrid.em.Query. Las consultas se realizan utilizando OGQL (Object Grid Query Languaje), un lenguaje similar a SQL en el que objetos y atributos son utilizados en lugar de tablas y columnas. En la calse QueryPeopleMapAgent se consultan las personas para las que deben crearse vehículos, con esta lista se crean los vehículos con los que se llenará el mapa de resultado.

@Override
public Map processAllEntries(Session ses, ObjectMap map) {
    EntityManager em = ses.getEntityManager();
    HashMap<Long, Vehicle> result=new HashMap<Long, Vehicle>();
Query q = em.createQuery("SELECT p FROM Person p WHERE p.startTime = ?1");
    q.setParameter(1, currentTime);
    Iterator iter = q.getResultIterator();
    while (iter.hasNext()) {
        p=(Person)iter.next();
        Vehicle v=new Vehicle();
        v.vehicleId=p.personId;
        v.route=p.route;
        result.put(v.vehicleId, v);
    }
    return result;
}

La lista de vehículos a crear es alimentada al agente AddVehiclesAgent. El agente recorrerá la lista de vehículos verificando si el tramo en el que el vehículo comienza su ruta se encuentra en la partición en que se está ejecutando el agente, en este caso se agrega a la cola de entrada del tramo. Como el agente se ejecutará en todas las particiones, eventualmente todos los vehículos podrán ser creados en alguna de ellas.

Query qryTrack=em.createQuery("SELECT t FROM Track t WHERE t.startPoint.id=?1
 AND t.endPoint.id=?2");
trackIter=qryTrack.getResultIterator();
if(trackIter.hasNext()) { // track is in this partition
    track=(Track)trackIter.next();
    track.inQueue.add(v);
}

Para mover los vehículos el agente MoveVehiclesMapAgent itera las calles de la partición y llama al método Street.moveVehicles() en cada una de ellas. El método Street.moveVehicles() cambia la posición de los vehículos en la calle y devuelve los vehículos que deben ser cambiados de calle. El cambio de calle no puede realizarse en la misma llamada si la siguiente calle se encuentra en otra partición, asi que el agente devuelve los vehículos que deben ser movidos a otra partición.

Query q = em.createQuery("SELECT s FROM Street s WHERE s.hasVehicles=true");
Iterator iter = q.getResultIterator();
while (iter.hasNext()) {
    Vector<Vehicle> vehicles=(Vector<Vehicle>)((Street)iter.next()).moveVehicles();
    for(Iterator<Vehicle> it=vehicles.iterator();it.hasNext();) {
        Vehicle v=it.next();
        result.put(v.vehicleId, v);
    }
}

El método Street.moveVehicles() itera los tramos de la calle, aceptando vehículos de la cola de entrada si hay espacio en el tramo e invocando para cada tramo el método Track.moveVehicles() que a su vez invoca el método Vehicle.move() en cada vehículo que contiene. El vehículo calculará su nueva posición en el tramo y al llegar al final se pondrá en la cola de salida del tramo. Para los vehículos en la cola de salida de un tramo el método Street.moveVehicles() evalúa si el siguiente tramo en su ruta forma parte de la misma calle, si es el caso lo coloca en su cola de entrada y lo remueve de la cola de salida del tramo anterior para liberar el espacio que ocupa, de lo contrario lo anexa a la lista de resultados.

Iterator iter = tracks.iterator();
while (iter.hasNext()) {
    track=tracks.next();
    result.addAll(track.moveVehicles());
						
    Iterator<Vehicle> vit=track.outQueue.iterator();
        while(vit.hasNext()) {
            v=vit.next();
            if(v.status!=Vehicle.WAITING_OUT) {
                nextTrack=trackStartingIn(v.route.firstElement().id);
                if(nextTrack!=null) { // same street
                    v.status=Vehicle.START_MOVING;
                    nextTrack.inQueue.add(v);
                    track.purgeVehicle(v);
                } else {
                    v.status=Vehicle.WAITING_OUT;
                }
            }
        }
    }
}

Para los vehículos que están en lista de espera para cambiar de calle se invoca nuevamente el agente AddVehiclesAgent. El resultado será la lista de vehículos que pudieron ser creados en la nueva calle y deben ser eliminados de la cola de salida de la calle anterior llamando al agente PurgeVehiclesAgent. Los vehículos que no pueden ingresar en la nueva calle por falta de espacio disponible, se quedarán detenidos en la calle anterior durante un ciclo más, posiblemente comenzando a generar un embotellamiento.

Este ciclo se repetirá para cada segundo del tiempo que se quiera simular.

Visualización

Para observar el desarrollo de la simulación la mejor opción es ver un mapa en el que se muevan los vehículos. Utilizando JViews Maps se puede cargar el mapa, dibujar una representación de los vehículos y moverlos de acuerdo a su cambio de posición, sin tener que tratar con detalles de bajo nivel del manejo de un sistema de coordenadas y lograr un despliegue eficiente de una gran cantidad de objetos gráficos. Adicionalmente JViews Maps provee herramientas para interactuar con el mapa realizando acercamientos, rotándolo y moviéndolo para seguir un agente en particular, lo que puede facilitar el análisis de la simulación.

Para desplegar el mapa se crea un JApplet que será utilizado como contenedor de los objetos gráficos. La clase SimulationMap extiende JApplet para cumplir este propósito. Al instanciarse crea una vista (objeto IlvManagerView) que servirá para manejar los objetos de JViews y un objeto IlvJScrollManagerView asociado para integrar la vista en la ventana del JApplet.

IlvManagerView view = new IlvManagerView();
IlvJScrollManagerView viewScroll = new IlvJScrollManagerView(view);

Estos elementos se integran en el JApplet mediante un JPanel

JPanel pane = new JPanel();
Container contentPane = getContentPane();
pane.add(viewScroll);
contentPane.add(pane, BorderLayout.CENTER);

Finalmente, de un archivo se lee la información del mapa utilizando un objeto IlvMapInputStream para asociarla a la vista.

URL ivlFile = SimulationMap.class.getResource(file);
IlvMapInputStream mapInput = new IlvMapInputStream(ivlFile);
mapInput.read(view.getManager());

De manera similar a AWT, en esta vista pueden ser creados nuevos objetos gráficos y modificados posteriormente para reflejar el movimiento de los vehículos durante la simulación. Los vehículos serán desplegados como círculos usando la clase IlvEllipse.

Figura 3 – Desplegando un mapa con JView Maps
Figura 3 – Desplegando un mapa con JView Maps

Ejecución

Para ejecutar la simulación se requiere configurar el almacén de objetos utilizando un archivo de definición de objetos y un archivo de despliegue.

El archivo de definición de objetos describe las entidades que serán almacenadas

<entity class-name="com.ibm.extremeabm.urban.Street" name="Street" schemaRoot="true"/>
<entity class-name="com.ibm.extremeabm.urban.Track" name="Track" schemaRoot="false"/>

El archivo de despliegue describe cómo serán divididos y replicados los objetos en los contedores. En este caso se crearán 5 particiones para los objetos y no se crearán réplicas porque no se requiere una alta disponibilidad de la plataforma.

<objectgridDeployment objectgridName="CityObjectGrid">
<mapSet name="STREET_MAPSET" numberOfPartitions="5" minSyncReplicas="0"
        maxSyncReplicas="0" maxAsyncReplicas="0">
        <map ref="Street" />
        <map ref="Track" />
    </mapSet>
</objectgridDeployment>

En el servidor central se iniciará el CatalogServer que controlará los contenedores

> startOgServer CatalogServer

Se iniciarán 5 contenedores, para que cada uno contenga una de las particiones. Para cada uno debe especificarse un nombre único. El primero se ejecutará con el nombre server1:

> startOgServer server1 -objectgridFile ObjectGrid_Definition.xml -
deploymentPolicyFile ObjectGrid_Deployment.xml -catalogServiceEndPoints 
xabmserver:2809 -jvmArgs –cp eXtremeABM

Con los cinco contenedores listos se pueden cargar los datos iniciales:

> java com.ibm.extremeabm.urban.LoadOSM -Djava.endorsed.dirs= 
extremescale\ObjectGrid\lib\endorsed

Se puede verificar que los objetos están distribuidos en las particiones. Las calles se distrubuyen de manera uniforme porque son constituyen la entidad raiz, mientras que los tramos están distribuidos de acuerdo a la calle a la que están asociados.

> xsadmin –mapsizes

Connecting to Catalog service at localhost:1099

************Displaying Results for Grid - CityObjectGrid, MapSet - 
STREET_MAPSET**************

*** Listing Maps for server1 ***
Map Name Partition Map Size Used Bytes (MB) Shard Type
Person   4         200      143             Primary
Street   4         2198     1.5             Primary
Track    4         25626    19.5            Primary
Server Total: 28024 (21.14MB)

*** Listing Maps for server2 ***
Map Name Partition Map Size Used Bytes (MB) Shard Type
Person   0         200      143             Primary
Street   0         2321     1.6             Primary
Track    0         27668    21.01           Primary
Server Total: 30189 (22.74MB)

*** Listing Maps for server3 ***
Map Name Partition Map Size Used Bytes (MB) Shard Type
Person   3         200      143             Primary
Street   3         2226     1.52            Primary
Track    3         25819    19.62           Primary
Server Total: 28245 (21.29MB)

*** Listing Maps for server4 ***
Map Name Partition Map Size Used Bytes (MB) Shard Type
Person   2         200      143             Primary
Street   2         2239     1.52            Primary
Track    2         24872    18.91           Primary
Server Total: 27311 (20.56MB)

*** Listing Maps for server5 ***
Map Name Partition Map Size Used Bytes (MB) Shard Type
Person   1         200      143             Primary
Street   1         2208     1.52            Primary
Track    1         26982    20.52           Primary
Server Total: 29390 (22.18MB)

Total Domain Count: 143159 (107.91MB)

El ambiente está listo para ejecutar la simulación:

java com.ibm.extremeabm.urban.RunModel -Djava.endorsed.dirs=
 extremescale\ObjectGrid\lib\endorsed

Una simulación utilizando 80,000 calles y 100,000 vehículos que inician su camino en un lapso de una hora se vería así:

Figura 4 – Simulación de tráfico
Figura 4 – Simulación de tráfico

Conclusiones

En este ejemplo se mostró cómo utilizar Websphere eXtreme Scale como base para simular modelos basados en agentes. La capacidad de Websphere eXtreme Scale para almacenar grandes volúmenes de objetos en memoria y ejecutar procesos de manera distribuida aprovechando recursos de diferentes servidores permite que las simulaciones puedan escalar para permitir el manejo de modelos con millones de agentes.

Sin una restricción en el tamaño de la simulación es posible tratar con problemas de la vida real a gran escala. La única limitante es la capacidad del modelador para representar el problema bajo este paradigma.


Recursos

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=WebSphere
ArticleID=755387
ArticleTitle=Simulando sistemas complejos con WebSphere eXtreme Scale
publish-date=09052011