To promote agent-based graph analysis with MASS, we extended the
Places class to GraphPlaces. Users can import graph data from a variety
of file formats or define graphs dynamically by creating vertices and
edges at runtime. The following example code propagates agents over a
biological network to search for network motifs. This snippet starts by
instantiating a new GraphPlaces object and reading graph data in from a
DSL file. DSL files represent a proprietary format for graph data. It
then adds a new vertex and edge to the graph, uses callAll
to invoke the updateState method at each vertex within the
graph, and exchangeAll to tell each vertex to invoke the
forwardMsg method on each of its neighbors.
import MASS.*;
public class GraphCreation {
public void main(String[] args) {
MASS.init( );
int gpHandle = 0;
GraphPlaces graph = new GraphPlaces(gpHandle, BionetVertex.class.getName());
graph.loadDSLFile("/home/NETID/foobar/input.dsl");
graph.addVertex();
int srcVertex = 99;
int destVertex = 100;
graph.addEdge(srcVertex, destVertex);
int updateStateFuncID = 0;
graph.callAll(updateStateFuncID);
int forwardMsgFuncID = 1;
graph.exchangeAll(forwardMsgFuncID);
Agents searcher = new Agents(2, "Motif", graph, 101);
crawler.doWhile(()->crawlers.hasAgents());
MASS.finish();
}
}
public class Motif extends Agent {
@onCreation public void init( ) { ...; }
@onArrival public void walk( ) { ...; }
}Empty Graph Constructor
GraphPlaces(int handle, String className)
Constructor initializes an empty graph.
Parameters: int handle - A unique identifier that
designates a group of places. Must be unique over all machines.
String className - Name of the user-implemented class
VertexPlaces are constructed from.
Empty Graph Constructor With Partition
public GraphPlaces(int handle, String className, int PARTITIONS_SIZE)
Constructor initializes an empty graph with specified partition size. Vertices in the same partition are assigned to the same node.
Parameters: int handle - A unique identifier that
designates a group of places. Must be unique over all machines.
String className - Name of the user-implemented class
VertexPlaces are constructed from.
int PARTITION_SIZE - Defines the maximum number of
vertices per partition.
GraphPlaces supports four file input types, two of which are propreitary to the UW Bothell distributed systems lab.
The DSL file format is a proprietary graph file format that can be ingested by MASS in parallel by all nodes within the cluster. The format itself represents an adjacency list and looks as follows:
0=1,1
1=0,1;2,1;3,1;4,1
2=1,1;3,1
3=1,1;2,1;4,1
4=1,1;3,1
There is no header to the file and the vertices must be 0-indexed.
The integer to the left of the = is the vertex ID and the
comma-deliminted pairs to the right of it is its edge list
(<vertex_id>;<edge_weight>). Files of this
format can be imported into MASS by first instantiating a GraphPlaces
object and then calling the loadDSLFile function and
passing it the absolute path of the file. It must not be a relative
path. This is because every node in the cluster will process the file
and nodes other than master will need to the absolute path in order to
find the file. An example can be seen below:
import MASS.*;
public class GraphCreation {
public void main(String[] args) {
MASS.init( );
int gpHandle = 0;
GraphPlaces graph = new GraphPlaces(gpHandle, BionetVertex.class.getName());
graph.loadDSLFile("/home/NETID/foobar/input.dsl");
MASS.finish();
}
}SAR is another properietary file format for importing graphs into MASS. It was started as a parallel I/O graph file format and named after the group members whom would be benefiting from its design. Unfortunately, it is not complete and will not work for graphs with more than 10 vertices. As it is currrently, it should not be used. This document will be updated if/when it is ready for use. An example of the file format is shown below:
9,9,9,9,9,9,9,9,9,9
1 2 3 4 5 6 7 8 9
0 2 3 4 5 6 7 8 9
0 1 3 4 5 6 7 8 9
0 1 2 4 5 6 7 8 9
0 1 2 3 5 6 7 8 9
0 1 2 3 4 6 7 8 9
0 1 2 3 4 5 7 8 9
0 1 2 3 4 5 6 8 9
0 1 2 3 4 5 6 7 9
0 1 2 3 4 5 6 7 8
loadDSLFile loads the DSL formatted graph file, from the provided path, into the distributed GraphPlaces object.
Parameters:
String filePath - The path to the DSL formatted graph
file. Note that this MUST be an absolute path if running MASS with more
than one node.
loadSARFile loads the SAR formatted graph file, from the provided path, into the distributed GraphPlaces object.
Parameters:
String filePath - The path to the SAR formatted graph
file. Note that this MUST be an absolute path if running MASS with more
than one node.
Return:
The total size of the distributed graph.
Adds an empty vertex to the graph
Parameters:
Return:
The vertex ID. Returns -1 if vertex is unable to be added.
Adds a vertex with unique identifier, vertexId to the
graph
Parameters:
Object vertexId – Unique Identifier of the vertex. Must
be unique and implement the hashCode and
equals methods.
Return:
The vertex ID. Returns -1 if vertex is unable to be added.
Adds a vertex with a unique identifier and arguments to initialize
the object extending VertexPlace.
Parameters:
Object vertexInitParam – Argument(s) to create vertex
inorder to initialize vertex
Return:
Integer used for global indexing. Returns -1 if vertex is unable to be added.
Removes the vertex associated with the provided vertexId object.
Parameters:
Object vertexId – Unique Identifier of the vertex. Must
be unique and implement the hashCode and
equals methods.
Return:
True if the vertex was successfully removed, false otherwise.
Removes the vertex associated with the provided vertex ID.
Parameters:
int vertexId – The vertex ID associated with the vertex
the user wishes to remove.
Return:
True if the vertex was successfully removed, false otherwise.
Returns the vertex associated with the provided vertexId object.
Parameters:
Object vertexId – Unique Identifier of the vertex. Must
be unique and implement the hashCode and
equals methods.
Return:
The vertex associated with the provided vertex ID object.
Returns the vertex associated with the provided vertex ID.
Parameters:
int vertexId – The vertex ID associated with the vertex
the user wishes to retrieve.
Return:
The vertex associated with the provided vertex ID.
Parameters:
int vertexId – The vertex ID.
Return:
The ID of the node that owns the vertex associated with the provided vertex ID.
Adds an edge to the graph between the provided vertexID and neighborID with a default weight of 1.0. The vertex and neghbor vertices must exist at the time of edge creation.
Parameters:
int vertexId – The source vertex ID.
int neighborId - The neighbor/destination ID.
Return:
True if the edge was successfully added, false otherwise.
Adds an edge to the graph between the provided vertexID and neighborID with the provided weight. The vertex and neghbor vertices must exist at the time of edge creation.
Parameters:
int vertexId – The source vertex ID.
int neighborId - The neighbor/destination ID.
double weight – Weight of the edge.
Return:
True if the edge was successfully added, false otherwise.
Adds an edge to the graph between the provided vertexID and neighborID with a default weight of 1.0. The vertex and neghbor vertices must exist at the time of edge creation.
Parameters:
Object vertexId – Unique Identifier of the source
vertex. Must be unique and implement the hashCode and
equals methods.
Object neighborId - Unique Identifier of the destination
vertex. Must be unique and implement the hashCode and
equals methods.
Return:
True if the edge was successfully added, false otherwise.
Adds an edge to the graph between the provided vertexID and neighborID with the provided weight. The vertex and neghbor vertices must exist at the time of edge creation.
Parameters:
Object vertexId – Unique Identifier of the source
vertex. Must be unique and implement the hashCode and
equals methods.
Object neighborId - Unique Identifier of the destination
vertex. Must be unique and implement the hashCode and
equals methods.
double weight – Weight of the edge.
Return:
True if the edge was successfully added, false otherwise.
Removes the edge between the provided vertex and neighbor IDs.
Parameters:
int vertexId – The vertex ID of the source vertex.
int neighborId – The vertex ID of the neighbor or
destination.
Return:
True if the edge was successfully removed, false otherwise.
Removes the edge between the provided vertex and neighbor IDs.
Parameters:
Object vertexId – Unique Identifier of the vertex that
is the source of the edge. Must be unique and implement the
hashCode and equals methods.
Object neighborId – Unique Identifier of the vertex that
is the neighbor/destination of the edge. Must be unique and implement
the hashCode and equals methods.
Return:
True if the edge was successfully removed, false otherwise.
Creates a GraphModel object containing all the vertices
as instances of VertexModel. Each instance of VertexModel
object contains a a list of neighors. Weight is not supported
Return
GraphModel object representing GraphPlaces
graph
public void setGraph(final GraphModel newGraph)
Reinitilizes graph to blank and creates a new distributed graph based
on the provided GraphModel. Weighted edges not
supported.
Parameter:
final GraphModel newGraph – GraphModel object that will be the new graph.
Given the object ID of the vertex, it returns a VertexMetaValues object containing meta values such as the vertex ID and node ID where the vertex is located.
Parameter:
Object vertexId – Unique Identifier of the vertex. Must
be unique and implement the hashCode and
equals methods.
Return:
The VertexMetaValues object associated with the provided vertexId object.
Initiates a callAll across all vertices within the graph to invoke the function associated with the provided functionId.
Parameter:
int functionId - The ID associated with the function the
caller wishes to invoke on the vertices within the graph.
Initiates a callAll across all vertices within the graph to invoke the function associated with the provided functionId.
Parameter:
int functionId - The ID associated with the function the
caller wishes to invoke on the vertices within the graph.
Object argument - An object containing the argument the
caller wishes to pass to the invoked function.
Initiates a callAll across all vertices within the graph to invoke the function associated with the provided functionId.
Parameter:
int functionId - The ID associated with the function the
caller wishes to invoke on the vertices within the graph.
Object argument - An object containing the argument the
caller wishes to pass to the invoked function.
Return:
An array of return values from the invoked functions on each vertex, ordered by vertex ID.
ExchangeAll tells all vertices within the graph to invoke the function associated with the provided functionID on each of its neighboring vertices and store the data within the calling vertex.
Parameter:
int destinationHandle - The handle of the GraphPlaces
object for which the exchangeAll results should be aggregated to. This
will most often be the handle of the GraphPlaces object that is calling
the function.
int functionId - The ID associated with the function the
caller wishes to invoke on neighboring vertices.
Although the underlying implementation differs, the usage of the lambda-based callAll is identical to that in Places.
public void callAll(SerializableCAFunction<Place> function)
public <A> void callAll(SerializableCAFunctionWithArg<Place, A> function, Object argument)
public <A,R> Object callAll(SerializableCAFunctionWithReturn<Place, A, R> function, Object[] argument)
In addition, these reduce-related methods are inherited from Places:
public <R> R reduce(SerializableFunction<Place, R> mapper, SerializableBinaryOperator<R> reducer)
public int count()
public Place collectBest(SerializableBinaryOperator<Place> reducer)
public List<Place> collectTopK(int k, SerializableBinaryOperator<Place> better)
Please refer to the Places page for detailed information.
public void doAll(int callAllFunctionId, Object argument, int destinationHandle, int exchangeAllFunctionId, int numberOfIterations)
This function is inherited from Places. Please refer to the Places page for detailed information.
VertexPlace is the base class for which vertex implementation can be created and used within GraphPlaces.
Return:
An array containing the vertex IDs of each of the vertices neighbors.
Return:
An array containing the weights of each of the edges between this
vertex and each of its neighbors. Note that this isn’t ordered but will
share an index with the array returned from getNeighbors.
To determine which edge the weight belongs to, use the index of weight
to lookup the neighbor from this function call.
The HIPPIE file format describes a protein network in the form of an
edge list. Each line in a HIPPIE tab-delimited file represents a
protein-protein interaction and a mapping of attributes associated with
that interaction. Support is provided by the Hippie class
and is found within the
edu.uw.bothell.css.dsl.MASS.graph.hippie package. This
class extends from GraphPlaces and provides facilities for reading in,
and working with, HIPPIE graph data. When adding edges to the graph,
HIPPIE attributes can be added as well. These are provided as a String
and follow the same format as the attributes field within the HIPPIE
file format. An example attributes string looks like this:
experiments:in vivo;pmids:9334256,16189514,16713569;sources:HPRD,I2D,Rual05,Lim06.
The are key/list pairs that are semi-colon delimited. keys are separated
from value lists using a colon, and list values are comma delimited. The
example attribute string will create the following edge attribute
map:
Map<String, String[]>{
"experiments": {"in vivo"},
"pmids": {"9334256","16189514","16713569"},
"sources": {"HPRD","I2D","Rual05","Lim06"},
}An example of the file format is as follows:
AL1A1_HUMAN 216 AL1A1_HUMAN 216 0.76 experiments:in vivo,Two-hybrid;pmids:12081471,16189514,25416956;sources:HPRD,BioGRID,IntAct,MINT,I2D,Rual05
ITA7_HUMAN 3679 ACHA_HUMAN 1134 0.73 experiments:in vivo,Affinity Capture-Western,affinity chromatography technology;pmids:10910772;sources:HPRD,BioGRID,I2D
NEB1_HUMAN 55607 ACTG_HUMAN 71 0.65 experiments:in vitro,in vivo;pmids:9362513,12052877;sources:HPRD
SRGN_HUMAN 5552 CD44_HUMAN 960 0.63 experiments:in vivo;pmids:9334256,16189514,16713569;sources:HPRD,I2D,Rual05,Lim06
GRB7_HUMAN 2886 ERBB2_HUMAN 2064 0.9 experiments:in vitro,in vivo,Reconstituted Complex,protein array,affinity chromatography technology,nuclear magnetic resonance,x-ray crystallography,competition binding,pull down;pmids:9079677,16273093,12975581,12061724,17875712;sources:HPRD,BioGRID,MINT,I2D,IntAct
PAK1_HUMAN 5058 ERBB2_HUMAN 2064 0.73 experiments:in vivo,Affinity Capture-Western,affinity chromatography technology;pmids:9774445;sources:HPRD,BioGRID,I2D,STRINGConstructs a HIPPIE graph with the provided handle and defaults to using the HIPPIEVertex class as its vertex implementation.
Parameters:
int handle - The handle to be assigned to the HIPPIE
instance. Must be unique.Constructs a HIPPIE graph with the provided handle and allows the caller to specify the vertex implementation to use.
Parameters:
int handle - The handle to be assigned to the HIPPIE
instance. Must be unique.
String className - The class name of the vertex
class implementation to be used by the graph. This MUST extend from
HippieVertex.
Constructs a HIPPIE graph with the provided handle, className, and HIPPIE filePath. This will populate the graph with the data from the provided file.
Parameters:
int handle - The handle to be assigned to the HIPPIE
instance. Must be unique.
String className - The class name of the vertex
class implementation to be used by the graph. This MUST extend from
HippieVertex.
String filePath - Path to the HIPPIE formatted graph
file. Note that this must be an absolute path if running MASS with more
than one node.
loadFromFile loads graph data from the provided HIPPIE formatted graph file.
Parameters:
String filePath - Path to the HIPPIE formatted graph
file. Note that this must be an absolute path if running MASS with more
than one node.MATSim is an XML format that was created as a traffic simulation
framework called Multi-Agent Traffic Simulation. The MATSim network file
is an edge list format with two second-level lists: nodes and links. The
nodes list contains a list of all vertices within the network whereas
the links list contains the list of edges. Support for this file format
is provided by the Matsim class and is found within the
edu.uw.bothell.css.dsl.MASS.graph.matsim package. Edges
within MATSim graphs can contain all of the edge attribute data found
within the file. This can consist of speed, capacity, number of lanes,
etc… An example of this file format is as follows:
<network>
<nodes>
<node id="1" x="665498.5915828889" y="6600721.058093354" ></node>
<node id="10" x="658803.7360160261" y="6575644.324923517"></node>
<node id="100" x="566282.7735573719" y="6454558.626888261"></node>
<node id="10000" x="408774.9462956431" y="6233917.802557087"></node>
<node id="10001" x="408772.02211252623" y="6234167.648466459"></node> ...
</nodes>
<links>
<link id="pt_99992" from="pt_740057809" to="pt_740057653" length="257.27792215211286" freespeed="8.333333333333334" capacity="500.0" permlanes="1.0" oneway="1" modes="pt" ></link>
<link id="pt_99996" from="pt_740057599" to="pt_740057756" length="157.21884660387735" freespeed="8.333333333333334" capacity="500.0" permlanes="1.0" oneway="1" modes="pt" ></link>
<link id="pt_99997" from="pt_740057688" to="pt_740057647" length="207.21244492773178" freespeed="8.333333333333334" capacity="500.0" permlanes="1.0" oneway="1" modes="pt" ></link>
<link id="pt_99998" from="pt_740057647" to="pt_740057623" length="378.77959250564095" freespeed="8.333333333333334" capacity="500.0" permlanes="1.0" oneway="1" modes="pt" ></link>
<link id="pt_99999" from="pt_740057623" to="pt_740057686" length="292.07787848782823" freespeed="8.333333333333334" capacity="500.0" permlanes="1.0" oneway="1" modes="pt" ></link>
</links>
</network>Constructs a MATSim graph with the provided handle and defaults to using the MatsimVertex class as its vertex implementation.
Parameters:
int handle - The handle to be assigned to the MATSim
instance. Must be unique.Constructs a MATSim graph with the provided handle and allows the caller to specify the vertex implementation to use.
Parameters:
int handle - The handle to be assigned to the MATSim
instance. Must be unique.
String className - The class name of the vertex
class implementation to be used by the graph. This MUST extend from
MatsimVertex.
Constructs a MATSim graph with the provided handle, className, and MATSim filePath. This will populate the graph with the data from the provided file.
Parameters:
int handle - The handle to be assigned to the MATSim
instance. Must be unique.
String className - The class name of the vertex
class implementation to be used by the graph. This MUST extend from
MatsimVertex.
String filePath - Path to the MATSim formatted graph
file. Note that this must be an absolute path if running MASS with more
than one node.
loadFromFile loads graph data from the provided MATSim formatted graph file.
Parameters:
String filePath - Path to the MATSim formatted graph
file. Note that this must be an absolute path if running MASS with more
than one node.The GraphAgent class extends SmartAgent and
implements the Serializable interface. It is designed to
represent agents in a graph-based simulation. Each agent can be
initialized with specific parameters, migrate between different nodes,
and interact with other agents. The class includes functionality for
distributing agents across computing nodes and managing their behavior
during the simulation.
GraphAgent()
Initializes a new instance of the agent by calling the superclass
(SmartAgent) constructor.
GraphAgent(Object arg)
Initializes a GraphAgent object with a specific argument
passed as an object. The argument can be used to configure specific
properties of the agent during initialization.
Parameters:
arg - An object containing initialization data for the
agent.
responsible for distributing agents across different nodes in a distributed environment. It calculates how many agents should be assigned to each node based on the total population and system size.
Parameters:
initPopulation - The total number of agents to be
distributed.size - The size of the grid or matrix where agents are
placed.index - The current index of the place where agents
will be mapped.offset - An additional offset used during mapping.Returns:
The number of agents that should be assigned to a particular node based on its rank and system size.
The SmartAgent class represents agents that can migrate
between places and perform actions based on their environment. It builds
upon the base Agent class by adding advanced capabilities
for managing agent behavior in a distributed simulation environment.
nextNode - An integer representing the next destination
node for the agent.prevNode - An integer representing the previous node
from which the agent migrated.justMigrated: A boolean indicating whether the agent
has just migrated.itinerary: An array of integers representing the
navigation path of the agent.OriginalSourceNode: An integer representing the
original source node where the agent was first instantiated.level: An integer representing the current depth or
level of the agent in a tree-like structure.BothBranch_, LeftBranch_,
RightBranch_: Constants used for tree propagation to
specify whether to propagate along both branches, left branch, or right
branch.SmartAgent()
Initializes a new instance of the agent by calling the superclass
(Agent) constructor.
SmartAgent(Object arg)
Initializes a SmartAgent object with a specific argument passed as an object. The argument can be used to configure specific properties of the agent during initialization.
Parameters:
arg - An object containing initialization data for the
agent.This method initializes the source node and itinerary of the smart agent.
Parameters:
place: The original source node where the agent is
first instantiated.This method returns the next destination node for migration.
Returns:
The next node index.
This method sets the next destination node for migration.
Parameters:
nextNode: The index of the next node.This method sets an itinerary (navigation path) for the agent.
Parameters:
itinerary: An array of integers representing the
navigation path.This method migrates an agent to another place and propagates child agents to neighboring nodes (except previous and next nodes).
This method propagates agents downwards in a tree structure by migrating them to lower-indexed neighbors and spawning child agents along available edges (lower indexed neighbors).
This method migrates an agent to a neighboring place with the minimum weight based on some criteria (e.g., distance or cost).
This method migrates an agent to a neighboring place with the maximum weight based on some criteria.
This method migrates an agent to a randomly selected neighboring place.
This method propagates agents through a binary tree structure by migrating either along both branches, left branch only, or right branch only based on input parameters.
Parameters:
path: Specifies which branches to propagate along
(BothBranch_, LeftBranch_, or RightBranch_).arg: Additional arguments passed during
propagation.
This method migrates an agent back to the graph vertex where it was first assigned.
public class CrawlerGraphMASS extends GraphAgent implements Serializable {
// function identifiers
public static final int init_ = 0;
public static final int onArrival_ = 1;
public static final int departure_ = 2;
public static final int getTriangle_ = 3;
public static final int propagateDown_ = 4;
public static final int migrateSource_ = 5;
public Object callMethod(int functionId, Object argument) {
switch (functionId) {
case init_:
return init(argument);
case propagateDown_:
return propagateDown(argument);
case migrateSource_:
return migrateSource(argument);
case getTriangle_:
return getTriangle(argument);
}
return null;
}
/**
* Is the default constructor.
*/
public CrawlerGraphMASS() {
super();
}
/**
* Is the actual constructor.
*
* @param arg an integer array that carries nodes this agent or
* parent has travelled so far.
*/
public CrawlerGraphMASS(Object arg) {
//Commenting for Auto Agent Migration
//itinerary = (int[]) arg;
super(arg);
MASS.getLogger().debug("agent(" + getAgentId() + ") was born.");
}
/**
* @param arg an integer array that includes only the first place to go.
* @return nothing
*/
public Object init(Object arg) {
int[] itinerary = (int[]) arg;
setitinerary(itinerary);
return null;
}
/**
* @param arg assumes null.
* @return a string that includes three vertices forming a triagle
*/
public Object getTriangle(Object arg) {
String triangle = "";
triangle += "agent(" + Integer.toString(getAgentId()) + "): ";
for (int i = 0; i < 4; i++)
triangle += Integer.toString(itinerary[i]) + " ";
return triangle;
}
}
public class CountTrianglesGraphMASS {
private static final boolean CYTOSCAPE_LISTENER = false;
private static int sequentialId = 2;
/**
* Counts and enumerates all triangles in a given graph
*
* @param args TBD
*/
public static void main(String[] args) {
// Read and validate input parameters
if (args.length != 1) {
System.err.println("Usage: java -jar TriangleCounting.jar <dsl_graph_file>");
System.exit(-1);
}
String filePath = args[0];
MASS.setLoggingLevel(LogLevel.DEBUG);
MASS.init(10000000);
System.out.println("Begin data space generation");
long begin = System.currentTimeMillis();
GraphPlaces network = new GraphPlaces(1, NodeGraphMASS.class.getName());
try {
network.loadDSLFile(filePath);
} catch(Exception e) {
System.err.println("Error reading in graph file: " + e);
System.exit(3);
}
long end = System.currentTimeMillis();
System.out.println("Import complete\nImport time: " + (end - begin) / 1000.0 + " s");
run_triangle_counting((GraphPlaces) network);
System.out.println("Finish MASS");
MASS.finish();
}
public static void run_triangle_counting(GraphPlaces network) {
Graph graph = network;
List<VertexModel> vertices = graph.getGraph().getVertices();
int nVertices = vertices.size();
System.out.println("Number of Vertices is : " + nVertices);
try {
network.callAll(NodeGraphMASS.init_);
// Time measurement starts
System.out.println("Go! Graph");
long startTime = System.currentTimeMillis();
// Instantiate an agent at each node
Agents crawlers = new Agents(sequentialId++, CrawlerGraphMASS.class.getName(), null, network, nVertices);
Integer [] indices = vertices.stream()
.map(vertex -> {
Object value = MASSBase.distributed_map.get(vertex.id);
if (value == null) {
value = vertex.id;
}
return (int) value;
} )
.collect(Collectors.toList())
.toArray((Integer[]) Array.newInstance(Integer.class, 0));
int[][] itineraries = new int[nVertices][4];
for (int i = 0; i < nVertices; i++) {
for (int j = 0; j < 4; j++) {
itineraries[i][j] = (j == 0) ? indices[i] : -1;
}
}
crawlers.callAll(CrawlerGraphMASS.init_, (Object[]) itineraries);
// For stats
int totalAgents = 0; // max # agents in computation
for (int i = 0; i < 3; i++) {
Object currStep = (Object) (new Integer(i));
System.out.println("*** iteration = " + i + "************");
if (i < 2)
{
crawlers.callAll(CrawlerGraphMASS.propagateDown_, currStep);
}
else {
crawlers.callAll(CrawlerGraphMASS.migrateSource_, currStep);
}
crawlers.manageAll();
// For stats
int nAgents = crawlers.nAgents();
totalAgents += nAgents;
System.out.println("*** Total Agents = " + nAgents + "************");
}
// Get results
int nAgents = crawlers.nAgents();
System.out.println("# triangles = " + nAgents);
// Time measurement ends
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("Elapsed time = " + elapsedTime);
// Stats
System.out.println("Statistics: total #agents = " + totalAgents);
// Enumerate all triangles
int[][] dummyArgs = new int[nAgents][1];
Object[] triangles = (Object[]) crawlers.callAll(CrawlerGraphMASS.getTriangle_, (Object[]) dummyArgs);
for (int i = 0; i < triangles.length; i++)
System.out.println(i + ": " + (String) triangles[i]);
network.callAll(NodeGraphMASS.display_);
} catch (Exception e) {
System.err.println("Error in execution: " + e.getMessage());
e.printStackTrace(System.err);
}
}
}