(Post 01/09/2006) In this tutorial, we described
the OptimalGrid system and showed how it enables you to use a Grid to
solve a problem. You need only to write the Java code to describe the
problem at the level of the cell and its interaction with its neighbors.
The OptimalGrid system then handles all of the details of mapping this
into a problem with thousands or millions of cells and running it on a
computing Grid consisting of hundreds of computers.
Các phần đã đăng:
Section 6. Summary
In this tutorial, we described the OptimalGrid system
and showed how it enables you to use a Grid to solve a problem. You need
only to write the Java code to describe the problem at the level of the
cell and its interaction with its neighbors. The OptimalGrid system then
handles all of the details of mapping this into a problem with thousands
or millions of cells and running it on a computing Grid consisting of
hundreds of computers.
We described how to install OptimalGrid and run a sample
problem.
Finally, we went step by step through the code you would
write to implement a solution to your own unique problem.
Section 7. Appendices
Code listing for OPCEden class
Following is the complete code for the OPCEden
class, except that the propagation() and localInteraction()
methods are shown next.
// OPCEden.java package com.ibm.almaden.smartgrid.apps.eden; /* ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT IBM Corp. 2002 All rights reserved. ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule ** Contract with IBM Corp. ** */ import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.Random; import java.util.Vector; import com.ibm.almaden.smartgrid.AppUtilsGeneric; import com.ibm.almaden.smartgrid.Coordinates; import com.ibm.almaden.smartgrid.EntityAbstract; import com.ibm.almaden.smartgrid.OPCAbstract; import com.ibm.almaden.smartgrid.AppUtilsAbstract; import com.ibm.almaden.smartgrid.VppAbstract; import com.ibm.almaden.smartgrid.util.ConfigFile; import com.ibm.almaden.smartgrid.util.Debug;
/** for xml output */ import org.jdom.Element; // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| // || Class OPCEden (Original Problem Cell || // |||||||||||||||||||||||||||||||||||||| /** ** ** ** OPCEden.java defines the "Original Problem Cell" * for the Eden model of bacteria growth. ** * OPCEden extends OPCAbstract * * The Eden model OPC describes a region of space representing the surface of a petri dish. If may contain entity objects such as bacteria, nutrients, etc. It may also have local properties that affect the behavior (reproduction rate) of the bacteria. The required methods, propagate(), and localInteraction(), determine how these entities reproduce and spread to neighboring OPCs based on other entities and properties that may be present. * ** An original problem cell is an "atomic" problem unit -- piece ** of the problem that represents a unit of computation (like an ** area (2D) or a volume (3D) that is exposed to some external ** interactions over time). OPCs interact with their ** neighbors -- sharing information to produce a larger (big picture) ** computation. That means, though, that an OPC must communicate ** its state with its neighboring OPCs at the end of each "time slice" ** so that the neighbor interaction can be computed in order to produce ** the next frame. ** * The creator of a problem computation sets up the collection of ** OPCs and also separates groups of OPCs into computable partitions ** (called Variable Problem Partitions -- VPPs) that are given to the ** compute agents to, well, compute. Each VPP (mostly running on a separate machine) must communicate its edges to the other VPPs ** * * OPCs are stored in collections of class OPCCollection. ** ** * For a picture showing how OPCs fit into VPPs refer to {@link OPCAbstract}. * * * The Eden model of bacterial growth. * * In the Eden model, each OPC represents a cell that may * contain an entity that represents one of 3 kinds of bacteria; A, B or C. * In this case, the interaction method causes A eats B, B eats C, * and C eats A. * In addition, the entities can propagate to their neighbors with * a specified probability where it will either be eaten by the neighbor or * eat the neighbor. * * ** @author >A HREF="mailto:kaufman@almaden.ibm.com"<James Kaufman>/A< ** @author >A HREF="mailto:toby@almaden.ibm.com"<Toby Lehman>/A< ** @author >A HREF="mailto:glenn@almaden.ibm.com"<Glenn Deen>/A< ** @version $Revision: 1.3 $ $Date: 2003/05/22 15:19:32 $ ** @see com.ibm.almaden.smartgrid.OPCAbstract ** @see com.ibm.almaden.smartgrid.OPCCollection ** @see EntityEden ** @see EntityAbstract */ // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| // public class OPCEden extends OPCAbstract implements Serializable, Cloneable { static final long serialVersionUID = -41318389852439458L; static private final String _className = "OPCEden";
/************************************************************************** ** OPCEden ** (empty) *********/ /** ** This class OPCEden creates an original problem cell ** for a predator prey calculation *************************************************************************** */ public OPCEden() { super._occupants = null; super._properties = null; } /************************************************************************** ** processNeighbor ** *******************/ /** * Given a neighboring OPC, see if any of the entities from it * will propagate to the list of Occupants for the current OPC * * @param OPCNeighbor OPC that is a neighbor of the current OPC * @param newOccupants ArrayList that contains current competing entities. * @param vpp_ The parent Vpp. * @param iteration_ The current iteration number * @return void *************************************************************************** */ private void processNeighbor(OPCEden OPCNeighbor, ArrayList newOccupants, VppAbstract vpp_, int iteration_, Random rnd_) { ArrayList hisOccupants = OPCNeighbor.getOccupants(); if (hisOccupants.size() > 0) { int numOccupants = hisOccupants.size(); // look at all of his occupants for (int j = 0; j <numOccupants; j++) { // get the occupant as an entity EntityEden ea = (EntityEden) (hisOccupants.get(j)); // generate the propagation probability for this entity double prob = getPropagationProb(ea, rnd_); if ((prob > ea.getPropProb()) && \ (entityNotPresent(ea, newOccupants))) { // if probability threshold exceeded and not already an occupant EntityAbstract child = ea.getChild(); //vpp_._valueMonitor.accumulateValueData\ (iteration_, child.getEntityID(), 1); // add to the new list of Occupants newOccupants.add(child); } } // for j (num occupants) } // size > 0 } /************************************************************************** ** getPropagationProb ** *******************/ /** * Generate the propagation probability for some entity * given the entity and properties of this OPC. * * If the OPC does not have any properties, then the next generated * random probability is returned. Otherwise the Property object is obtained * from the Properties collection and the probability is calculated based * on the Property. * This (somewhat unrealistic) method assumes that the first Property contains * a probability value. If the property ID matches \ the entity ID (type of bacteria) * then this value is added to the calculated propagation probability, * otherwise it is subtracted. * * @param ea entityAbstract * @param rnd_ Random rnd_ * @return probability *************************************************************************** */ private double getPropagationProb(entityAbstract ea, Random rnd_) { double prob = rnd_.nextDouble();
int entityID = ea.getentityID(); int numProps = 0; if (_properties != null) { numProps = _properties.size(); if (numProps > 0) { PropertyEden p = (PropertyEden) _properties.get(0); if (p.getPropertyID() == entityID) { prob += p.getProbability(); if (prob > 1.0) prob = 1.0; } else { prob -= p.getProbability(); if (prob <0.0) prob = 0.0; } } } return prob; } /** ******************************************************************************* * cloneOPC() * required method to return a clone of the OPC with a * copy of those objects in this OPC that may be modified. * * * Eden model requires that we do a deep copy of the occupants only * * The following variables are not required * in this eden model clone method but could be required * in other synchronized applications * * newOPC._properties = new Vector(); * newOPC._loc = this._loc; * newOPC._index = this._index;= * newOPC._edgeCollectionID = this._edgeCollectionID; * newOPC._edgeIndex = this._edgeIndex; * * @return a clone of this OPC **/ public OPCAbstract cloneOPC() { OPCEden newOPC = null; try { newOPC = (OPCEden)this.clone(); } catch (CloneNotSupportedException cns) { Debug.error(_className+"cloneOPC ","Error",cns); } // do deep copy of occupants ArrayList. ArrayList newOccupants = new ArrayList(); ArrayList oldOccupants = this.getOccupants(); if (oldOccupants == null || oldOccupants.size() == 0) { newOPC.setOccupants(null); } else { newOccupants.addAll(oldOccupants); newOPC.setOccupants(newOccupants); } // not null return newOPC; }; /************************************************************************** ** entityNotPresent ** *********************/ /** * Test an EntityEden object against an Array list and return "true" if * there is No EntityEden of the same type already in the ArrayList * * * @param ea_ An abstract entity * @param a_ An ArrayList of entities (EntityEden objects) * * @return true if this type of entity NOT already present. * *
*************************************************************************** */ public boolean entityNotPresent(EntityAbstract ea_, ArrayList a_) { // first make sure this class object is not already present int classID = ea_.getEntityID(); int numEnts = a_.size(); for (int i = 0; i < numEnts; i++) { EntityAbstract obj = (EntityAbstract)a_.get(i); int classID2 = obj.getEntityID(); // if already there, punt if (classID==classID2) return false; } // else return true; } /************************************************************************** ** initFromXML() ** *******************/ /** * This method is only needed if we defined new instance variable * for this class. Refer to EntityEden for an example of the required coding. * *************************************************************************** */ // public void initFromXML(Element OPCElement_) { // super.initCommonSubsetFromXML(OPCElement_); // } // getXML() /************************************************************************** ** getXML() ** *******************/ /** * This method is only needed if we defined new instance variable * for this class. Refer to EntityEden for an example of the required coding. *************************************************************************** */ // public Element getXML() { // Element OPCElement = super.getXmlElement(); // return OPCElement; // } // getXML() /************************************************************************** ** toString ** **************/ /** ** Provide good debug output This will pick up the output from the * OPCAbstract.toString() method and then append some information * about the occupants and properties. ** ** @return String that represents the values in the object *************************************************************************** */ public String toString() { // Put everything into a string buffer first (pick the right size), // and then turn into a string at the end. // StringBuffer sb = new StringBuffer(64); sb.append(super.toString()); sb.append(" OPCEden: "); if (_occupants != null) { sb.append("#Occupants="+_occupants.size()); } if (_properties != null) { sb.append(" #Properties="+_properties.size()); } return sb.toString(); } // end toString() } // Class OPCEden |
Code listing for OPCEden Propagate()
Following is the complete code for the OPCEden propagate()
method.
/************************************************************************** ** propagate ** **************/ /** * * All OPCs communicate with neighbors (local or remote) * propagate() for OPCEden determines what entities are * present at neighboring sites and clones them, adding any * new types of entities to this site. There is never more * than one type of entity represented. This step is done * before the entities are allowed to compete (eat each other) * which is done later by the localInteraction method. * Following that method call we know what bacteria spread to * what OPCs - and which ones survived. * * Note that the new "occupant" list is returned but not * stored back into the OPC. This is so that when the next * OPC is processed and they look back at me (as a neighbor) * they will see my old occupant status. * * In general, in the propagate() method you only want to * manipulate the list of occupants and not modify the OPC * or the properties. Use the localInteraction() method to * make changes to the OPC and Properties. * * @param collectionIndex_ The Index into the array of * OPCCollections for the * OPCCollection that this OPC belongs to. * @param vpp_ The parent VPP * @param iteration_ Current iteration (cycle) number * @param rnd_ Random number generator. * * @return Updated collection of occupants (entities) for this OPC. * *************************************************************************** */ public synchronized ArrayList propagate(int collectionIndex_, \ VppAbstract vpp_, int iteration_, Random rnd_) { String methodName = _className + ".propagate "; ArrayList newOccupants = new ArrayList(); ArrayList oldOccupants = super.getOccupants(); // uncomment the following if we wanted to use the appUtils class. //AppUtilsGeneric appUtil = \ (AppUtilsGeneric)OPCAbstract.getAppUtils(); if (oldOccupants.size() > 0) newOccupants.addAll(oldOccupants); // || ==============================================|| // || = Get all neighbors (whether local or remote =========|| // || ==============================================|| ArrayList tempArray = this.getAllOPCNeighbors(collectionIndex_, vpp_); Iterator iter = tempArray.iterator(); while (iter.hasNext()) { // get the collection element OPCEden OPCNeighbor = (OPCEden) iter.next(); // propagate neighbors entities to newOccupants processNeighbor(OPCNeighbor,newOccupants,vpp_,iteration_,rnd_); } // while hasNext // return the new list of occupants return newOccupants; } // propagate() |
Code listing for OPCEden localInteraction()
Following is the complete code for the OPCEden localInteraction()
method.
/************************************************************************** ** localInteraction ** **********************/ /** * After we learn from propagate which species of bacteria are * competing to live on this site in the next time step, we cycle * through all the competing occupants of this OPCEden * and see if, for each occupant, there is a predator that * eats the occupant. * * We then loop through the occupants again and remove the dead * bacteria. We then call the updateCount method which updates * the information about the number of entities for the chart. * * Finally we store the current list of occupants back into the OPC. * * * @param vpp_ The parent Vpp. * @param iteration_ The current iteration number * @param occupants_ ArrayList of the new entities for this OPC * This is the ArrayList of occupants that was returned by the propagate method. We are required to store it into the OPC. * * @return void * *************************************************************************** */ public synchronized void localInteraction(VppAbstract vpp_, \ int iteration_, ArrayList occupants_) { String methodName = _className + ".localInteraction "; // are there any occupants? if ((occupants_ != null) && (!occupants_.isEmpty())) { // yes, then loop through them for (int i = 0; i <occupants_.size(); i++) { for (int j = 0; j < occupants_.size(); j++) { if (i == j) continue; EntityEden obj1 = (EntityEden) occupants_.get(i); EntityEden obj2 = (EntityEden) occupants_.get(j); // obj2._foodID contains the type of food that obj2 eats. // so if it matches the EntityID for obj1, then obj2 eats obj1. if (obj2.isAlive() && (obj2.getFoodID() == obj1.getEntityID())) { //yes, then obj1 is dead obj1.setAlive(false); } } // for j } // for i. First loop checks for predators // finally loop through one more time and remove the dead ones for (Iterator iter = occupants_.iterator(); iter.hasNext();) { EntityEden obj1 = (EntityEden) iter.next(); if ( ! obj1.isAlive() ) { iter.remove(); } } // iterate. Second loop removed dead occupants } // end if not null or empty // update running totals of entities super.updateCounter(vpp_, iteration_, occupants_); // update the OPCAbstract super.setOccupants(occupants_); } //localInteraction() |
(Copyright IBM Corporation)
|