/** * 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.awt.image.BufferedImage; import java.io.File; import java.io.IOException; //import java.util.Calendar; //import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Random; import org.jfree.chart.JFreeChart; import uk.ac.leeds.ccg.andyt.grids.core.AbstractGrid2DSquareCell; import uk.ac.leeds.ccg.andyt.grids.core.Grid2DSquareCellDouble; import uk.ac.leeds.ccg.andyt.grids.core.Grid2DSquareCellDoubleFactory; import uk.ac.leeds.ccg.andyt.grids.exchange.ImageExporter; 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.Mortality; 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.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.utilities.Time; import uk.ac.leeds.ccg.andyt.projects.genesis.utilities.ErrorHandler; /** * A class to generate a society. */ public class GenerateSociety extends ErrorHandler { private int _RandomSeed; private Environment _Environment; /** * _Population[0] is a Female HashSet * _Population[1] is a Male HashSet */ private Object[] _Population; public boolean _HandleOutOfMemoryError; public ImageExporter _ImageExporter; public String _Type; public GenerateSociety() { } public static void main(String args[]) { GenerateSociety _GenerateSociety = new GenerateSociety(); //_GenerateSociety.run0(); _GenerateSociety.run1(); //_GenerateSociety._Initialise_AndrewGeoffreyDerekTurner_Order1(); } /** * Example run producing age/gender charts at each yearly time step */ public void run0() { _RandomSeed = 0; // Initialise Environment // Calendar _Environment_Calendar; // _Environment_Calendar = Calendar.getInstance(); // _Environment_Calendar.set(20, 0, 0); // _Environment = new Environment( // new Random(_RandomSeed), // _Environment_Calendar); Time _Time; _Time = new Time(20, 0); // Initialise People _Time = new Time(0, 0); _Initialise_Population0( _Environment, _Time); //_ImageExporter = new ImageExporter(); // _Type = "PNG"; //File _File = new File("C:/temp/_Density_Map_Population." + _Type); //_Map_Population(_File, _Type, _ImageExporter); Demographics _Demographics = new Demographics(); // JFreeChart _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Calendar); // JFreeChart _JFreeChart; // _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Time); _Simulate(_Demographics, 300); } /** * Example run producing a map of locations at each day time step. */ public void run1() { _RandomSeed = 0; Time _Time = new Time(20, 0); HashSet _Grid2DSquareCells = new HashSet(); _HandleOutOfMemoryError = false; long _NRows = 100; long _NCols = 200; Grid2DSquareCellDoubleFactory _Grid2DSquareCellDoubleFactory = new Grid2DSquareCellDoubleFactory(_Grid2DSquareCells, _HandleOutOfMemoryError); 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); // Initialise People _Time = new Time(0, 0); _Initialise_Population1( _Environment, _Time); _ImageExporter = new ImageExporter(); _Type = "PNG"; File _File = new File("C:/temp/_Density_Map_Population." + _Type); _Map_Population(_File, _Type, _ImageExporter); Demographics _Demographics = new Demographics(); // JFreeChart _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Calendar); // JFreeChart _JFreeChart; // _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Time); _Simulate(_Demographics, 300); } /** * Example run producing: * age/gender plots at each year * a map of locations at each day time step * an aggregate location map for each year * * 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 run2() { _RandomSeed = 0; Time _Time = new Time(20, 0); HashSet _Grid2DSquareCells = new HashSet(); _HandleOutOfMemoryError = false; long _NRows = 100; long _NCols = 200; Grid2DSquareCellDoubleFactory _Grid2DSquareCellDoubleFactory = new Grid2DSquareCellDoubleFactory(_Grid2DSquareCells, _HandleOutOfMemoryError); 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); _Environment._Init_Resource_Grid2DSquareCellDouble(); // Initialise People _Time = new Time(0, 0); _Initialise_Population1( _Environment, _Time); _ImageExporter = new ImageExporter(); _Type = "PNG"; File _File = new File("C:/temp/_Density_Map_Population." + _Type); _Map_Population(_File, _Type, _ImageExporter); Demographics _Demographics = new Demographics(); // JFreeChart _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Calendar); // JFreeChart _JFreeChart; // _JFreeChart = _Demographics._AgeGenderPlot( // _Population, // _Environment._Time); _Simulate(_Demographics, 300); } public Time get_Random_DateOfBirth_Date( Time _Time, int _MaxYear) { int _StartYear = _Time._Year; int _Year = _Environment._Random.nextInt(_MaxYear) + _StartYear; int _Day = _Environment._Random.nextInt(Time._Normal_Days_In_Year); System.out.println("_Year " + _Year + " _Day " + _Day); return new Time(_Year, _Day); } /** * Initialises the people in a simple hunter gatherer society. * In this case there are 10 groups/bands/tribes/communities of * hunter gatherers. Each group consists of: * 0 Elders * 10 Males aged 15 * 10 Females aged 15 * 0 Children */ public void _Initialise_Population0( Environment _Environment, Time _Time) { _Population = new Object[2]; HashSet _Males = new HashSet(); HashSet _Females = new HashSet(); int _NumberOfHouseholds = 1; int _NumberOfMalesPerHousehold = 100; int _NumberOfFemalesPerHousehold = 100; int i; int _Household_int; Object _ID; Male _Male; Female _Female; //Person _Person; int _MaxYear = 15; Time _Time_Birth; //Calendar _DateOfBirth_Calendar; for (_Household_int = 0; _Household_int < _NumberOfHouseholds; _Household_int++) { Household _Household = new Household(); // Generate Females for (i = 0; i < _NumberOfFemalesPerHousehold; i++) { _ID = new Object(); _Time_Birth = get_Random_DateOfBirth_Date( _Time, _MaxYear); _Female = new Female( _Environment, _ID, _Time_Birth, _Household); _Females.add(_Female); } // Generate Males for (i = 0; i < _NumberOfMalesPerHousehold; i++) { _ID = new Object(); _Time_Birth = get_Random_DateOfBirth_Date( _Time, _MaxYear); _Male = new Male( _Environment, _ID, _Time_Birth, _Household); _Males.add(_Male); } } _Population[0] = _Females; _Population[1] = _Males; } /** * Initialises the people in a simple hunter gatherer society. * In this case there are 10 groups/bands/tribes/communities of * hunter gatherers. Each group consists of: * 0 Elders * 10 Males aged 15 * 10 Females aged 15 * 0 Children * These people are spatially located within the Environment */ public void _Initialise_Population1( Environment _Environment, Time _Time) { _Population = new Object[2]; HashSet _Males = new HashSet(); HashSet _Females = new HashSet(); int _NumberOfHouseholds = 1; int _NumberOfMalesPerHousehold = 100; int _NumberOfFemalesPerHousehold = 100; int i; int _Household_int; Object _ID; Male _Male; Female _Female; //Person _Person; int _MaxYear = 15; Time _Time_Birth; //Calendar _DateOfBirth_Calendar; for (_Household_int = 0; _Household_int < _NumberOfHouseholds; _Household_int++) { Object _Place_Location; _Place_Location = _Environment.getRandomLocation(); Household _Household = new Household(_Place_Location); // Generate Females for (i = 0; i < _NumberOfFemalesPerHousehold; i++) { _Place_Location = _Environment.getRandomLocation(); _ID = new Object(); _Time_Birth = get_Random_DateOfBirth_Date( _Time, _MaxYear); _Female = new Female( _Environment, _ID, _Time_Birth, _Household, _Place_Location); _Females.add(_Female); } // Generate Males for (i = 0; i < _NumberOfMalesPerHousehold; i++) { _Place_Location = _Environment.getRandomLocation(); _ID = new Object(); _Time_Birth = get_Random_DateOfBirth_Date( _Time, _MaxYear); _Male = new Male( _Environment, _ID, _Time_Birth, _Household, _Place_Location); _Males.add(_Male); } } _Population[0] = _Females; _Population[1] = _Males; } /** * This society has: * 200 families with 2 parents of different gender: * These have upto 5 (chosen randomly) children of random gender and age * less than 16. * These have upto 4 (chosen randomly) grandparents * * Government * 1 _Mayor * 1 _DeputyMayor * * Entertainment * 2 bars/cafe * 8 staff * * Business Organisations * 2 barber/hairdresser/beautitions * * Food * 2 Grocers * 2 owners * 10 employees * * Service Industry * 1 dump * 5 cleaners * * 1 hospital * 5 doctors * 15 nurses * 2 administrators * 1 school * 5 teachers * 50 farms * 50 farm owners * ? farmhands * 10 factories * 10 factory owners * 100 factory workers * Utilities are all provided * 1 Power plant * 1 Water power plant * 1 sewage works * * Police/Law Enforcement * 1 Jail * 2 senior police officers * 5 junior police officers * * The fire service is non existant * * There are 100 single men age 16 to 30. * There are 100 single women age 16 to 30. * * Incomplete Stub * */ public void _Initialise_Population_Year_0( Environment _Environment, Time _Time) { _Population = new Object[2]; } public static BufferedImage[] _OutputImage( JFreeChart[] tJFreeCharts, int width, int height, String directory, String outputImageFileNamePrefix, String type) throws IOException { File directoryFile = new File(directory); if (!directoryFile.exists()) { directoryFile.mkdirs(); } BufferedImage[] result = new BufferedImage[tJFreeCharts.length]; for (int i = 0; i < tJFreeCharts.length; i++) { //System.out.println("i " + i); result[i] = tJFreeCharts[i].createBufferedImage(width, height); javax.imageio.ImageIO.write( result[i], type, new File(directory, outputImageFileNamePrefix + i + "." + type)); } return result; } /** * 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); JFreeChart _JFreeChart; _JFreeChart = _Demographics._AgeGenderPlot( _Population, _Environment._Time); int _TotalBirths = 0; int _TotalBirthsInYear = 0; int _TotalDeaths = 0; int _TotalDeathsInYear = 0; int _TotalPregnancies = 0; int _TotalPregnanciesInYear = 0; int _TotalMiscarriages = 0; int _TotalMiscarriagesInYear = 0; Object[] result = new Object[2]; HashSet _Females = (HashSet) _Population[0]; HashSet _Males = (HashSet) _Population[1]; HashSet _PregnantFemales = new HashSet(); File _File; Iterator _Iterator0; Iterator _Iterator1; Female _Female; double _Fertility_double; Fertility _Fertility = new Fertility(); for (int _Year = 0; _Year < _Years; _Year++) { _TotalBirthsInYear = 0; _TotalDeathsInYear = 0; _TotalPregnanciesInYear = 0; _TotalMiscarriagesInYear = 0; for (int _Day = 0; _Day < 365; _Day++) { // Output Map _File = new File("C:/temp/_Density_Map_Population" + _Year + "_" + _Day + "." + _Type); _Map_Population(_File, _Type, _ImageExporter); // 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( _PregnantFemales, _Fertility); // Miscarriage // Does anyone miscarry today? _TotalMiscarriagesInYear += _SimulateMiscarriage( _PregnantFemales); _SimulateMovement(); _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); _JFreeChart = _Demographics._AgeGenderPlot( _Population, _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; HashSet _Females = (HashSet) _Population[0]; HashSet _Males = (HashSet) _Population[1]; Iterator _Iterator; Female _Female; Male _Male; double comparison; _Iterator = _Females.iterator(); while (_Iterator.hasNext()) { _Female = (Female) _Iterator.next(); // Only people who are not already dead can die. if (_Female._Time_Death == null) { _DailyDeathRate = _Mortality.get_AnnualMortalityLikelihood(_Female) / 365.0d; comparison = _Environment._Random.nextDouble(); //if (comparison<_FixedDailyDeathRate){ if (comparison < _DailyDeathRate) { _Female.set_Time_Death(_Environment._Time); _TotalDeaths++; //System.out.println("Death of Person " + _Female); // } else { // System.out.println("Living Person " + _Female); } } } _Iterator = _Males.iterator(); while (_Iterator.hasNext()) { _Male = (Male) _Iterator.next(); // Only people who are not already dead can die. if (_Male._Time_Death == null) { _DailyDeathRate = _Mortality.get_AnnualMortalityLikelihood(_Male) / 365.0d; comparison = _Environment._Random.nextDouble(); //if (comparison<_FixedDailyDeathRate){ if (comparison < _DailyDeathRate) { _Male.set_Time_Death(_Environment._Time); _TotalDeaths++; //System.out.println("Death of Person " + _Male); // } else { // System.out.println("Living Person " + _Male); } } } return _TotalDeaths++; } /** * @return Total number of births */ public int _SimulateBirth() { int _TotalBirths = 0; HashSet _Females = (HashSet) _Population[0]; Iterator _Iterator; Female _Female; HashSet newbornFemales = new HashSet(); _Iterator = _Females.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 { ((HashSet) _Population[1]).add(_Person); } _TotalBirths++; //System.out.println("Birth"); //} else { // System.out.println("Birth due in " + _Female._Time_DueToGiveBirth._Difference(_Environment._Time)); } } } _Females.addAll(newbornFemales); return _TotalBirths; } /** * Returns all males at _Location * @param _Location */ public HashSet getMales( Object _Location){ HashSet _MalesHashSet = (HashSet)_Population[1]; Iterator _Iterator = _MalesHashSet.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( HashSet _PregnantFemales, Fertility _Fertility) { int _TotalPregnancies = 0; HashSet _Females = (HashSet) _Population[0]; Iterator _Iterator; Female _Female; int _Age; double fertility; double comparison; _Iterator = _Females.iterator(); while (_Iterator.hasNext()) { _Female = (Female) _Iterator.next(); _Age = _Female.get_AgeInYears_int(); if (!_Female._IsPregnant() && _Female._Time_Death == null) { // 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); _PregnantFemales.add(_Female); _TotalPregnancies++; //System.out.println("Pregnancy"); } } } } return _TotalPregnancies; } /** * * @param _PregnantFemales */ public int _SimulateMiscarriage( HashSet _PregnantFemales) { int _TotalMiscarriages = 0; // Fixed chance of miscarriage double _MiscarriageProbablity = 0.0005; double comparison; Iterator _Iterator; Female _Female; _Iterator = _PregnantFemales.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"); } } _PregnantFemales.removeAll(_MiscarriedFemales); return _TotalMiscarriages; } /** * 0 1 2 * 3 4 5 * 6 7 8 * @param _Location * @param _Movement * @return A new long[] giving a row and column location relative to _Movement */ public long[] getNewLocation(long[] _Location, int _Movement) { if (_Movement == 4) { return _Location; } long[] result = new long[2]; long _NRows = _Environment._World_Grid2DSquareCellDouble.get_NRows(_HandleOutOfMemoryError); long _NCols = _Environment._World_Grid2DSquareCellDouble.get_NCols(_HandleOutOfMemoryError); if (_Movement < 3) { if (_Location[0] > 0) { result[0] = _Location[0] - 1L; } else { result[0] = _NRows - 1L; } } else { if (_Movement > 5) { if (_Location[0] == _NRows - 1) { result[0] = 0L; } else { result[0] = _Location[0] + 1L; } } else { result[0] = _Location[0]; } } if (_Movement == 0 || _Movement == 3 || _Movement == 6) { if (_Location[1] > 0) { result[1] = _Location[1] - 1L; } else { result[1] = _NCols - 1L; } } else { if (_Movement == 2 || _Movement == 5 || _Movement == 8) { if (_Location[1] == _NCols - 1) { result[1] = 0L; } else { result[1] = _Location[1] + 1L; } } else { result[1] = _Location[1]; } } return result; } /** * need to get agents moving about... * Each agent can move to any position in a 1 cell radius of their current location. */ public void _SimulateMovement() { long[] _Location; Iterator _Iterator; HashSet _Females = (HashSet) _Population[0]; Female _Female; int _Movement; _Iterator = _Females.iterator(); while (_Iterator.hasNext()) { _Female = (Female) _Iterator.next(); _Location = (long[]) _Female._Location; _Movement = _Environment._Random.nextInt(8); _Female._Location = getNewLocation(_Location, _Movement); } HashSet _Males = (HashSet) _Population[1]; Male _Male; _Iterator = _Males.iterator(); while (_Iterator.hasNext()) { _Male = (Male) _Iterator.next(); _Location = (long[]) _Male._Location; _Movement = _Environment._Random.nextInt(8); _Male._Location = getNewLocation(_Location, _Movement); } } /** * Map locations with living population. * @param _File * @param _Type * @param _ImageExporter */ public void _Map_Population( File _File, String _Type, ImageExporter _ImageExporter) { Grid2DSquareCellDouble _Denisty_Map_Population = (Grid2DSquareCellDouble) _Environment._Grid2DSquareCellDoubleFactory.create(_Environment._World_Grid2DSquareCellDouble); //long _NRows = _Denisty_Map_Population.get_NRows(_HandleOutOfMemoryError); //long _NCols = _Denisty_Map_Population.get_NCols(_HandleOutOfMemoryError); //long row; //long col; long[] _Location; Iterator _Iterator; HashSet _Females = (HashSet) _Population[0]; Female _Female; _Iterator = _Females.iterator(); while (_Iterator.hasNext()) { _Female = (Female) _Iterator.next(); if (_Female._Time_Death == null) { _Location = (long[]) _Female._Location; // _Denisty_Map_Population.addToCell( // _Location[0], _Location[1], 1.0d, _HandleOutOfMemoryError); _Denisty_Map_Population.setCell( _Location[0], _Location[1], 1.0d, _HandleOutOfMemoryError); } } HashSet _Males = (HashSet) _Population[1]; Male _Male; _Iterator = _Males.iterator(); while (_Iterator.hasNext()) { _Male = (Male) _Iterator.next(); if (_Male._Time_Death == null) { _Location = (long[]) _Male._Location; // _Denisty_Map_Population.addToCell( // _Location[0], _Location[1], 1.0d, _HandleOutOfMemoryError); _Denisty_Map_Population.setCell( _Location[0], _Location[1], 1.0d, _HandleOutOfMemoryError); } } _ImageExporter.toGreyScaleImage( _Denisty_Map_Population, _File, _Type, _HandleOutOfMemoryError); // for (row=0;row<_NRows;row++){ // for (col=0;col<_NCols;col++){ // // } // } } }