Actions

Network.java

From Santa Fe Institute Events Wiki

Revision as of 14:09, 15 June 2006 by Seoc (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

/*

* Network.java
*
* Created on January 18, 2005, 4:09 PM
* Modified June 14, 2006
* 
* This class generates a network, runs some
* net statistics, and writes it to a pajek-formatted file
*/

package CoopNetBlue; //import java.util.Random; import uchicago.src.sim.network.NetworkFactory; import uchicago.src.sim.network.EdgeFactory; import java.util.Formatter; import uchicago.src.sim.util.Random; import java.util.ArrayList; import uchicago.src.sim.gui.OvalNetworkItem; import rlriolo.ioutils.*; import java.io.PrintWriter; import java.util.HashSet; import uchicago.src.sim.util.*; import java.util.Vector;


/**

*
* @author Jack Waddell
*/

public class Network {

   //*******************************************************
   // static parameters
   // the main model
   public static CoopNetBlue model;
   
   //*******************************************************
   // Instance parameters
   public int[][]     adjacencyMatrix;  // Yes, it is Aij = 1 if j -> i.
   public int         networkSize;      // The number of agents
   public int         connectRadius;    // The radius for grid or SWN inits
   public double      reconnectProb;    // The prob or (re)wiring in (SWN) or random net
   // a pointer to the agent list,
   public ArrayList<CustomNode> agentList = new ArrayList<CustomNode>();
   
   // These are for writing a pajek-formatted file
   protected String		pajekFileName = "pajek";
   protected String 		outputDirName = "./";
   protected PrintWriter	pajekFile, plaintextPajekFile;
   
   
  
   ////////////////////////////////////////////////////////////////////////
   // Constructor
   public Network(int networkSize, int connectRadius, double reconnectProb){

this.networkSize = networkSize; this.connectRadius = connectRadius; this.reconnectProb = reconnectProb;

   }


   ///////////////////////////////////////////////////////////////////////
   // buildAdjacencyMatrix
   // Inputs: int netType, selects which specific type of matrix to form
   // Outputs: int[][], the adjacency matrix
   public int[][] buildAdjacencyMatrix(int netType){

switch(netType){ case 0 : return buildAdjacencyMatrix2DWS(); case 1 : return buildAdjacencyMatrixWS(); case 2 : return buildAdjacencyMatrixRand(); default: return buildAdjacencyMatrix2DWS(); }

   }
   
   ///////////////////////////////////////////////////////////////////////////
   //
   // buildAdjacencyMatrixWS
   // Develops an adjacency matrix for a Watts-Strogatz Small World 
   // network based on the given parameters.  Note that this 
   // implementation uses a disconnecting rewire, so that it is
   // possible to disconnect groups in the network.  It is also 
   // possible to have less than an average degree of 2x connectRadius, 
   // since a connection can be "overwritten" during the rewire.
   //
   //  Inputs:  double reconnectProb:  each neighbor connection 
   // has a probability p of being disconnected from the outgoing side (i) 
   // and reattached to a random node (including the one from which it 
   // was just disconnected, and any other nodes that j goes to.)]
   // connectRadius: the number of neighbors to either side of each node.  
   // Note that this often leads to cycles.
   
   public int[][] buildAdjacencyMatrixWS(){
       
       adjacencyMatrix = new int[networkSize][networkSize];

// Make the regular gride

       for(int i = 0; i < networkSize; i++){
           for(int j = i; j< networkSize; j++){
               if( (j <= (i + connectRadius) ) && (i!=j) ){
                   adjacencyMatrix[i][j] = 1;
                   adjacencyMatrix[j][i] = 1;
               }
               else if( (j >= (networkSize - connectRadius + i) ) && (i!=j)){
                   adjacencyMatrix[i][j] = 1;
                   adjacencyMatrix[j][i] = 1;
               }
               else{
                   adjacencyMatrix[i][j] = 0;
                   adjacencyMatrix[j][i] = 0;
               }
           }
       }
       

// Do random rewiring double randomDouble;

       for(int i = 0; i < networkSize; i++){
           for(int j = 1; j < networkSize; j++){
               randomDouble = model.getUniformDoubleFromTo(0,1);
               if((randomDouble < reconnectProb)&&

(adjacencyMatrix[i][j]==1)){ adjacencyMatrix[i][j] = 0; int randomi = j; do{ randomi = model.getUniformIntFromTo(0, networkSize - 1); if(model.rDebug > 2) System.out.printf("j = %d, randomi = %d, A[i][j] = %d\n", j,randomi, adjacencyMatrix[randomi][j]); } while (randomi == j || adjacencyMatrix[randomi][j] ==1);

adjacencyMatrix[randomi][j] = 1; adjacencyMatrix[j][randomi] = 1;

               }
           }
       }


       return adjacencyMatrix;
   }
   ///////////////////////////////////////////////////////////////////////////
   //
   // buildAdjacencyMatrix2DWS
   // Develops an adjacency matrix for a Toroidal - Watts-Strogatz Small 
   // World network based on the given parameters.  Note that this 
   // implementation uses a disconnecting rewire, so that it is
   // possible to disconnect groups in the network. 
   public int[][] buildAdjacencyMatrix2DWS(){
       // Make regular grid
       adjacencyMatrix = new int[networkSize][networkSize];
       int ix, iy, jx, jy;
       int size = (int) Math.floor(Math.sqrt(networkSize));
       System.out.printf("Size = %d \n", size);
       for(int i = 0; i < networkSize; i++){
           for(int j = i; j< networkSize; j++){
               
               ix = i % size;
               iy = i / size;
               
               jx = j % size;
               jy = j / size;
               
               double dx = Math.min( Math.min( Math.pow(jx - ix,2), 

Math.pow(jx + size - ix, 2)), Math.pow(jx - size - ix, 2) );

               double dy = Math.min( Math.min( Math.pow(jy - iy,2), 

Math.pow(jy + size - iy, 2)), Math.pow(jy - size - iy, 2) );

               if( (Math.sqrt(dx + dy) <= (connectRadius) ) && (i!=j) ){
                   adjacencyMatrix[i][j] = 1;
                   adjacencyMatrix[j][i] = 1;
               }
               
               else{
                   adjacencyMatrix[i][j] = 0;
                   adjacencyMatrix[j][i] = 0;
               }
           }
       }
       
       double randomDouble;
       // Do random rewiring
       for(int i = 0; i < networkSize; i++){
           for(int j = 1; j < networkSize; j++){
               randomDouble = model.getUniformDoubleFromTo(0,1);
               if((randomDouble < reconnectProb)&&

(adjacencyMatrix[i][j]==1)){ adjacencyMatrix[i][j] = 0; int randomi = j; do{ randomi = model.getUniformIntFromTo(0, networkSize - 1); System.out.printf("j = %d, randomi = %d, A[i][j] = %d\n", j,randomi, adjacencyMatrix[randomi][j]); } while (randomi == j || adjacencyMatrix[randomi][j] ==1);

adjacencyMatrix[randomi][j] = 1; adjacencyMatrix[j][randomi] = 1;

               }
           }
       }

System.out.printf("----> Finished 2DWS Adjacency Mat\n");

       return adjacencyMatrix;
   }
   
   
   ///////////////////////////////////////////////////////////////////////////
   //
   // buildAdjacencyMatrixStar
   // Develops an adjacency matrix for a Star Network, centered on i.
   public int[][] buildAdjacencyMatrixStar(int i){
       
       adjacencyMatrix = new int[networkSize][networkSize];
       int ix, iy, jx, jy;
       for(int k = 0; k < networkSize; k++){

for(int j = 0; j< networkSize; j++){ adjacencyMatrix[k][j] = 0; adjacencyMatrix[j][k] = 0; } }

for(int j = 0; j< networkSize; j++){ if(i!=j){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } }

System.out.printf("----> Finished Star Adjacency Mat\n");

       return adjacencyMatrix;
   }
   
   //////////////////////////////////////////////////////////////////
   // buildAdjacencyMatrixRand
   // Develops a symmetric, random adjacency matrix, so that the
   //  probability of an edge existing between any pair of nodes is
   //  reconnectProb.
   public int[][] buildAdjacencyMatrixRand(){
       
       adjacencyMatrix = new int[networkSize][networkSize];
       int i, j;

double randn;

       for(i = 0; i < networkSize; i++){

for(j = 0; j < networkSize; j++){ randn = model.getUniformDoubleFromTo(0, 1);

if (randn < reconnectProb){ adjacencyMatrix[i][j] = 1; adjacencyMatrix[j][i] = 1; } //else // System.out.printf("Randn = %f vs %f\n", randn, reconnectProb); } }

System.out.printf("----> Finished Random Adjacency Mat\n");

       return adjacencyMatrix;
   }


   ///////////////////////////////////////////////////////////////////////
   // buildAgentList
   // Develops an arrayList of CustomNodes interconnected based on the
   // adjacency matrix developed.
   public void buildAgentList(){

// Create all the agents

       for(int i = 0; i < networkSize; i++){
           OvalNetworkItem drawable = new OvalNetworkItem(0,0);

double strategy = model.getUniformDoubleFromTo(0, 1);

           CustomNode agent = new CustomNode(drawable, strategy);
           agentList.add(agent);
       }

// Create the edges between them, governed by the adjacency // matrix

       CustomEdge edge;
       double cc;
       CustomNode jnode, inode;
       for(int i = 0; i < networkSize; i++){
           for(int j = 0; j < networkSize; j++){
               if(adjacencyMatrix[i][j] == 1){
                   jnode = (CustomNode) agentList.get(j);
                   inode = (CustomNode) agentList.get(i);
                   edge = new CustomEdge(jnode, inode);
                   jnode.addOutEdge(edge);
                   inode.addInEdge(edge);

// This symmetritizes the network // i.e. makes undirected edge = new CustomEdge(inode, jnode); inode.addOutEdge(edge); jnode.addInEdge(edge);


               }
           }
       }
   }
   
   
   /////////////////////////////////////////////////////////////
   // printAdjacencyMatrix
   // a debugging tool.  Prints the adjacency matrix to the terminal
   public void printAdjacencyMatrix(){
       System.out.printf("--- Printing Adjacency Matrix, size %d ---\n", 

networkSize);

       for(int i = 0; i < networkSize; i++){
           for(int j = 0; j < networkSize; j++){

System.out.printf(" %d ", adjacencyMatrix[i][j]);

           }
           System.out.printf("\n");
       }
   }
   
   
   //////////////////////////////////////////////////////////////
   // writePajekNetwork
   // Writes the network to a file in pajek
   //  format.  Note: this version writes DOS type line feeds.
   public void writePajekNetwork(ArrayList<CustomNode> agentList){

String verts, arcs; // These are carriage return and line feed in DOS format. char cr = (char) 13; char lf = (char) 10;

// pajek requires the vertices and arcs separately. verts = String.format("*Vertices %d%c%c", networkSize, cr, lf); arcs = String.format("*Arcs %c%c", cr, lf);

// step through all nodes for(int i = 0; i < networkSize; i++){ CustomNode inode = (CustomNode) agentList.get(i); verts += String.format("%d \"N%d: %d\"", inode.getID() + 1, inode.getID(), inode.getUtility());

verts += String.format(" ic %s%c%c", inode.getMyPajekColor(),cr, lf);

ArrayList edgesInList = inode.getInEdges(); int numEdges = edgesInList.size(); CustomNode testNode = (CustomNode) (model.agentList).get(i); if (testNode != inode) System.out.printf("Nodes(%d) not equal\n", i); if ( (testNode.getOutDegree() != inode.getOutDegree()) || (testNode.getInDegree() != inode.getInDegree())) System.out.printf("Nodes(%d) have different degree\n", i); if (numEdges > 0) // if node has at least one neighbor, write the edges for(int j = 0; j < numEdges; j++){ CustomEdge edge = (CustomEdge)edgesInList.get(j); arcs += String.format("%d %d %c%c", ((CustomNode)edge.getFrom()).getID() + 1, ((CustomNode)edge.getTo()).getID() + 1, cr, lf); } } String s = verts + arcs; writeToPajekFile(s);

   }
   
   /////////////////////////////////////////////////////////////
   // writeLineToPajekFile
   // writes a single line to the pajek file
   public void writeLineToPajekFile ( String line ) {

if ( pajekFile == null ) { return; } else { pajekFile.println( line ); }

   }
   
   //////////////////////////////////////////////////////////
   // writeToPajekFile
   // Does the same.
   public void writeToPajekFile ( String line ) {

if ( pajekFile == null ) { return; } else { pajekFile.print( line ); }

   }
   
   //////////////////////////////////////////////////////////////
   // startPajekFile
   // opens a file to write the pajek network to.
   public PrintWriter startPajekFile () {

if ( model.rDebug > 0 ) System.out.println( "startPajekFile called!" ); pajekFile = null; String fullFileName = pajekFileName + String.format( "%02d.net", model.runNumber );

pajekFile = IOUtils.openFileToWrite( outputDirName, fullFileName, "r" ); if ( model.rDebug > 0 ) System.out.println( "startPajekFile completed!" );

return pajekFile;

   }
   
   //////////////////////////////////////////////////////////////
   // startPajekFile - overload
   // opens a file to write the pajek network to.  Calls it
   // by integer i
   public PrintWriter startPajekFile (int i) {

if ( model.rDebug > 0 ) System.out.println( "startPajekFile called!" ); pajekFile = null; String fullFileName = pajekFileName + String.format( "%03d.%02d.net", i, model.runNumber );

pajekFile = IOUtils.openFileToWrite( outputDirName, fullFileName, "r" );

if ( model.rDebug > 0 ) System.out.println( "startPajekFile completed!" ); return pajekFile;

   }
   
   //////////////////////////////////////////////////////////
   // endPajekFile
   // closes the open pajekFile
   public void endPajekFile ( ) {

IOUtils.closePWFile( pajekFile );

   }


   ///////////////////////////////////////////////////////////
   // getAverageCC1
   // Calculates the average 1-neighborhood clustering coefficient
   public double getAverageCC1(){

CustomNode node = null; double sum = 0; for(int i = 0; i < agentList.size(); i ++){ node = (CustomNode) agentList.get(i); sum += getNodeCC1(node); } return sum / (double) agentList.size();

   }


   //////////////////////////////////////////////////////////
   // getAverageCC2
   // Calculates the average 2-neighborhood clustering coefficient
   public double getAverageCC2(){

CustomNode node = null; double sum = 0; for(int i = 0; i < agentList.size(); i ++){ node = (CustomNode) agentList.get(i); sum += getNodeCC2(node); } return sum / (double) agentList.size();

   }


   /////////////////////////////////////////////////////////
   // union
   // Support function.
   // Returns the union of two array lists of nodes
   public ArrayList<CustomNode> union(ArrayList<CustomNode> l1, 

ArrayList<CustomNode> l2){ ArrayList<CustomNode> unionList = new ArrayList<CustomNode>(); unionList.addAll(l1); for(int i = 0; i < l2.size(); i ++){ CustomNode node = (CustomNode) l2.get(i); if (!unionList.contains(node)) unionList.add(node); } return unionList;

   }
   /////////////////////////////////////////////////////////////
   // intersection
   // Support function
   // Return the intersection of two array lists of nodes
   public ArrayList<CustomNode> intersection(ArrayList<CustomNode> l1, 

ArrayList<CustomNode> l2){ ArrayList<CustomNode> interList = new ArrayList<CustomNode>(); for(int i = 0; i < l1.size(); i ++){ CustomNode node = (CustomNode) l1.get(i); if (l2.indexOf(node) >-1) interList.add(node); } return interList;

   }
   /////////////////////////////////////////////////////////////
   // getNodeCC1
   // Computes the clustering coefficient CC1, as per Pajek documentation
   // This is the 1-neighborhood clustering coefficient
   public double getNodeCC1 (CustomNode node){

ArrayList<CustomNode> neighborsList = new ArrayList<CustomNode>(); // Get all neighbors neighborsList = union(node.getOutNodes(), node.getInNodes()); int sum = 0; int k = neighborsList.size(); for(int j = 0; j < k; j ++){ CustomNode jnode = (CustomNode) neighborsList.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes();

sum += (intersection(nOut, neighborsList)).size(); sum += (intersection(nIn, neighborsList)).size();

} double cc1 = 0; if (k > 1) cc1 = (double)sum/( 2* (double)k * (double)(k-1)); return cc1;

   }


   /////////////////////////////////////////////////////////////
   // getNodeCC2
   // computes the clustering coefficient CC2, as per Pajek documentation
   // E(G1(v))/E(G2(v))
   // This is the 2-neighboorhood clustering coefficient
   public double getNodeCC2 (CustomNode node){

// calc E(G1(v)) = sum1 ArrayList<CustomNode> neighbors1List = new ArrayList<CustomNode>(); ArrayList<CustomNode> neighbors2List = new ArrayList<CustomNode>(); neighbors1List = union(node.getOutNodes(), node.getInNodes()); neighbors2List.addAll(neighbors1List);

int sum1 = 0; int k = neighbors1List.size(); for(int j = 0; j < k; j ++){ CustomNode jnode = (CustomNode) neighbors1List.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes();

sum1 += (intersection(nOut, neighbors1List)).size(); //sum1 += (intersection(nIn, neighbors1List)).size();

neighbors2List = union(neighbors2List, union(nOut, nIn)); }

//System.out.printf("For node %d sum1 = %d\n", node.getID(), sum1);


int index = neighbors2List.indexOf(node); while (index > 0){ //System.out.printf("node index = %d\n", index); neighbors2List.remove(index); index = neighbors2List.indexOf(node); }

// calc E(G2(v)) = sum2 int sum2 = 0; int ind1, ind2; for(int j = 0; j < neighbors2List.size(); j++){

CustomNode jnode = (CustomNode) neighbors2List.get(j); ArrayList<CustomNode> nOut = jnode.getOutNodes(); ArrayList<CustomNode> nIn = jnode.getInNodes();

sum2 += (intersection(nOut, neighbors2List)).size(); //sum2 += (intersection(nIn, neighbors2List)).size();

ind1 = neighbors2List.indexOf(jnode); ind2 = neighbors2List.lastIndexOf(jnode); if (ind1 != ind2) System.out.printf ("Node %d in list multiple times\n", jnode.getID());

}

//System.out.printf("For node %d sum1 = %d\n", node.getID(), sum2);


double cc2 = 0; if (sum2 > 0) cc2 = (double)sum1/(double)sum2; return cc2;

   }



   /////////////////////////////////////////////////////////
   // printList
   // Debug tool
   // Prints the contents of an ArrayList
   public void printList(ArrayList<CustomNode> list){

for(int i = 0; i < list.size(); i++){ CustomNode node = (CustomNode) list.get(i); System.out.printf("%d, ", node.getID());

} System.out.printf("\n");

   }
   ///////////////////////////////////////////////////////////
   // PickRandomEdge
   // Picks a random edge with uniform probability in O(m/(n*n))
   //   (I think)
   public CustomEdge pickRandomEdge(){

CustomEdge edge = null; CustomNode inode; CustomNode jnode; do{ inode = agentList.get(model.getUniformIntFromTo(0, agentList.size() -1)); do{ jnode = agentList.get(model.getUniformIntFromTo(0, agentList.size() -1)); } while (inode == jnode);

if ( (jnode.getOutNodes()).contains(inode)) edge = getEdgeFromTo(jnode, inode); } while (edge == null); return edge;

   }


   ///////////////////////////////////////////////////////////
   // selectRandomUncoupledPair
   // Selectrs a random pair of nodes with uniform probability.
   public CustomNode[] selectRandomUncoupledPair(){

boolean pass = false; CustomNode inode, jnode; int i, j; CustomEdge edge; do{ i = model.getUniformIntFromTo(0, agentList.size() -1); do{ j = model.getUniformIntFromTo(0, agentList.size() -1); } while (i == j);

inode = (CustomNode) agentList.get(i); jnode = (CustomNode) agentList.get(j); if ( !(jnode.getOutNodes()).contains(inode)){ pass = true; } } while (!pass); CustomNode[] nodes = {inode, jnode}; return nodes;

   }
   ////////////////////////////////////////////////////////////
   // selectRandomUncoupledNode
   // 
   public CustomNode selectRandomUncoupledNode(CustomNode jnode){

boolean pass = false; CustomNode inode = null; int i, j = jnode.getID(); CustomEdge edge; // get a list of the nodes, but make sure it isn't the main list // 'cause we're gonna shuffle it ArrayList <CustomNode> nodesList = new ArrayList<CustomNode>(); nodesList.addAll(agentList); SimUtilities.shuffle(nodesList, Random.uniform);

i = 0; int k = 0; do{

inode = (CustomNode) nodesList.get(i); if (inode != jnode){ if ( !(jnode.getOutNodes()).contains(inode)){ pass = true; } } i++; if (i == nodesList.size()){ i = 0; k ++; } } while ( !pass && k < 2 );

if (k == 2){ do{ i = model.getUniformIntFromTo(0, agentList.size() - 1); inode = (CustomNode) agentList.get(i); } while ( i == j || (jnode.getOutNodes()).contains(inode)); } return inode;

   }


   // getters and setters
   public String getPajekFileName () { return pajekFileName; }
   public void setPajekFileName ( String s ) {

pajekFileName = s;

   }
   
   
   public String getOutputDirName () { return outputDirName; }
   public void setOutputDirName ( String s ) {

outputDirName = s;

   }
   public int getNetworkSize() {return networkSize;}
   public ArrayList<CustomNode> getAgentList() {return agentList;}
   
   public PrintWriter getPajekFile () { return pajekFile; }
   
   public CustomEdge getEdgeFromTo(CustomNode jnode, CustomNode inode){

CustomEdge edge; HashSet edgeList = inode.getEdgesFrom(jnode); Object[] edges = edgeList.toArray(); // get the edge object connected to jnode edge = ((CustomEdge)edges[0]); return edge;

   }
   //**************************************************
   // Static Methods
   public static void setModel(CoopNetBlue m){model = m;}

}