/**
* A component of a library for
* GENESIS
* Copyright (C) 2008
* Andy Turner,
* University of Leeds.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package uk.ac.leeds.ccg.andyt.projects.genesis.process;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Vector;
import uk.ac.leeds.ccg.andyt.grids.core.Grid2DSquareCellDouble;
import uk.ac.leeds.ccg.andyt.grids.exchange.ImageExporter;
import uk.ac.leeds.ccg.andyt.grids.process.Grid2DSquareCellProcessor;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.demography.Demographics;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.demography.Fertility;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.demography.Mapping;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.demography.Mortality;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.demography.Movement;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.environment.Environment;
//import uk.ac.leeds.ccg.andyt.projects.genesis.society.organisations.Family;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.environment.Location;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.organisations.Household;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.persons.Female;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.persons.Male;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.persons.Person;
import uk.ac.leeds.ccg.andyt.projects.genesis.society.environment.Time;
/**
* A class to generate a society.
*/
public class GenerateSociety_2 extends Grid2DSquareCellProcessor {
private int _RandomSeed;
private Environment _Environment;
/**
* _Population[0] is a Female HashSet
* _Population[1] is a Male HashSet
*/
//private Object[] _Population;
/**
* A collection of all Persons, alive or dead, male or female.
*/
private HashSet _Population;
/**
* A collection of all alive Females.
*/
private HashSet _Population_Alive_Female;
/**
* A collection of all alive Females that are pregnant.
*/
private HashSet _Population_Alive_Female_Pregnant;
/**
* A collection of all alive Males.
*/
private HashSet _Population_Alive_Male;
public ImageExporter _ImageExporter;
public String _Type;
public GenerateSociety_2() {
}
public static void main(String args[]) {
GenerateSociety_2 _GenerateSociety_2 = new GenerateSociety_2();
_GenerateSociety_2.run();
}
/**
* Example run with the smallest timestep being 1 second producing:
* Age/gender plots at each year
* A composite map of locations each day
*
* Each person has a workplace and some workhours. They travel to their
* workplace and depending on how early/late they are, they set off at
* different time the next day. Hopefully after a few days most people
* should set of at about the right time so as not to be late.
*
* To begin with, each Person works from 9am to 5pm every day.
*
* There are 10 Work Locations and these assigned at Random.
*
* information about how related society is
* need to model who fathers which children
* people now have fertility and mortality rates conditioned by their resource level.
* people move about the landscape getting resource
* people need a memory of where they have gone and what resource is available there
* people have social networks forming now they move about in space coming into contact with people from other households
*/
public void run() {
_RandomSeed = 0;
Time _Time = new Time(20, 0);
_Grid2DSquareCells = new HashSet();
boolean _HandleOutOfMemoryError = false;
long _NRows = 501;
long _NCols = 501;
Grid2DSquareCellDouble _World_Grid2DSquareCellDouble = (Grid2DSquareCellDouble) _Grid2DSquareCellDoubleFactory.create(_NRows, _NCols);
long row;
long col;
for (row = 0; row < _NRows; row++) {
for (col = 0; col < _NCols; col++) {
_World_Grid2DSquareCellDouble.setCell(row, col, 0.0d, _HandleOutOfMemoryError);
}
}
_Environment = new Environment(
new Random(_RandomSeed),
_Time,
_Grid2DSquareCellDoubleFactory,
_World_Grid2DSquareCellDouble,
_HandleOutOfMemoryError);
_Environment._Init_Resource_Grid2DSquareCellDouble();
_Time = new Time(0, 0);
int numberOfWorkplaces = 100;
Vector _Location_Works = new Vector(numberOfWorkplaces);
int delta_row;
int delta_col;
int variation = 400;
for (int i = 0; i < numberOfWorkplaces; i++) {
delta_row = _Environment._Random.nextInt(variation);
delta_col = _Environment._Random.nextInt(variation);
//_Location_Works.add(_Environment.getRandomLocation());
_Location_Works.add(new Location(
_NRows / 2 - (variation / 2) + delta_row,
_NCols / 2 - (variation / 2) + delta_col));
}
int _NumberOfHouseholds = 5000;
int _Max_NumberOfFemalesPerHousehold = 5;
int _Max_NumberOfMalesPerHousehold = 5;
_Initialise_Population(
_Environment,
_Time,
_NumberOfHouseholds,
_Max_NumberOfFemalesPerHousehold,
_Max_NumberOfMalesPerHousehold,
_Location_Works);
_ImageExporter = new ImageExporter();
_Type = "PNG";
Demographics _Demographics = new Demographics();
int _Years = 1;//300;
_Simulate(_Demographics, _Years);
}
/**
* Initialises Persons in a simple society.
* There are 10 households each consisting of 10 Males and 10
* Females as yet unrelated.
* Each household is randomly located within the environment.
* Each Person has a randomly located workplace within the environment.
*/
public void _Initialise_Population(
Environment _Environment,
Time _Time,
int _NumberOfHouseholds,
int _Max_NumberOfFemalesPerHousehold,
int _Max_NumberOfMalesPerHousehold,
Vector _Location_Works) {
_Population = new HashSet();
_Population_Alive_Male = new HashSet();
_Population_Alive_Female = new HashSet();
_Population_Alive_Female_Pregnant = new HashSet();
int _NumberOfFemalesPerHousehold;
int _NumberOfMalesPerHousehold;
int i;
int _Household_int;
Object _ID;
Male _Male;
Female _Female;
//Person _Person;
Time _Min_Time_Birth = new Time(0, 0, 0);
Time _Max_Time_Birth = new Time(15, 0, 0);
Time _Time_Birth;
//Calendar _DateOfBirth_Calendar;
for (_Household_int = 0; _Household_int < _NumberOfHouseholds; _Household_int++) {
// N.B. Possibility of empty households.
Household _Household = new Household(_Environment.getRandomLocation());
// Generate Females
_NumberOfFemalesPerHousehold = _Environment._Random.nextInt(_Max_NumberOfFemalesPerHousehold);
for (i = 0; i < _NumberOfFemalesPerHousehold; i++) {
//_Place_Location = _Environment.getRandomLocation();
_ID = new Object();
_Time_Birth = Time.get_RandomTime(
_Min_Time_Birth,
_Max_Time_Birth,
_Environment._Random);
_Female = new Female(
_Environment, _ID, _Time_Birth, _Household);
_Female._Location_Work = (Location) _Location_Works.elementAt(_Environment._Random.nextInt(_Location_Works.size()));
_Female._Time_Work = new Time[2];
_Female._Time_Work[0] = new Time(0, 0, 60 * 60 * 9);
_Female._Time_Work[1] = new Time(0, 0, 60 * 60 * 17);
_Female._Time_SetOffToWork = _Female._Time_Work[0];
_Population_Alive_Female.add(_Female);
}
// Generate Males
_NumberOfMalesPerHousehold = _Environment._Random.nextInt(_Max_NumberOfMalesPerHousehold);
for (i = 0; i < _NumberOfMalesPerHousehold; i++) {
//_Place_Location = _Environment.getRandomLocation();
_ID = new Object();
_Time_Birth = Time.get_RandomTime(
_Min_Time_Birth,
_Max_Time_Birth,
_Environment._Random);
_Male = new Male(
_Environment, _ID, _Time_Birth, _Household);
//_Male._Location_Work = _Environment.getRandomLocation();
_Male._Location_Work = (Location) _Location_Works.elementAt(_Environment._Random.nextInt(_Location_Works.size()));
_Male._Time_Work = new Time[2];
_Male._Time_Work[0] = new Time(0, 0, 60 * 60 * 9);
_Male._Time_Work[1] = new Time(0, 0, 60 * 60 * 17);
_Male._Time_SetOffToWork = _Male._Time_Work[0];
_Population_Alive_Male.add(_Male);
}
}
_Population.addAll(_Population_Alive_Male);
_Population.addAll(_Population_Alive_Female);
}
/**
* Dynamically simulates a population over time.
* @param _Demographics
* @param _Years The number of years over which the simulation occurs
*/
public void _Simulate(
Demographics _Demographics,
int _Years) {
Mortality _Mortality = new Mortality(_Environment);
int _TotalBirths = 0;
int _TotalBirthsInYear = 0;
int _TotalDeaths = 0;
int _TotalDeathsInYear = 0;
int _TotalPregnancies = 0;
int _TotalPregnanciesInYear = 0;
int _TotalMiscarriages = 0;
int _TotalMiscarriagesInYear = 0;
Grid2DSquareCellDouble _Population_Location_Composite_Map;
Grid2DSquareCellDouble _Population_Movement_Composite_Map;
File _File;
Fertility _Fertility = new Fertility();
boolean movement;
int _Hours;
int _HoursInSeconds;
int _Minutes;
int _MinutesInSeconds;
int _Seconds;
//int _StartSimulationSecondOfDay = (60 * 60 * 9);
for (int _Year = 0; _Year < _Years; _Year++) {
_TotalBirthsInYear = 0;
_TotalDeathsInYear = 0;
_TotalPregnanciesInYear = 0;
_TotalMiscarriagesInYear = 0;
//for (int _Day = 0; _Day < Time._Normal_Days_In_Year; _Day++) {
for (int _Day = 0; _Day < 2; _Day++) {
_Population_Location_Composite_Map = (Grid2DSquareCellDouble) _Environment._Grid2DSquareCellDoubleFactory.create(_Environment._World_Grid2DSquareCellDouble);
_Population_Movement_Composite_Map = (Grid2DSquareCellDouble) _Environment._Grid2DSquareCellDoubleFactory.create(_Environment._World_Grid2DSquareCellDouble);
//_Environment._Time._SecondOfDay = _StartSimulationSecondOfDay;
//for (int _Second = _StartSimulationSecondOfDay; _Second < Time._Normal_Seconds_In_Day; _Second++) {
for (int _Second = 0; _Second < Time._Normal_Seconds_In_Day; _Second++) {
// if (_Second > (60 * 60 * 9) + (60 * 4)) {
// int Debug = 0;
// }
movement = _SimulateMovement();
//if (_Day == 0) {
_Hours = _Second / (60 * 60);
_HoursInSeconds = _Hours * 60 * 60;
_Minutes = (_Second - _HoursInSeconds) / 60;
_MinutesInSeconds = _Minutes * 60;
_Seconds = _Second - _MinutesInSeconds - _HoursInSeconds;
if (movement) {
Mapping._AddTo_Population_Movement_Composite_Map(
_Population_Movement_Composite_Map,
_Population_Alive_Female,
_Population_Alive_Male,
1.1d,
_Environment._HandleOutOfMemoryError);
// Mapping._AddTo_Population_Location_Composite_Map(
// _Population_Movement_Composite_Map,
// _Population,
// 1.1d,
// _Environment._HandleOutOfMemoryError);
if (_Second % 5 == 0) {
_File = new File("C:/temp/_Population_Movement_Composite_Map_" + _Year + "_" + _Day + "_" + _Hours + "_" + _Minutes + "_" + _Seconds + "." + _Type);
//_Rescale(_Population_Movement_Composite_Map, "log", 1.0d, 10.0d,_Environment._HandleOutOfMemoryError);
Mapping._OutputMap(
_Population_Movement_Composite_Map,
_File, _Type, _ImageExporter, _Environment);
}
}
//}
// // Output Map
// Mapping._AddTo_Population_Location_Composite_Map(
// _Population_Location_Composite_Map,
// _Population,
// 1.0d,
// _Environment._HandleOutOfMemoryError);
// if (_Second % 60 == 0) {
// _File = new File("C:/temp/_Population_Location_Composite_Map_" + _Year + "_" + _Day + "_" + _Hours + "_" + _Minutes + "_" + _Seconds + "." + _Type);
// Mapping._OutputMap(
// _Population_Location_Composite_Map,
// _File, _Type, _ImageExporter, _Environment);
// }
System.out.println("Second " + _Second + " Out Of " + Time._Normal_Seconds_In_Day);
_Environment._Time._Increment_Second();
}
// _File = new File("C:/temp/_Density_Map_Population" + _Year + "_" + _Day + "." + _Type);
// Mapping._OutputMap(
// _Population_Location_Composite_Map,
// _File, _Type, _ImageExporter, _Environment);
// Output Demographics
// Deaths
// Does anyone die today?
_TotalDeathsInYear += _SimulateDeath(
_Mortality);
// Births
// Is anyone born today?
_TotalBirthsInYear += _SimulateBirth();
// Pregnancy
// Does anyone get pregnant today?
_TotalPregnanciesInYear += _SimulatePregnancy(_Fertility);
// Miscarriage
// Does anyone miscarry today?
_TotalMiscarriagesInYear += _SimulateMiscarriage();
_Environment._Time._Increment_Day();
System.out.println(
"_Year " + _Year +
"_Day " + _Day);
}
_TotalDeaths += _TotalDeathsInYear;
_TotalBirths += _TotalBirthsInYear;
_TotalPregnancies += _TotalPregnanciesInYear;
System.out.println(
"_Year " + _Year +
", _TotalDeathsInYear " + _TotalDeathsInYear +
", _TotalBirthsInYear " + _TotalBirthsInYear +
", _TotalPregnanciesInYear " + _TotalPregnanciesInYear +
", _TotalMiscarriagesInYear " + _TotalMiscarriagesInYear);
_Demographics._AgeGenderPlot(
_Population_Alive_Female,
_Population_Alive_Male,
_Environment._Time);
}
System.out.println(
", _TotalDeaths " + _TotalDeaths +
", _TotalBirths " + _TotalBirths +
", _TotalPregnancies " + _TotalPregnancies +
", _TotalMiscarriages " + _TotalMiscarriages);
//return result;
}
/**
*/
public int _SimulateDeath(
Mortality _Mortality) {
int _TotalDeaths = 0;
//double _FixedDailyDeathRate = 0.001; //0.5;
double _DailyDeathRate;
Iterator _Iterator;
Female _Female;
Male _Male;
double comparison;
HashSet newDeadFemales = new HashSet();
_Iterator = _Population_Alive_Female.iterator();
while (_Iterator.hasNext()) {
_Female = (Female) _Iterator.next();
_DailyDeathRate = _Mortality.get_AnnualMortalityLikelihood(_Female) / 365.0d;
comparison = _Environment._Random.nextDouble();
//if (comparison<_FixedDailyDeathRate){
if (comparison < _DailyDeathRate) {
_Female.set_Time_Death(_Environment._Time);
newDeadFemales.add(_Female);
_TotalDeaths++;
}
}
_Population_Alive_Female.removeAll(newDeadFemales);
_Population_Alive_Female_Pregnant.removeAll(newDeadFemales);
HashSet newDeadMales = new HashSet();
_Iterator = _Population_Alive_Male.iterator();
while (_Iterator.hasNext()) {
_Male = (Male) _Iterator.next();
_DailyDeathRate = _Mortality.get_AnnualMortalityLikelihood(_Male) / 365.0d;
comparison = _Environment._Random.nextDouble();
//if (comparison<_FixedDailyDeathRate){
if (comparison < _DailyDeathRate) {
_Male.set_Time_Death(_Environment._Time);
newDeadFemales.add(_Male);
_TotalDeaths++;
}
}
_Population_Alive_Male.removeAll(newDeadMales);
return _TotalDeaths++;
}
/**
* @return Total number of births
*/
public int _SimulateBirth() {
int _TotalBirths = 0;
Iterator _Iterator;
Female _Female;
HashSet newbornFemales = new HashSet();
_Iterator = _Population_Alive_Female.iterator();
while (_Iterator.hasNext()) {
_Female = (Female) _Iterator.next();
if (_Female._IsPregnant()) {
if (_Female._Time_DueToGiveBirth.compareTo(_Environment._Time) == 0) {
Person _Person = _Female._Gives_Birth();
if (_Person.get_Gender() == 0) {
newbornFemales.add(_Person);
} else {
_Population_Alive_Male.add(_Person);
}
_TotalBirths++;
//System.out.println("Birth");
//} else {
// System.out.println("Birth due in " + _Female._Time_DueToGiveBirth._Difference(_Environment._Time));
}
}
}
_Population_Alive_Female.addAll(newbornFemales);
return _TotalBirths;
}
/**
* Returns HashSet of all males at _Location
* @param _Location
*/
public HashSet getMales(Object _Location) {
Iterator _Iterator = _Population_Alive_Male.iterator();
Male _Male;
HashSet _MalesAtLocation = new HashSet();
while (_Iterator.hasNext()) {
_Male = (Male) _Iterator.next();
if (_Male._Location == _Location) {
_MalesAtLocation.add(_Male);
}
}
return _MalesAtLocation;
}
/**
*/
public int _SimulatePregnancy(
Fertility _Fertility) {
int _TotalPregnancies = 0;
Iterator _Iterator;
Female _Female;
int _Age;
double fertility;
double comparison;
_Iterator = _Population_Alive_Female.iterator();
while (_Iterator.hasNext()) {
_Female = (Female) _Iterator.next();
_Age = _Female.get_AgeInYears_int();
if (!_Female._IsPregnant()) {
// Is there a male around to tango?
HashSet _Males = getMales(_Female._Location);
if (_Males.size() > 0) {
// Select one to be the father.
// At the moment we just get the first given by the HashSet...
// This is probably not best practive, but it's good enough for now
Iterator _Males_Iterator = _Males.iterator();
Male _Father = (Male) _Males_Iterator.next();
fertility = _Fertility.get_Fertility_Female(_Age);
comparison = _Environment._Random.nextDouble();
if (comparison < fertility) {
_Female.set_Pregnant();
//_Female.set_UnbornsFather(_Father);
_Population_Alive_Female_Pregnant.add(_Female);
_TotalPregnancies++;
//System.out.println("Pregnancy");
}
}
}
}
return _TotalPregnancies;
}
/**
*
* @param _PregnantFemales
*/
public int _SimulateMiscarriage() {
int _TotalMiscarriages = 0;
// Fixed chance of miscarriage
double _MiscarriageProbablity = 0.0005;
double comparison;
Iterator _Iterator;
Female _Female;
_Iterator = _Population_Alive_Female_Pregnant.iterator();
HashSet _MiscarriedFemales = new HashSet();
while (_Iterator.hasNext()) {
_Female = (Female) _Iterator.next();
comparison = _Environment._Random.nextDouble();
if (comparison < _MiscarriageProbablity) {
_Female._Time_DueToGiveBirth = null;
_MiscarriedFemales.add(_Female);
_TotalMiscarriages++;
//System.out.println("Miscarriage");
}
}
_Population_Alive_Female_Pregnant.removeAll(_MiscarriedFemales);
return _TotalMiscarriages;
}
/**
* Agents only move from home to work and then back again.
* Each agent can move to any position in a 1 cell radius of their current location.
* @return true if some Person moves
*/
public boolean _SimulateMovement() {
boolean result = false;
Iterator _Iterator;
Person _Person;
_Iterator = _Population_Alive_Female.iterator();
while (_Iterator.hasNext()) {
_Person = (Person) _Iterator.next();
if (_Person._Location_Heading == null) {
if (_Person._Time_Work[1]._SecondOfDay == _Environment._Time._SecondOfDay) {
// Everyone goes home after work!
_Person._Location_Heading = _Person._Household._Location;
} else {
if (_Person._Time_SetOffToWork._SecondOfDay == _Environment._Time._SecondOfDay) {
_Person._Location_Heading = _Person._Location_Work;
}
}
} else {
if (_Person._Location_Heading.equals(_Person._Location_Work)) {
if (!_Person._Location.equals(_Person._Location_Work)) {
result = true;
_Person._Location = Movement.getNewLocation_1(
_Person._Location,
_Person._Location_Work,
_Environment);
}
if (_Person._Location.equals(_Person._Location_Work)) {
// Person arrives at work
int _Seconds_Late =
_Environment._Time._SecondOfDay -
_Person._Time_Work[0]._SecondOfDay;
_Person._Location_Heading = null;
_Person._Time_SetOffToWork._SecondOfDay -= _Seconds_Late;
}
} else {
if (_Person._Location_Heading.equals(_Person._Household._Location)) {
if (!_Person._Location.equals(_Person._Household._Location)) {
result = true;
_Person._Location = Movement.getNewLocation_1(
_Person._Location,
_Person._Household._Location,
_Environment);
}
if (_Person._Location.equals(_Person._Household._Location)) {
// Person arrives at home
_Person._Location_Heading = null;
}
}
}
}
}
_Iterator = _Population_Alive_Male.iterator();
while (_Iterator.hasNext()) {
_Person = (Person) _Iterator.next();
if (_Person._Location_Heading == null) {
if (_Person._Time_Work[1]._SecondOfDay == _Environment._Time._SecondOfDay) {
// Everyone goes home after work!
_Person._Location_Heading = _Person._Household._Location;
} else {
if (_Person._Time_SetOffToWork._SecondOfDay == _Environment._Time._SecondOfDay) {
_Person._Location_Heading = _Person._Location_Work;
}
}
} else {
if (_Person._Location_Heading.equals(_Person._Location_Work)) {
if (!_Person._Location.equals(_Person._Location_Work)) {
result = true;
_Person._Location = Movement.getNewLocation_1(
_Person._Location,
_Person._Location_Work,
_Environment);
}
if (_Person._Location.equals(_Person._Location_Work)) {
// Person arrives at work
int _Seconds_Late =
_Environment._Time._SecondOfDay -
_Person._Time_Work[0]._SecondOfDay;
_Person._Location_Heading = null;
_Person._Time_SetOffToWork._SecondOfDay -= _Seconds_Late;
}
} else {
if (_Person._Location_Heading.equals(_Person._Household._Location)) {
if (!_Person._Location.equals(_Person._Household._Location)) {
result = true;
_Person._Location = Movement.getNewLocation_1(
_Person._Location,
_Person._Household._Location,
_Environment);
}
if (_Person._Location.equals(_Person._Household._Location)) {
// Person arrives at home
_Person._Location_Heading = null;
}
}
}
}
}
return result;
}
}