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.
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();
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();
}
}
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
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]);
}
}
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;
}
}
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;
}