Model Code Supplement

This document contains supplemental material for the article “Modeling Social Ties and Household Mobility” by Sara Metcalf in the Annals of the Association of American Geographers. Full model code is provided below in Java syntax as implemented in AnyLogic 5.5 (Part 1) and as employed for data processing (Part 2). The author may be contacted at smetcalf@buffalo.edu for further information.

 

Part 1. AnyLogic Model Code

1A. Main Active Object Class

Main Active Object Parameters

integer minConnect = 3; //minimum number of social ties per household

real localProb, nwConst, nwInc, nwDist, nwNorm, nwRace, nwChild //parameters set in Monte Carlo experiments

real ownMoveRate = 0.1; //frequency of move decisions per year

real rentMoveRate = 10*ownMoveRate;

real annualArrivals = 500; //in-migrating households per year

real annualLeavers = annualArrivals; //out-migrating HHs per year

real rentToOwnProb = 0.5; //probability of transitioning from renter to owner

real ownToRentProb = 0.5; //probability of transitioning from owner to renter

integer parcelSetSize = 15; //maximum number of vacant parcels in HH consideration set

real locConst, locAfford, locSN, locNorm; //parameters set in Monte Carlo experiments

real priorOwnerProb = 0.5; //probability of an initially vacant parcel having been owner-occupied before

integer nbrRuns = 25; //batch size for each simuation experiment, number of runs

real dMax = 34736.97; //maximum distance between block centroids, in feet

real minInc = 5; //minimum income is $5000

real maxInc = 250; //maximum income is $250k

 

Main Active Object Variables

real avgIncome, avgDegree, localFrac;

integer totDirError, totMoveError;

real avgDirError, avgMoveError;

real objective;

integer totalOwnerToOwnerMoves, totalOwnerMoveError,

int[][] moveFromTo = new int[29][29];

Matrix(29,29) moveFromToMatrix, moveFromToDat1Matrix, moveFromToDat2Matrix;

int[][] moveFromToError1 = new int[29][29];

int[][] moveFromToError2 = new int[29][29];

Matrix(29,29) moveFromToError1Matrix, moveFromToError2Matrix;

integer totalError1, totalError2;

int[] bgTotalTies = new int[28];

int[][] bgCrossTies = new int[28][28];

Matrix(28,28) bgNetMatrix;

 

Main Active Object Code

Startup code

initialize.startupSequence(); //call the startup sequence

 

Additional class code

caseTown.ModelObjects mo = (caseTown.ModelObjects) initialize.mo;

final static int[][] moveFromToDat1 = {

{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12},

{0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,5,0,0,0,0,0,0,0,1,1,0,0,0,86},

{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32},

{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20},

{0,1,0,0,2,0,0,0,0,4,0,0,0,0,0,6,0,1,0,0,0,0,0,0,1,1,1,0,117},

{0,0,0,0,1,0,0,0,0,2,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,1,52},

{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,20},

{1,4,0,0,5,0,0,0,0,6,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,140},

{0,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,90},

{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,50},

{0,3,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38},

{0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,23},

{0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,41},

{0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,133},

{0,3,0,0,0,0,0,0,1,1,1,0,1,0,0,4,1,0,0,0,0,0,0,0,0,0,0,0,81},

{0,2,0,0,1,0,0,0,0,1,0,0,0,0,0,3,0,1,0,0,0,0,0,0,0,0,0,0,66},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},

{0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,53},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10},

{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,35},

{0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,87},

{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,36},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,51},

{0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,93},

{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,12},

{23,79,20,22,134,58,28,2,19,150,91,46,44,21,45,123,94,79,7,62,5,15,52,80,36,49,79,9,0}

};

 

public boolean needRepeat() {

  calcRunStats();

  return Engine.getReplication() < nbrRuns;}

 

Main Active Object Algorithmic Functions

real calcAvgIncome()

double income = 0;

double avgIncome;

int numH = household.size();

for (int i=0; i<numH; i++){

  Household h = (Household)household.get(i);

  income += h.getHousehold().income;

}

avgIncome = income/numH;

return avgIncome;

 

void calcError1()

totalError1 = 0;

totalOwnerToOwnerMoves = 0;

for(int i = 0; i < 28; i++){

for(int j = 0; j < 28; j++){

moveFromToError1[i][j] = (int) abs(moveFromTo[i][j] - moveFromToDat1[i][j]);

totalError1+=moveFromToError1[i][j];

totalOwnerToOwnerMoves += moveFromTo[i][j] ;

}}

totalOwnerOwnerMoveError = (int) abs(totalOwnerToOwnerMoves - 139) ;

int sumErr = totalError1+totalOwnerOwnerMoveError;

int n = (int)Engine.getReplication();

totDirError += totalError1;

totMoveError += totalOwnerOwnerMoveError;

 

void calcNetStats()

double totInc, myInc, myLocalFrac, totLocalFrac;

int numH = household.size();

int numF, totF, totLocals, myLocals;

totF = 0; totInc = 0; totLocals = 0; myInc = 0; myLocalFrac = 0; totLocalFrac = 0;

for (int i=0; i<numH; i++){

  Household h = (Household)household.get(i);

  myInc = h.getHousehold().income;

  totInc += myInc;

  caseTown.BlockGroup bg = (caseTown.BlockGroup) h.getMyBlockGroup();

  int m = initialize.mo.blockGroupList.indexOf(bg);

  numF = h.Network.size();

  bgTotalTies[m]+=numF;

  totF += numF;

  myLocals = 0;

  for (int j=0; j<numF; j++){

    Household hj = (Household)h.Network.get(j);

    caseTown.BlockGroup bgj = (caseTown.BlockGroup) hj.getMyBlockGroup();

    int mj = initialize.mo.blockGroupList.indexOf(bgj);

    bgCrossTies[m][mj]+=1;

    if (bg==bgj) myLocals++;

  }

  totLocals += myLocals;

  myLocalFrac = ((double)myLocals)/((double)numF);

  totLocalFrac += myLocalFrac;

}

avgIncome = totInc/numH;

avgDegree = ((double)totF)/numH;

avgLocalFrac = (double) totLocalFrac/numH;

double cell;

for(int i = 0; i < 28; i++){

  for(int j = 0; j < 28; j++){

    cell = ((double)bgCrossTies[i][j])/((double)bgTotalTies[i]);

    bgNetMatrix.set(i,j,cell);

  }

}

 

void calcRunStats()

int n = (int)Engine.getReplication(); //run number index from the batch of 25 runs per setting

avgDirError = (double) totDirError/n;

avgMoveError = (double) totMoveError/n;

objective = avgMoveError + avgDirError;

 

void convertArrayToMatrix()

for(int i = 0; i < 29; i++){

  for(int j = 0; j < 29; j++){

    moveFromToDat1Matrix.set(i,j,moveFromToDat1[i][j]);

    moveFromToDat2Matrix.set(i,j,moveFromToDat2[i][j]);

    moveFromToMatrix.set(i,j,moveFromTo[i][j]);

    moveFromToError1Matrix.set(i,j,moveFromToError1[i][j]);

    moveFromToError2Matrix.set(i,j,moveFromToError2[i][j]);

  }

}

 

void resetMoveArray()

for(int i = 0; i < 29; i++){

for(int j = 0; j < 29; j++){

moveFromTo[i][j]=0;

}}

 

Main Active Object Timers

moveIn

Cyclic Timer

Timeout: exponential(annualArrivals)

Expiry action:

caseTown.ModelObjects mo = (caseTown.ModelObjects) initialize.mo;

int sizeV = mo.vacantParcelList.size();

if (sizeV>0){

  caseTown.Household hj = new caseTown.Household();

  mo.householdList.add(hj);

  hj.income = DistrUniform.sample(minInc,maxInc);

  //find a placeholder parcel at random

  int j = uniform_discr(0, sizeV-1);

  caseTown.Parcel pj = (caseTown.Parcel)mo.vacantParcelList.get(j);

  caseTown.Parcel pMax = pj;

  hj.myParcel = pj;

  Household h = create_household();

  h.stateHousehold = hj;

  h.arrive(pj);

  h.run();

  double toss = DistrUniform.sample(0,1);

     if (toss>priorOwnerProb) h.priorOwner = true;

  double maxUtil = 0;

  sizeV = mo.vacantParcelList.size();

  int sizeRE = (int) min(sizeV, parcelSetSize);

  for (int i=0; i<(sizeRE); i++){

    int startP = h.ParcelSet.size();

    for (int k=0; h.ParcelSet.size()<startP+1; k++){

      j = uniform_discr(0, sizeV-1);

      pj = (caseTown.Parcel)mo.vacantParcelList.get(j);

      if (pj.myHousehold==null && !h.ParcelSet.contains(pj)){

        h.ParcelSet.add(pj);

        double jUtil = h.locUtility(pj);

        if (jUtil > maxUtil) {

          maxUtil = jUtil;

          pMax = pj;

        }//endif

      }//endif

    }//endfor

  }//endfor

  h.leave(); //empty the placeholder parcel

  h.arrive(pMax);

  caseTown.Parcel p = h.getMyParcel();

  caseTown.BlockGroup bg = h.getMyBlockGroup();

  int m = mo.blockGroupList.indexOf(bg);

  if(p.ownerOccupied==true) moveFromTo[28][m]++;

  for (int n = 0; n < minConnect; n++){

    h.connect();

  }

  calcAvgIncome();

}

 

moveOut

Cyclic Timer

Timeout: exponential(annualLeavers)

Expiry action:

caseTown.ModelObjects mo = (caseTown.ModelObjects) initialize.mo;

int numH = household.size();

if (numH>0){

  int j = uniform_discr(0,household.size()-1);

  Household h = (Household)household.item(j);

  caseTown.BlockGroup bg = h.getMyBlockGroup();

  int m = mo.blockGroupList.indexOf(bg);

  for (int i=0; i<h.Network.size(); i++){

    Household hi = (Household) h.Network.get(i);

    hi.Network.remove(h);

    //household is removed from network, not vice versa

  }

  h.leave();

  if(h.priorOwner==true) moveFromTo[m][28]++;

  household.remove(h);

  dispose_household(h);

  //household is NOT removed from the java ArrayList

  calcAvgIncome();

}

 

firstPeriod

Expire Once

Timeout: 2.0

calcError1();

convertArrayToMatrix();

resetMoveArray();

 

1B. Initialize Active Object Class

Initialize Active Object Code

Additional class code

Main main = (Main)(Engine.getRoot());

 

public static caseTown.ModelObjects mo;

 

public static final String filename =  "C:\\modelObjectsFinal.ser";

 

Initialize Active Object Algorithmic Functions

void startupSequence()

loadSerializedData( filename );

//filename is defined in Initialize additional class code

 

createHousehold();

//create households from the imported list, not autocreate

 

setParcelPrior();

createNetwork();

main.calcNetStats();

mo.vacantParcels();

 

 

void loadSerializedData()

mo = (caseTown.ModelObjects)io.Serializer.load(filename);

 

void createHousehold()

int nbrHH = mo.householdList.size();

for(int i=0; i<nbrHH; i++){

  Household h = main.create_household();

  h.stateHousehold = (caseTown.Household) mo.householdList.get(i);

  h.run();

}

 

void setParcelPrior()

int nbrP = mo.parcelList.size();

for(int i=0; i<nbrP; i++){

  caseTown.Parcel p = (caseTown.Parcel) mo.parcelList.get(i);

  p.priorOwnerProb = main.priorOwnerProb;

  p.setPrior();

}

 

void createNetwork()

int nbrH = main.household.size();

for (int i = 0; i < nbrH; i++){

  Household hi = main.household.item(i);

  for (int j = 0; j < main.minConnect; j++){

    hi.connect();

   }

}

 

1C. Household Active Object Class

Household Active Object Parameters

real threshold = DistrUniform.sample(0,1); //idiosyncrasy in criteria for network connection

real locThreshold = DistrUniform.sample(0,1); //idiosyncrasy in current location satisfaction

 

Household Active Object Variables

Vector ParcelSet = new Vector();

Vector Network = new Vector();

boolean priorOwner;

caseTown.Household stateHousehold;

 

Household Active Object Code

Additional class code

Main main = (Main)(Engine.getRoot());

caseTown.ModelObjects mo = (caseTown.ModelObjects) main.initialize.mo;

 

Household Active Object Algorithmic Functions

caseTown.Household getHousehold()

return (caseTown.Household) stateHousehold; //assigned in initialize.createHousehold()

 

caseTown.Parcel getMyParcel()

return getHousehold().myParcel;

 

caseTown.Block getMyBlock()

return getMyParcel().myBlock;

 

caseTown.BlockGroup getMyBlockGroup()

return getMyBlock().myBlockGroup;

 

void moveSequence(caseTown.Parcel pNew)

caseTown.BlockGroup bg = getMyBlockGroup();

int i = mo.blockGroupList.indexOf(bg);

leave();

arrive(pNew);

caseTown.Parcel p = getMyParcel();

bg = getMyBlockGroup();

int j = mo.blockGroupList.indexOf(bg);

if(priorOwner==true && p.ownerOccupied==true){

  main.moveFromTo[i][j] ++;

}//end owner moving

if(priorOwner==true && p.ownerOccupied==false){

  main.moveFromTo[i][28] ++; //j of 28 is leaving owner status

}//end owner leaving

if(priorOwner==false && p.ownerOccupied==true){

  main.moveFromTo[28][j] ++; //i of 28 is new owner status

}//end owner arriving

connect(); //definitely adds a tie

disconnect();//does not necessarily remove a tie

 

void leave()

caseTown.Parcel p = getMyParcel();

caseTown.BlockGroup bg = getMyBlockGroup();

p.myHousehold = null;

mo.vacantParcelList.add(p);

if (p.ownerOccupied == true) {

  p.priorOwnerOccupied = true;

  p.ownerOccupied = false;

  priorOwner = true;

}

caseTown.Household h = getHousehold();

h.myParcel = null;

bg.householdList.remove(h);

 

void arrive(caseTown.Parcel p)

caseTown.Household h = getHousehold();

p.myHousehold = h;

h.myParcel = p;

mo.vacantParcelList.remove(p);

caseTown.BlockGroup bg = getMyBlockGroup();

bg.householdList.add(h);

double ro = main.rentToOwnProb;

double or = main.ownToRentProb;

 

//rent-own prior status

boolean ho = priorOwner;

boolean po = p.priorOwnerOccupied;

 

if((ho==true)&&(po==true)){

  p.ownerOccupied = true;

}

else if((ho==false)&&(po==true)){

  double toss = DistrUniform.sample();

  if(toss>ro) p.ownerOccupied = true;

}

else if((ho==true)&&(po==false)){

  double toss = DistrUniform.sample();

  if(toss>or) p.ownerOccupied = true;

}

 

void connect()

Household hi = Household.this;

double util, p, t, r;

double lp = main.localProb;

double br = DistrUniform.sample(0,1);

int startN = Network.size();

int j;

caseTown.BlockGroup bg = (caseTown.BlockGroup)getMyBlockGroup();

 

//the for condition enables just ONE new connection

for (int f=0; Network.size() < (startN+1); f++){

    j = uniform_discr(0, main.household.size()-1);

    Household hj = (Household) main.household.item(j);

    caseTown.BlockGroup bgj = (caseTown.BlockGroup) hj.getMyBlockGroup();

    if (((lp > br)&&(bg == bgj))||((lp<br)&&(bg!=bgj))) {

      util = nwUtility(hj);

      p = Math.exp(util)/(1+Math.exp(util));

      r = DistrUniform.sample(0,1);

      if (p > r && !Network.contains(hj)){

        hi.Network.add(hj);

        hj.Network.add(hi);

      }

    }

}

 

void disconnect()

Household hi = Household.this;

double util, p, t;

int jMin = 0;

Household hMin = (Household) Network.get(0);

double minUtil = 0; //initialization only;

int startN = Network.size();

for (int j=0; j<startN; j++){

  Household hj = (Household) Network.get(j);

  util = nwUtility(hj);

  if (j==0) minUtil = util;

  if (minUtil<util) {

    minUtil = util;

    jMin = j;

    hMin = hj;

  }

}

hi.Network.remove(hMin);

hMin.Network.remove(hi);

 

real nwUtility(Household hi)

Household hi = Household.this;

double ii = hi.getHousehold().income;

double C = main.nwConst;

double ad = main.nwDist;

double ai = main.nwInc;

double ar = main.nwRace;

double ak = main.nwChild;

double b = main.nwNorm;

double dMax = main.dMax;

double ij, i, d, r, k, util;

boolean wi = hi.getHousehold().white;

boolean wj = hj.getHousehold().white;

boolean ki = hi.getHousehold().children;

boolean kj = hj.getHousehold().children;

 

if (wi==wj) r=1; else r=0;

if ((ki==kj)&&(ki==true)) k=1; else k=0;

 

d = getBlockDistance(hj)/dMax; //divide by max blockdist (ft)

ij = hj.getHousehold().income;

i = Math.abs(ii-ij)/245; //$245k is max-min income

util = (C - ad*d - ai*i + ar*r + ak*k)/b;

 

return util;

 

real locUtility(caseTown.Parcel p)

double hi, bi, ai;

double afford, attract, netFrac, u;

double wAff, wAtt, wSN, C, normB;

 

wAff = main.locAfford;

wAtt = main.locAttract;

wSN = main.locSN;

C = main.locConst;

normB = main.locNorm;

 

hi = getHousehold().income;

 

caseTown.Block b = (caseTown.Block)p.myBlock;

bi = b.calcBlockIncome();

ai = main.avgIncome;

 

if (p == getMyParcel()) afford = 0;

else {

  afford = (hi-bi)/bi;

  afford = min(0, afford); //only if bi > hi

}

attract = (bi-ai)/ai;

 

caseTown.BlockGroup bg = (caseTown.BlockGroup)b.myBlockGroup;

 

int n = Network.size();

int bn = 0;

for (int j=0; j<n; j++){

  Household hj = (Household)Network.get(j);

  caseTown.BlockGroup bgj = (caseTown.BlockGroup)hj.getMyBlockGroup();

  if (bg == bgj) bn++;

}

if (n==0) netFrac = 0;

else netFrac = bn/n;

u = (C + wAff*afford + wAtt*attract + wSN*netFrac)/normB;

 

return u;

 

real getMoveRate()

caseTown.Household h = getHousehold();

caseTown.Parcel p = getMyParcel();

boolean po = p.ownerOccupied;

if (po == true) return main.ownMoveRate;

else return main.rentMoveRate;

 

Household Active Object Timer

 

evalMove

Cyclic Timer

Timeout: exponential(getMoveRate())

Expiry Action:

caseTown.Parcel p = getMyParcel();

double myUtil = locUtility(p);

double prob;

prob = exp(myUtil)/(1+exp(myUtil));

 

int sizeV = mo.vacantParcelList.size();

if (prob < locThreshold && sizeV >0){

  double maxUtil = myUtil;

  caseTown.Parcel pMax = p;

  ParcelSet.clear();

  int sizeRE = (int) min(sizeV,main.parcelSetSize);

  for (int i=0; i<sizeRE; i++){

    int startP = ParcelSet.size();

    int j;

    for (int k=0; ParcelSet.size()<startP+1; k++){

      j = uniform_discr(0, sizeV-1);

      caseTown.Parcel pj = (caseTown.Parcel)mo.vacantParcelList.get(j);

      if (pj.myHousehold==null && !ParcelSet.contains(pj)){

        ParcelSet.add(pj);

        double jUtil = locUtility(pj);

        if (jUtil > maxUtil) {

          maxUtil = jUtil;

          pMax = pj;

        }//endif

      }//endif

    }//endfor

  }//endfor

  if (pMax != p){

    moveSequence(pMax);

  }//endif

  ParcelSet.clear();

}//end unhappy condition

 

Part 2. Java Classes for Data Processing

2A. Processing Package

CreateDataStructure.java

package processing;

 

import io.Serializer;

import io.TextFile;

 

import java.io.IOException;

import java.util.HashMap;

 

import structure.BlockContainer;

import structure.BlockGroupContainer;

import structure.CensusMoves;

import structure.DataContainer;

import structure.OwnerContainer;

import structure.ParcelContainer;

import structure.ParcelStatus;

 

public class CreateDataStructure {

     /*

* @param args: 28blockgroups.csv, 764blocks.csv, 13166parcels.csv, 7576owners.csv,

* dataStructure.ser

     * @throws IOException

*/

     public static void main(String[] args) throws IOException {

          //create the Data Container and add the hashmap

          DataContainer dc = new DataContainer();

          HashMap<String,BlockGroupContainer> blockGroups = new HashMap<String,BlockGroupContainer>

();

          HashMap<String,BlockContainer> blocks = new HashMap<String,BlockContainer>();

          HashMap<String,ParcelContainer> parcels = new HashMap<String,ParcelContainer>();

          HashMap<String,OwnerContainer> owners = new HashMap<String,OwnerContainer>();

          dc.blockGroups = blockGroups;

          dc.blocks = blocks;

          dc.parcels = parcels;

          dc.owners = owners;

          //get the blockGroups.csv Data file and throw away the header row

          TextFile in1 = new TextFile( args[0] );

          in1.remove(0);

          for(int i=0; i<in1.size(); i++){

              String[] row = in1.getRowArray(i);

              BlockGroupContainer bgc = new BlockGroupContainer();

              //field 0 is id, field 1 is "BlockGroupName" 12-char string

              bgc.key = row[1].trim();

              //create Hashmap

              blockGroups.put(bgc.key, bgc);

              //fields 2-4 are child fractions among total, white and nonwhite HHs

              bgc.tcf = Double.parseDouble(row[2].trim());

              bgc.wcf = Double.parseDouble(row[3].trim());

              bgc.ncf = Double.parseDouble(row[4].trim());

              //now we're on field 5, "Stayed"

              bgc.censusMoves = new CensusMoves(Double.parseDouble(row[5].trim()),

                        Double.parseDouble(row[6].trim()),

                        Double.parseDouble(row[7].trim()));

              //now we're on field 8

              for(int j=0; j<16; j++){

                   bgc.incomeGroup[j]=Double.parseDouble(row[j+8].trim());

                   bgc.whiteIncome[j]=Double.parseDouble(row[j+24].trim());

                   bgc.nonwhiteIncome[j]=Double.parseDouble(row[j+40].trim());

              }

          }//blockGroup loop

          //import blocks.csv Data File as args[1]

          TextFile in2 = new TextFile(args[1]);

          in2.remove(0);

          for(int i=0; i<in2.size(); i++){

              String[] row = in2.getRowArray(i);

              BlockContainer bc = new BlockContainer();

              bc.key = row[1].trim(); //blockName

              blocks.put(bc.key, bc); //create hashMap

              bc.bgName = row[2].trim(); //blockGroupName, aka bgc.key

              bc.parcelNum = Integer.parseInt(row[3].trim());

              bc.parcelStatus = new ParcelStatus(Integer.parseInt(row[4].trim()),

                        Integer.parseInt(row[5].trim()),

                        Integer.parseInt(row[6].trim()));

              bc.owp = Double.parseDouble(row[7].trim());

              bc.rwp = Double.parseDouble(row[8].trim());

              bc.cenX = Double.parseDouble(row[9].trim());

              bc.cenY = Double.parseDouble(row[10].trim());

          }

          //import parcels.csv Data File as args[2]

          TextFile in3 = new TextFile(args[2]);

          in3.remove(0);

          for(int i=0; i<in3.size(); i++){

              String[] row = in3.getRowArray(i);

              ParcelContainer pc = new ParcelContainer();

              pc.key = row[0].trim(); //parcelID, same as i

              parcels.put(pc.key, pc); //create hashMap

               pc.xPos = Double.parseDouble(row[1].trim());

              pc.yPos = Double.parseDouble(row[2].trim());

              pc.bName = row[3].trim(); //blockName, aka bc.key

              pc.bgName = row[4].trim(); //blockGroupName, aka bgc.key

              pc.pCode = row[5].trim(); //parcel_ID for GIS reference

          }

          TextFile in4 = new TextFile(args[3]);

          in4.remove(0);

          for(int i=0; i<in4.size(); i++){

              String[] row = in4.getRowArray(i);

              OwnerContainer oc = new OwnerContainer();

              oc.key = row[0].trim(); //ownerID, same as i

              owners.put(oc.key, oc); //create hashMap

              oc.pName = row[1].trim(); //matches pc.key

              oc.moveCode = row[2].trim();

              oc.lastName = row[3].trim();

              oc.lastNameCt = Integer.parseInt(row[4].trim());

          }

          //assign lists

          for (String key: dc.parcels.keySet()){

              ParcelContainer pc = dc.parcels.get(key);

              if(dc.blocks.containsKey(pc.bName)){

                   BlockContainer bc = dc.blocks.get(pc.bName);

                   bc.parcelList.add(pc);

              }

          }//end parcel loop

          for(String key: dc.owners.keySet()){

              OwnerContainer oc = dc.owners.get(key);

              if(dc.parcels.containsKey(oc.pName)){

                   ParcelContainer pc = dc.parcels.get(oc.pName);

                   pc.owner = oc;

              }

          }//end owner loop

          for(String key: dc.blocks.keySet()){

              BlockContainer bc = dc.blocks.get(key);             

              BlockGroupContainer bgc = dc.blockGroups.get(bc.bgName);

              bgc.blockList.add(bc);

          }//end block loop

         

          //args[4] is dataStructure.ser as a persistent data structure

          Serializer.store(dc, args[4]);

     }

}

 

CreateModelInstances.java

 

package processing;

 

import io.Serializer;

 

import java.io.FileNotFoundException;

import java.io.IOException;

import java.util.ArrayList;

 

import structure.BlockContainer;

import structure.BlockGroupContainer;

import structure.DataContainer;

import structure.OwnerContainer;

import structure.ParcelContainer;

 

import caseTown.Block;

import caseTown.BlockGroup;

import caseTown.Household;

import caseTown.ModelObjects;

import caseTown.Parcel;

 

public class CreateModelInstances {

 

     /**

      * @param args: dataStructure.ser, modelObjectsFinal.ser

      * @throws IOException

      * @throws FileNotFoundException

      * @throws ClassNotFoundException

      */

     public static void main(String[] args) throws FileNotFoundException, IOException,

ClassNotFoundException {

          // TODO Auto-generated method stub

          ArrayList<BlockGroup> blockGroupList = new ArrayList<BlockGroup>();

          ArrayList<Block> blockList = new ArrayList<Block>();

          ArrayList<Parcel> parcelList = new ArrayList<Parcel>();

          ArrayList<Household> householdList = new ArrayList<Household>();

          ArrayList<Household> ownerList = new ArrayList<Household>();

          ArrayList<Household> renterList = new ArrayList<Household>();

          ArrayList<Parcel> vacantParcels = new ArrayList<Parcel>();

         

          DataContainer dc = (DataContainer) Serializer.load(args[0]);

         

          for (String bgKey: dc.blockGroups.keySet()){

              BlockGroupContainer bgc = dc.blockGroups.get(bgKey);

              BlockGroup bg = new BlockGroup();

              blockGroupList.add(bg);

              bg.name = bgKey;

              bg.incomeGroup = bgc.incomeGroup;

              bg.whiteIncome = bgc.whiteIncome;

              bg.nonwhiteIncome = bgc.nonwhiteIncome;

              bg.wcf = bgc.wcf;

              bg.ncf = bgc.ncf;

              for (BlockContainer bc: bgc.blockList){

                   Block b = new Block();

                   b.name = bc.key;

                   b.xCen = bc.cenX;

                   b.yCen = bc.cenY;

                   b.parcelStatus = bc.parcelStatus;

                   int r = b.parcelStatus.rent;

                   int v = b.parcelStatus.vacant;

                   b.myBlockGroup = bg;

                   blockList.add(b);

                   bg.blockList.add(b);

                   for (ParcelContainer pc: bc.parcelList){

                        Parcel p = new Parcel();

                        p.name = pc.key;

                        p.myBlock = b;

                        p.xPos = pc.xPos;

                        p.yPos = pc.yPos;

                        b.xAvg += p.xPos;

                        b.yAvg += p.yPos;

                        parcelList.add(p);

                        b.parcelList.add(p);

                        OwnerContainer oc = pc.owner;

                        double rand = Math.random();

                        if (oc != null){

                             Household h = new Household();

                             h.name = oc.key;

                             h.myParcel = p;

                             p.myHousehold = h;

                             p.ownerOccupied = true;

                             if (bc.owp > rand) h.white = true;

                             householdList.add(h);

                             ownerList.add(h);

                             bg.householdList.add(h);

                        }

                        else if (r > 0) {

                             if (r > v){

                                  Household h = new Household();

                                  h.myParcel = p;

                                  p.myHousehold = h;

                                  if (bc.rwp > rand) h.white = true;

                                  householdList.add(h);

                                  renterList.add(h);

                                  bg.householdList.add(h);

                                  r = r-1;

                             }//end if rentals dominate

                             else v = v-1; //parcel stays empty

                        }//end if rentals exist

                        if (p.myHousehold == null) vacantParcels.add(p);

                   }//end parcel loop

                   b.xAvg = b.xAvg/b.parcelList.size();

                   b.yAvg = b.yAvg/b.parcelList.size();

              }//end block loop           

          }//end blockGroup loop

 

          ModelObjects mo = new ModelObjects();

          mo.blockGroupList = blockGroupList;

          mo.blockList = blockList;

          mo.parcelList = parcelList;

          mo.householdList = householdList;

          Serializer.store(mo, args[1]); //output serializer filename

     }

}

 

BlockDistance.java

 

package processing;

 

import io.Serializer;

 

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.Serializable;

 

import caseTown.Block;

import caseTown.ModelObjects;

 

public class BlockDistance implements Serializable {

     private static final long serialVersionUID = 1L;

    

     public static void addDistances (ModelObjects mo){

          int size = mo.blockList.size();

          mo.blockDistance = new double[size][];

          for(int row = 0; row < size; row++){

              Block fromB = (Block) mo.blockList.get(row);

              fromB.seq = row;

              double fromX = fromB.xAvg;

              double fromY = fromB.yAvg;

              mo.blockDistance[row] = new double[row+1];

              for(int col = 0; col < row+1; col++){

                   Block toB = (Block) mo.blockList.get(col);

                   double toX = toB.xAvg;

                   double toY = toB.yAvg;

                   double xDist = fromX - toX;

                   double yDist = fromY - toY;

                   double d = Math.hypot(xDist, yDist);

                   mo.blockDistance[row][col]=d;

              }

          }

     }

     /**

      * @param args: modelObjectsFinal.ser

      * @throws ClassNotFoundException

      * @throws IOException

      * @throws FileNotFoundException

      */

     public static void main(String[] args) throws FileNotFoundException, IOException,

ClassNotFoundException {

          // TODO Auto-generated method stub

          ModelObjects mo = (ModelObjects)Serializer.load(args[0]);

          addDistances(mo);

          Serializer.store(mo,args[0]);

     }

}

 

AssignChildrenIncome.java

 

package processing;

 

import io.Serializer;

 

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.Serializable;

 

import caseTown.BlockGroup;

import caseTown.Household;

import caseTown.ModelObjects;

 

public class AssignChildrenIncome implements Serializable {

 

     private static final long serialVersionUID = 1L;

    

     public static void addAttributes (ModelObjects mo){

          int bgs = mo.blockGroupList.size();

          double[] tip = new double[16];

          double[] wip = new double[16];

          double[] nip = new double[16];

          double[] max = {10,15,20,25,30,35,40,45,50,60,75,100,125,150,200,250};

          double[] min = {5,10,15,20,25,30,35,40,45,50,60,75,100,125,150,200};

          for (int index=0; index<bgs; index++){

              BlockGroup bg = (BlockGroup) mo.blockGroupList.get(index);

              double[] tir = bg.incomeGroup;

              double[] wir = bg.whiteIncome;

              double[] nir = bg.nonwhiteIncome;

              for (int j=0; j<16; j++){

                   for (int k=0; k<j+1; k++){

                        tip[j] += tir[k];

                        wip[j] += wir[k];

                        nip[j] += nir[k];

                   }

              }//assign cumulative probs for each income group

              for (int j=0; j<16; j++){

                   tip[j] = tip[j]*1/tip[15];

                   wip[j] = wip[j]*1/wip[15];

                   nip[j] = nip[j]*1/nip[15];

              }//scale so they wind up at exactly one

              int size = bg.householdList.size();

              for (int i=0; i<size; i++){

                   //int randomIndex = (int) Math.random()*(size-1);

                   Household h = (Household) bg.householdList.get(i);

                   double r = Math.random();

                   if (h.white && (bg.wcf>r)) h.children = true;

                   if (!h.white && (bg.ncf>r)) h.children = true;

                   double minP = 0;

                   double maxP = 1;

                   boolean[] fit = new boolean[16];

                   for (int k=0; k<16; k++){

                        if (h.white) maxP = wip[k]; else maxP = nip[k];

                        if ((r<maxP)&&(r>=minP)){

                             fit[k]=true;

                             h.income = Math.random()*(max[k]-min[k])+min[k];

                        }

                        if (h.white) minP = wip[k]; else minP = nip[k];

                   }//find the fitting category

              }

          }

     }

     /**

      * @param args

      * @throws ClassNotFoundException

      * @throws IOException

      * @throws FileNotFoundException

      */

     public static void main(String[] args) throws FileNotFoundException, IOException,

ClassNotFoundException {

          // TODO Auto-generated method stub

          ModelObjects mo = (ModelObjects)Serializer.load(args[0]);

          addAttributes(mo);

          Serializer.store(mo,args[0]);

     }

}

 

 

2B. Structure Package

DataContainer.java

 

package structure;

 

import java.io.Serializable;

import java.util.HashMap;

 

public class DataContainer implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public HashMap<String, BlockGroupContainer> blockGroups;

     public HashMap<String, BlockContainer> blocks;

     public HashMap<String, ParcelContainer> parcels;

     public HashMap<String, OwnerContainer> owners;

}

 

BlockGroupContainer.java

 

package structure;

 

import java.io.Serializable;

import java.util.ArrayList;

 

public class BlockGroupContainer implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public String key;

     //total, white, nonwhite fraction of HHs with children

     public double tcf, wcf, ncf;

     //overall, white, and nonwhite income group fractions

     public double[] incomeGroup = new double[16];

     public double[] whiteIncome = new double[16];

     public double[] nonwhiteIncome = new double[16];

     public CensusMoves censusMoves;

     public ArrayList<BlockContainer> blockList = new ArrayList<BlockContainer>();

}

 

BlockContainer.java

 

package structure;

 

import java.io.Serializable;

import java.util.ArrayList;

 

public class BlockContainer implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public String key;

     public String bgName;

     public int parcelNum;

     public double owp, rwp, cenX, cenY;

     public ParcelStatus parcelStatus;

     public ArrayList<ParcelContainer> parcelList = new ArrayList<ParcelContainer>();

}

 

ParcelContainer.java

 

package structure;

 

import java.io.Serializable;

 

public class ParcelContainer implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public String key;

     public double xPos;

     public double yPos;

     public String bName;

     public String bgName;

     public String pCode;

     public int addressNum;

     public String street;

     public OwnerContainer owner;

}

 

OwnerContainer.java

 

package structure;

 

import java.io.Serializable;

 

public class OwnerContainer implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public String key;

     public String pName;

     public String moveCode;

     public String lastName;

     public int lastNameCt;

}

 

ParcelStatus.java

 

package structure;

 

import java.io.Serializable;

 

public class ParcelStatus implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public int own;

     public int rent;

     public int vacant;

    

     public ParcelStatus(int own, int rent, int vacant){

          this.own = own;

          this.rent = rent;

          this.vacant = vacant;

     }

}

 

CensusMoves.java

 

package structure;

 

import java.io.Serializable;

 

public class CensusMoves implements Serializable {

     private static final long serialVersionUID = 1L;

     public double stayed;

     public double movedNear;

     public double movedFar;

    

     public CensusMoves(double stayed, double movedNear, double movedFar){

          this.stayed = stayed;

          this.movedNear = movedNear;

          this.movedFar = movedFar;

     }

}

 

 

2C. CaseTown Package

ModelObjects.java

 

package caseTown;

 

import java.io.Serializable;

import java.util.ArrayList;

 

public class ModelObjects implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public ArrayList blockGroupList = new ArrayList();

     public ArrayList blockList = new ArrayList();

     public ArrayList parcelList = new ArrayList();

     public ArrayList householdList = new ArrayList();

     public double[][] blockDistance;

     public ArrayList vacantParcelList;

    

     public ArrayList vacantParcels(){

          vacantParcelList = new ArrayList();

          int size = parcelList.size();

          for (int i=0; i<size; i++){

              Parcel p = (Parcel)parcelList.get(i);

              if (p.myHousehold==null) vacantParcelList.add(p);

          }

          return vacantParcelList;

     }

}

 

BlockGroup.java

 

package caseTown;

 

import java.io.Serializable;

import java.util.ArrayList;

 

public class BlockGroup implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public ArrayList blockList = new ArrayList();

     public ArrayList householdList = new ArrayList();

     public String name;

     public double[] incomeGroup = new double[16];

     public double[] whiteIncome = new double[16];

     public double[] nonwhiteIncome = new double[16];

     public double incAvg, wcf, ncf;

    

     public double calcBlockGroupIncome(){

          int size = householdList.size();

          incAvg = 0;

          for (int i=0; i < size; i++){

              Household h = (Household)householdList.get(i);

              incAvg += h.income;

          }

          incAvg = incAvg/size;

          return incAvg;

     }

}

 

Block.java

 

package caseTown;

 

import java.io.Serializable;

import java.util.ArrayList;

 

import structure.ParcelStatus;

 

public class Block implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public ArrayList parcelList = new ArrayList();

     public BlockGroup myBlockGroup;

     public String name;

     public ParcelStatus parcelStatus;

     public double xAvg, yAvg, xCen, yCen;

     public int seq;

     public double incAvg;

    

     public double calcBlockIncome(){

          incAvg = 0;

          int pSize = parcelList.size();

          int hSize = 0;

          for (int i = 0; i<pSize; i++){

              Parcel p = (Parcel)parcelList.get(i);

              if (p.myHousehold != null){

                   Household h = p.myHousehold;

                   incAvg += h.income;

                   hSize ++;

              }

          }

          incAvg = incAvg/hSize;

          return incAvg;

     }

 

}

 

Parcel.java

 

package caseTown;

 

import java.io.Serializable;

 

public class Parcel implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public Block myBlock;

     public String name;

     public Household myHousehold;

     public boolean ownerOccupied; //default is false

     public double xPos;

     public double yPos;

     public double priorOwnerProb;

    

     public boolean priorOwnerOccupied; //for rent-own transition

    

     public boolean setPrior(){

          double toss = Math.random();

          if (toss>priorOwnerProb) priorOwnerOccupied = true;

          return priorOwnerOccupied;

     }   

}

 

Household.java

 

package caseTown;

 

import java.io.Serializable;

 

public class Household implements Serializable {

 

     private static final long serialVersionUID = 1L;

     public Parcel myParcel;

     public String name;

     public double income;

     public boolean white;

     public boolean children;    

}