ThInf-HOME

  1. Einführung

  2. Transferfunktion f

  3. Berechnung des Phasenshifts

  4. Berechnung des Phasenflows

  5. Testbeispiel

  6. Übungsaufgaben


I-PROGRAMMIEREN1 WS 0203 - Vorlesung mit Übung
VL12: Projekt EARTHSIMULATOR1 - Erste Berechnungen


AUTHOR: Gerd Döben-Henisch
DATE OF FIRST GENERATION: Dec-10, 2002
DATE OF LAST CHANGE: Dec-18, 2002
EMAIL: Gerd Döben-Henisch



1. Einführung

Nach den Vorüberlegungen aus den vorausgehenden Vorlesung zu einer möglichen Struktur der Daten für EARTHSIMULATOR1 sowie deren Ein- und Ausgabe ist es jetzt möglich, erste Berechnungen auszuführen. Die benutzten C-Quellen liegen als folgende Dateien bereit:


START



2. Transferfunktion f


Die Überlegung zur Berechnung der Simulationswerte nimmt ihren Ausgangspunkt bei der Tatsache, dass die Berechnung der Werte den Übergang von einem Zeitpunkt t (ein bestimmtes Jahr) zu einem Folgezeitpunkt (Folgejahr) berechnet. Die Zeit (TIME) wird innerhalb der Simulation als ein Abschnitt der ganzen Zahlen betrachtet.

Zu jedem Zeitpunkt t gibt es endlich viele Populationen, die durch einen Namen (bzw. Index) eineindeutig gekennzeichnet sind. Vorläufig wird nur der Fall betrachtet, dass genau eine Population vorliegt, die den Index 'germany' besitzt.



compute
Berechnung der Werte einer Population fuer das Folgejahr



Für die Frage, wie die Übergangsfunktion (Transferfunktion) f genau zu definieren ist, muss man klären, welche Werte auf welche Weise verändert werden sollen.

Zu diesem Zweck muss man sich erinnern, dass jede Population POPx aus einer endlichen Zahl von Phasen besteht und jede Phase PHASE[i] aus einer endlichen Zahl von Parametern, die unterschiedliche Werte annehmen können. Für die nachfolgenden Überlegungen werden nur jene Parameter berücksichtigt, die für die demographischen Aspekte unmittelbar wichtig sind, d.h. wir beschränken uns bei der Untersuchung zunächst auf den Aspekt der quantitativen Bevölkerungsentwicklung.

Für die Berechnung der demographischen Entwicklung werden im folgenden zwei Annahmen gemacht:

  1. Mengenaustausch zwischen den Phasen ('Shift' genannt)


  2. Mengenzufluss und -abfluss jeder Phase, unabhängig von den Nachbarphasen ('Flow' genannt)


Der Shift zwischen den Phasen soll duch die Funktion compute_phase_shift() berechnet werden; dazu gibt es die Hilfsfunktion compute_birth().

Der Flow jeder einzelnen Phase soll duch die Funktion compute_phase_flow() berechnet werden.

Dies bedeutet, dass die Transferfunktion f realisiert wird durch eine Kombination der beiden Teilfunktionen compute_phase_shift() sowie compute_phase_flow(), also:
f = compute_phase_shift() o compute_phase_flow() (wobei 'o' die Hintereinanderausführung von zwei Funktionen bedeutet)


START



3. Berechnung des Phasenshifts


Die Berechnung des Phasen-Shifts geht davon aus, dass beim Übergang von einem Zeitpunkt t zu einem Zeitpunkt t+1 zwischen benachbarten Phasen Mengen ausgetauscht werden. Ist number die aktuelle Anzahl aller Mitglieder einer Phase, dann wird angenommen, dass nach einem Zyklus (= einem Jahr) soviele Mitglieder die Phase verlassen, soviele anteilsmässig einem Zyklus zuzurechnen wären. Da jede Phase in ihrer zeitlichen Ausprägung durch den Parameter interval mit unterem Wert interval[0] und oberem Wert interval[1] beschrieben ist, könnte man als Phasendichte (phase_density) die Diferenz dieses Intervalls annehmen und den Anteil dadurch bestimmen, dass man die absolute Zahl number durch die Phasendichte dividiert, also:
Abgabe_Anteil = number / (interval[1] - interval[0])
bzw.
shift_quantity = number / phase_density

Aufgrund dieser Annahme kann man dann drei Fälle unterscheiden:

  1. Phase 0: Zufluss von 'unterer' Phase nur durch Geburten


  2. Phase max_phase-1: zwar Zufluss von 'unten' aber keine Abgabe durch shift


  3. Phasen zwischen 0 und max_phase-1: Zufluss durch vorausgehenden Phase i-1 und Abgabe an nachfolgende Phase i+1.


Für die Umsetzung dieser Annahmen benötigt man eine Hilfsfunktion compute_birth(), um den Zufluss in Phase 0 durch Geburten berechnen zu können. Dazu ist es wichtig, festzulegen, aus welchen Teilen der Population POPx in einem Zyklus Kinder entstehen können. Für die aktuelle Simulation werden folgende (idealisierende) Annahmen gemacht:

  1. Als Quelle von Neugeborenen werden Frauen angenommen.


  2. Als Altersperiode, in der Frauen 'normalerweise' Kinder zur Welt bringen, wird das Intervall 16 - 45 gewählt, also bei vorausgesetzter Phaseneinteilung die Phasen 2-4.


  3. Die Geburtenrate kann zwischen den Phasen variieren.


Für jene Phasen, die hier einschlägig sind, gilt dann die Formel: birth = number * (percentage_women/100) * birthrate.



computeshift
Berechnung der Shift-Werte fuer jede Phase



Ein Beispiel für die Realisierung der Funktion compute_birth() ist das folgende:





/***************************
 *
 * compute_birth()
 *
 * idea: Berechnet in Abhaengigkeit von Phase, Anzahl, Proz.Frauen,
 *           Geburtenrate die Anzahl der Geburten insgesamt pro Jahr
 *
 ********************************************/

float compute_birth(struct PHASE *php, struct SIMULATION *simp){

  /* Es wird angenommen, dass als Adresse Phase[0] uebergeben wird. Die Phasen mit den
   * geburtsfaehigen Frauen werden mittels den Parametern 'low' und 'high' als
   * Offset zu Phase[0] berechnet
   */

   float birth_sum = 0;
   int i;

   for(i = simp->birth_low; i < simp->birth_high+1; i++){
     birth_sum +=  (php[i].number * (php[i].percentage_women/100.0) * php[i].birthrate);
   }

   return birth_sum;

}



In dieser Funktion müssten alle Variablen bekannt sein bis auf die Variablen birth_low und birth_high. Dies sind Variablen einer zusätzlich definierten Struktur SIMULATION, die einige Elemente enthält, die die gesamte Simulation einer Phase betreffen. Hier die Struktur SIMULATION:




struct SIMULATION {

  int max_phase;               /* Innerhalb des Rahmens COUNTRY_PHASE_NUMBER kann der
				* Benutzer eine eigene maximale Phasenzahl waehlen */
  int sim_duration;            /* Anzahl der Jahre, die durchlaufen werden sollen */
  int birth_low;               /* Phase, ab der Frauen Kinder gebaehren koennen */
  int birth_high;               /* Phase, bis zu der Frauen Kinder gebaehren koennen */

};



Die Funktion compute_birth() bekommt als Argumente zwei Adressen: eine Adresse von phase[0] sowie eine Adresse der Variablen sim vom Typ struct SIMULATION für den Pointer simp. Über den Pointer simp kann die Funktion dann auf die Elemente birth_low und birth_high zugreifen und damit bestimmen, welche Phasen zur Berechnung der Geburten herangezogen werden sollen. Mit der Adresse von phase[0] für den Pointer php kann die Funktion dann auf jene Elemente der Phasen zugreifen, mittels deren die Geburtenrate bestimmt wird.

Es folgt nun die volltändige Darstellung der Funktion compute_phase_shift():




/***************************
 *
 * compute_phase_shift()
 *
 * idea: Berechnet die Verschiebung der Populationen zwischen den
 *       Phasen, beginnend bei der hoechsten Phase
 *
 ********************************************/

int compute_phase_shift(struct PHASE *php,  struct SIMULATION *simp) {

  /* Es wird angenommen, dass als Adresse Phase[0] uebergeben wird. Andere Phasen
   * werden als Offset zu Phase[0] berechnet
   */

   int i;
   float birth;


 birth = compute_birth(php, simp);
 printf("GEBURTEN = %f\n",birth);

   i=simp->max_phase-1;

   /* Die oberste Phase gibt keine Anteile weiter, sonder bekommt nur Anteile von der unteren Phase */

     printf("TEST compute_phase_shift BEFORE %d = %f\n",i,php[i].number);
     php[i].number += php[i-1].number/(php[i-1].interval[1] - php[i-1].interval[0]);
     printf("TEST compute_phase_shift AFTER %d = %f\n",i,php[i].number);

     i--;

     while(i>0) {
     printf("TEST compute_phase_shift BEFORE %d = %f\n",i,php[i].number);
     php[i].number =  php[i].number - (php[i].number/(php[i].interval[1] - php[i].interval[0])) +  php[i-1].number/(php[i-1].interval[1] - php[i-1].interval[0]);
     printf("TEST compute_phase_shift AFTER %d = %f\n",i,php[i].number);
     i--;

   }/*End of while */

     /* Die unterste Phase gib Anteile weiter und bekommt Geburten */

  printf("TEST compute_phase_shift BEFORE %d = %f\n",i,php[i].number);
     php[i].number =  php[i].number - (php[i].number/(php[i].interval[1] - php[i].interval[0]) )+ birth;
     printf("TEST compute_phase_shift AFTER %d = %f\n",i,php[i].number);


   return (1);
}



In dieser Funktion werden also die möglichen Geburten berechnet, bevor die Phasen geshifted werden. Sie werden dann während dem Shiftprozess der Phase 0 zugerechnet. Alternativ könnte man sich vorstellen dass man die Geburten vor und nach dem Shiftprozess berechnet, dann einen Mittelwert bildet und diesen dann der Phase 0 zurechnet. Solche -und mögliche andere präzisierende Annahmen- währen im Rahmen einer empirischen Validierung im einzelnen zu untersuchen.


START



4. Berechnung des Phasenflows


Im Phasen-Flow werden jene Mengenverschiebungen zusammengefasst, die weitgehend unabhängig vom Shift-Prozess sind. Hierbei werden im ersten Modell die Parameter deathrate, migration_plus und migration_minus berücksichtigt. Mit deathrate wird die Sterberate (angegeben mit dem Intervall [1,0], 1 = 100%) angegeben bezogen auf die Gesamtheit der Mitglieder der Phase. Man kann die absolute Zahl der Sterbefälle entweder zu Beginn oder am Ende des Shiftprozesses ermitteln oder als Mittelwert. In der aktuellen Version wird sie nach dem Shiftprozess erfasst. Letzteres gilt auch für die Parameter migration_plus sowie migration_minus. Sie beschreiben die Zu- bzw. die Abwanderung. Wandern ganze Familien zu oder ab, dann können sich die verschiedenen Familienmitglieder auf unterschiedliche Phasen verteilen.



computeflow
Berechnung der Flow-Werte fuer jede Phase



Hier der Quellkode zur Flow-Berechnung:





/***************************
 *
 * compute_phase_flow()
 *
 * idea: Berechnet die Verschiebung der Populationen durch
 *       Migration und Sterbefaelle
 *
 ********************************************/

int compute_phase_flow(struct PHASE *php, int phase_max) {

  /* Es wird angenommen, dass als Adresse Phase[0] uebergeben wird. Andere Phasen
   * werden als Offset zu Phase[0] berechnet
   */

   int i;

   for(i=0; i<phase_max; i++) {
     printf("TEST compute_phase_flow BEFORE %d = %f\n",i,php[i].number);
     php[i].number += (php[i].migration_plus - php[i].migration_minus - ( php[i].number * php[i].deathrate));
     printf("TEST compute_phase_flow AFTER %d = %f\n",i,php[i].number);

   }/*End of for */

   return (1);
}




START



5. Testbeispiel


Hier ein Testbeispiel mit 4 Phasen und 20 Zyklen (Man beachte, dass es sich um eine Testversion handelt, die mehr Ausdrucke erzeugt, als später für die Anwendung wirklich notwendig sind).



********* BEGINN EINGABE ALLGEMEINER STARTWERTE  *******************


GENERAL:  Anzahl Phasen (int) (MAXIMUM = 20)
: 4
PHASE:  Max.Anzahl Phasen = 4

GENERAL:  Anzahl Durchgaenge/ Jahre (int)
: 20
PHASE:  Anzahl Durchgaenge/Jahre = 20


********* BEGINN EINGABE SPEZIELLER STARTWERTE FUER PHASE  *******************

Phasezahlen 0 - 5


*****************************************************************************

PHASE:  Anzahl Mitglieder (Vorher) = 0.00

PHASE: Anzahl Mitglieder  = 1000
PHASE:  Anzahl Mitglieder Neu = 1000.00

PHASE: Proz-Maenner Vorher (Gleitkomma) = 0.00
PHASE: Proz-Maenner (Gleitkomma) = 50
PHASE:  Proz-Maenner Neu = 50.00
PHASE:  Proz-Frauen Neu = 50.00

PHASE: Geburtenrate (Gleitkomma) = 0.00
PHASE: Geburtenrate (Gleitkomma) = 0
PHASE:  Geburtenrate Neu = 0.00

PHASE: Sterberate (Gleitkomma) = 0.00
PHASE: Sterberate (Gleitkomma) = 0.1
PHASE:  Sterberate Neu = 0.10

PHASE: Zuwanderung (Gleitkomma) = 0.00
PHASE: Zuwanderung (Gleitkomma) = 0
PHASE: Zuwanderung  Neu = 0.00

PHASE: Abwanderung (Gleitkomma) = 0.00
PHASE: Abwanderung (Gleitkomma) = 0
PHASE: Abwanderung  Neu = 0.00


********* BEGINN EINGABE SPEZIELLER STARTWERTE FUER PHASE  *******************

Phasezahlen 6 - 15


*****************************************************************************

PHASE:  Anzahl Mitglieder (Vorher) = 0.00

PHASE: Anzahl Mitglieder  = 2000
PHASE:  Anzahl Mitglieder Neu = 2000.00

PHASE: Proz-Maenner Vorher (Gleitkomma) = 0.00
PHASE: Proz-Maenner (Gleitkomma) = 50
PHASE:  Proz-Maenner Neu = 50.00
PHASE:  Proz-Frauen Neu = 50.00

PHASE: Geburtenrate (Gleitkomma) = 0.00
PHASE: Geburtenrate (Gleitkomma) = 0
PHASE:  Geburtenrate Neu = 0.00

PHASE: Sterberate (Gleitkomma) = 0.00
PHASE: Sterberate (Gleitkomma) = 0.05
PHASE:  Sterberate Neu = 0.05

PHASE: Zuwanderung (Gleitkomma) = 0.00
PHASE: Zuwanderung (Gleitkomma) = 0
PHASE: Zuwanderung  Neu = 0.00

PHASE: Abwanderung (Gleitkomma) = 0.00
PHASE: Abwanderung (Gleitkomma) = 0
PHASE: Abwanderung  Neu = 0.00


********* BEGINN EINGABE SPEZIELLER STARTWERTE FUER PHASE  *******************

Phasezahlen 16 - 25


*****************************************************************************

PHASE:  Anzahl Mitglieder (Vorher) = 0.00

PHASE: Anzahl Mitglieder  = 2000
PHASE:  Anzahl Mitglieder Neu = 2000.00

PHASE: Proz-Maenner Vorher (Gleitkomma) = 0.00
PHASE: Proz-Maenner (Gleitkomma) = 50
PHASE:  Proz-Maenner Neu = 50.00
PHASE:  Proz-Frauen Neu = 50.00

PHASE: Geburtenrate (Gleitkomma) = 0.00
PHASE: Geburtenrate (Gleitkomma) = 1.2
PHASE:  Geburtenrate Neu = 1.20

PHASE: Sterberate (Gleitkomma) = 0.00
PHASE: Sterberate (Gleitkomma) = 0.07
PHASE:  Sterberate Neu = 0.07

PHASE: Zuwanderung (Gleitkomma) = 0.00
PHASE: Zuwanderung (Gleitkomma) = 0
PHASE: Zuwanderung  Neu = 0.00

PHASE: Abwanderung (Gleitkomma) = 0.00
PHASE: Abwanderung (Gleitkomma) = 0
PHASE: Abwanderung  Neu = 0.00


********* BEGINN EINGABE SPEZIELLER STARTWERTE FUER PHASE  *******************

Phasezahlen 26 - 35


*****************************************************************************

PHASE:  Anzahl Mitglieder (Vorher) = 0.00

PHASE: Anzahl Mitglieder  = 2300
PHASE:  Anzahl Mitglieder Neu = 2300.00

PHASE: Proz-Maenner Vorher (Gleitkomma) = 0.00
PHASE: Proz-Maenner (Gleitkomma) = 45
PHASE:  Proz-Maenner Neu = 45.00
PHASE:  Proz-Frauen Neu = 55.00

PHASE: Geburtenrate (Gleitkomma) = 0.00
PHASE: Geburtenrate (Gleitkomma) = 1.0
PHASE:  Geburtenrate Neu = 1.00

PHASE: Sterberate (Gleitkomma) = 0.00
PHASE: Sterberate (Gleitkomma) = 0.15
PHASE:  Sterberate Neu = 0.15

PHASE: Zuwanderung (Gleitkomma) = 0.00
PHASE: Zuwanderung (Gleitkomma) = 0
PHASE: Zuwanderung  Neu = 0.00

PHASE: Abwanderung (Gleitkomma) = 0.00
PHASE: Abwanderung (Gleitkomma) = 0
PHASE: Abwanderung  Neu = 0.00
...

JAHR: 0 ***********************************************
POPULATION SUM = 7300.000000
GEBURTEN = 2465.000000
TEST compute_phase_shift BEFORE 3 = 2300.000000
TEST compute_phase_shift AFTER 3 = 2522.222168
TEST compute_phase_shift BEFORE 2 = 2000.000000
TEST compute_phase_shift AFTER 2 = 2000.000000
TEST compute_phase_shift BEFORE 1 = 2000.000000
TEST compute_phase_shift AFTER 1 = 1977.777832
TEST compute_phase_shift BEFORE 0 = 1000.000000
TEST compute_phase_shift AFTER 0 = 3265.000000

TEST compute_phase_flow BEFORE 0 = 3265.000000
TEST compute_phase_flow AFTER 0 = 2938.500000
TEST compute_phase_flow BEFORE 1 = 1977.777832
TEST compute_phase_flow AFTER 1 = 1878.888916
TEST compute_phase_flow BEFORE 2 = 2000.000000
TEST compute_phase_flow AFTER 2 = 1860.000000
TEST compute_phase_flow BEFORE 3 = 2522.222168
TEST compute_phase_flow AFTER 3 = 2143.888916
...

JAHR: 9 ***********************************************
POPULATION SUM = 15090.110352
GEBURTEN = 2099.083740
TEST compute_phase_shift BEFORE 3 = 1414.016235
TEST compute_phase_shift AFTER 3 = 1658.715210
TEST compute_phase_shift BEFORE 2 = 2202.291260
TEST compute_phase_shift AFTER 2 = 2553.344727
TEST compute_phase_shift BEFORE 1 = 5361.771973
TEST compute_phase_shift AFTER 1 = 5988.425781
TEST compute_phase_shift BEFORE 0 = 6112.030762
TEST compute_phase_shift AFTER 0 = 6988.708496

TEST compute_phase_flow BEFORE 0 = 6988.708496
TEST compute_phase_flow AFTER 0 = 6289.837402
TEST compute_phase_flow BEFORE 1 = 5988.425781
TEST compute_phase_flow AFTER 1 = 5689.004395
TEST compute_phase_flow BEFORE 2 = 2553.344727
TEST compute_phase_flow AFTER 2 = 2374.610596
TEST compute_phase_flow BEFORE 3 = 1658.715210
TEST compute_phase_flow AFTER 3 = 1409.907959
...

JAHR: 19 ***********************************************
POPULATION SUM = 24136.160156
GEBURTEN = 3469.404541
TEST compute_phase_shift BEFORE 3 = 1914.385498
TEST compute_phase_shift AFTER 3 = 2361.884033
TEST compute_phase_shift BEFORE 2 = 4027.487061
TEST compute_phase_shift AFTER 2 = 4552.753906
TEST compute_phase_shift BEFORE 1 = 8754.890625
TEST compute_phase_shift AFTER 1 = 9670.004883
TEST compute_phase_shift BEFORE 0 = 9439.398438
TEST compute_phase_shift AFTER 0 = 11020.922852

TEST compute_phase_flow BEFORE 0 = 11020.922852
TEST compute_phase_flow AFTER 0 = 9918.830078
TEST compute_phase_flow BEFORE 1 = 9670.004883
TEST compute_phase_flow AFTER 1 = 9186.504883
TEST compute_phase_flow BEFORE 2 = 4552.753906
TEST compute_phase_flow AFTER 2 = 4234.061035
TEST compute_phase_flow BEFORE 3 = 2361.884033
TEST compute_phase_flow AFTER 3 = 2007.601440

START


6. Übungsaufgaben

  1. Bilden sie ein Team von max.3 Mitgliedern


  2. Erstellung Sie gemeinsam einen Text mit Namen und Matr.Nr. der AutorenInnen. Abgabe einer Kopie des Textes an den Dozenten vor Beginn der Vorlesung am Di (1 Woche nach Aufgabenstellung). Falls die Aufgabe ausführbaren Programmcode enthält wäre die zusätzliche Übergabe des Quelltextes auf Diskette oder per email wünschenswert. Im Falle von Programmcode muss im Programmtext auch nochmals Name und Matr.Nr. erscheinen.


  3. Präsentation der Lösung als Team vor der gesamten Gruppe. Präsentationszeit (abhängig von der Gesamtzahl der Teams) 3-5 Min. Mögliche Punkte: 1-3 im Normalfall. (Im Falle von mehr als 1 Autor ist die ausführliche Besprechung in der Übung Voraussetzung für die Vergabe der Punkte!)


  4. Versuchen Sie in dem Text Antworten auf eine der folgenden Aufgaben zu formulieren:


    1. Erarbeiten Sie ein Konzept,wie Sie das bisher erarbeitete Programm testen koennen.


    2. Erarbeiten Sie ein Konzept,wie Sie das bisher erarbeitete Programm um eine Eingabe aus einer Textdatei ergänzen können.


    3. Erarbeiten Sie ein Konzept,wie Sie den Simulationslauf des bisher erarbeiteten Programms in einer Textdatei mitprotokollieren können, so dass man auf diese Datei mittels eines Visualisierungswerkzeuges zugreifen kann.



START